Название: Объединение двух QColor Отправлено: navrocky от Июль 25, 2011, 15:07 Есть задача: надо наложить один QColor с прозрачностью поверх другого QColor, как будто происходило рисование точки одним цветом и поверх рисование точки другим цветом. Не нашел в доке функций/методов для этого. (
Сейчас вижу только один способ - самостоятельно просчитать цвет результирующей точки с учетом прозрачности. Но хотелось бы не изобретать лисапедов. Название: Re: Объединение двух QColor Отправлено: Ground от Июль 25, 2011, 15:13 Немного не понял вопроса, нужно смешать цвет до рисования?
Можно посмотреть QPainter::setCompositionMode Название: Re: Объединение двух QColor Отправлено: navrocky от Июль 25, 2011, 15:20 Да. Именно смешать два цвета, получить результирующий, при рисовании которым, результат должен совпадать с результатом последовательного рисования двумя цветами.
Название: Re: Объединение двух QColor Отправлено: Igors от Июль 26, 2011, 10:29 Да. Именно смешать два цвета, получить результирующий, при рисовании которым, результат должен совпадать с результатом последовательного рисования двумя цветами. Это неоднозначно, напр- просто интерполировать 2 цвета с учетом их alpha (порядок слагаемых не имеет значения) - второй цвет виден "сквозь" первый (здесь уже результат разный в зависимости от того кто первый) Название: Re: Объединение двух QColor Отправлено: m_ax от Июль 26, 2011, 12:32 По-моему это уже где-то обсуждалось)
То что результат будет зависеть от порядка наложения цветов, это понятно. Предлагаю такую реализацию: Код
Название: Re: Объединение двух QColor Отправлено: navrocky от Июль 26, 2011, 12:50 У меня получилось так:
Код
Основное отличие от предыдущего поста получилось в просчете альфа-канала. Название: Re: Объединение двух QColor Отправлено: Igors от Июль 26, 2011, 13:25 То что результат будет зависеть от порядка наложения цветов, это понятно. Лучше если человек скажет что ему нужноКод
Код Не пойму откуда такая велосипедо-боязнь? :) Название: Re: Объединение двух QColor Отправлено: m_ax от Июль 26, 2011, 15:54 Цитировать Не пойму откуда такая велосипедо-боязнь? Да какая там велосипедобоязнь)) У меня таблетки от велосипедофобии)Вот непонятно, зачем так накручивать: Код
И что Вы всё float, да float? qreal - это ж double. А по-поводу альфа-канала, согласен с тем, что здесь больше зависит от постановки задачи. В зависимости от желаемого поведения, короче) Название: Re: Объединение двух QColor Отправлено: Igors от Июль 27, 2011, 11:00 Да какая там велосипедобоязнь)) У меня таблетки от велосипедофобии) У Вас с велосипедами все отлично, вот только проверять нужно тщательнееКод
Вот непонятно, зачем так накручивать: Ну вообще-то это называется "взвешивать" :)Edit: кстати о птичках Код
Название: Re: Объединение двух QColor Отправлено: m_ax от Июль 27, 2011, 16:23 Цитировать Пусть clr1.alpha = 1.0f. Тогда выходной цвет должен быть = clr1 (позади полностью непрозрачного цвета ничего нового мы не увидим). А у Вас? Нет, clr1 - это цвет который кладут первым. Результирующий цвет зависит как от прозрачности этого первого clr1.alphaF() так и от прозрачности второго цвета clr2.Если у обоих цветов альфа = 1, то результирующий цвет будет соответствовать clr2, поскольку он кладётся последним и полностью закрашивает первый clr1. Название: Re: Объединение двух QColor Отправлено: Igors от Июль 27, 2011, 17:06 Нет, clr1 - это цвет который кладут первым. Результирующий цвет зависит как от прозрачности этого первого clr1.alphaF() так и от прозрачности второго цвета clr2. Если бы Вы назвали переменные как-то разумно (напр front, back) - ничего бы "дешифрировать" и пояснять не пришлось :) Непонятно причем тут "у обоих цветов" - если у переднего цвета полная alpha = 1.0f то какой цвет и alpha у "заднего" - до лампочки, сквозь совершенно непрозрачный передний все равно ничего не увидеть.Если у обоих цветов альфа = 1, то результирующий цвет будет соответствовать clr2, поскольку он кладётся последним и полностью закрашивает первый clr1. Код
// clr1 задний. 1% красного clr1.red = 1.0 clr1.alpha = 0.01 // clr2 передний, красный отсутствует clr2.red = 0.0; clr2.alpha = 0.5; r = 1.0 + (0.0 - 1.0) * 0.5 = 0.5 В итоге видимая красная компонента = 0.5 * 0.5 = 0.25 (25%). Как так если в обоих исходных красного было 1%? Опять ребенок накакал больше собственного веса :) Название: Re: Объединение двух QColor Отправлено: m_ax от Июль 27, 2011, 20:07 Цитировать В итоге видимая красная компонента = 0.5 * 0.5 = 0.25 (25%). Как так если в обоих исходных красного было 1%? Опять ребенок накакал больше собственного веса Улыбающийся Да, верно, здесь явный косяк)А как Вы себе представляете процесс смешения цветов? В смысле, какой аналогией с реальностью руководствуетесь в этом методе весов? Вот я сейчас прикинул такой вариант. Итоговый цвет это результат следующего процесса. Есть источник некоторых объектов (типа фотонов) которые характеризуются тремя значениями (r, g, b) Источник приготавлевает их в состоянии (r=1, g=1, b=1). Есть приёмник, который их принимает и может распознать значение каждой компоненты. В приёмник они попадают в результате отражения от "плёнки", причём плёнка обладает свойствами: 1) процентом отражённых "фотонов" (альфа-канал) 2) новыми компонентами r, g, b. (при условии что падающие ф. были в состоянии (1, 1, 1)). 3) прошедшие сквозь плёнку ф. не подвергаются изменению компонент. Теперь наш случай с наложением двух цветов. Пусть первый цвет - back, а накладываемый на него - front. Тогда, в рамках рассматриваемой модели итоговый цвет есть результат следующего процесса: Приёмник испускает N "фотонов" в состоянии (1, 1, 1) которые вначале падают на front - плёнку. Число отразившихся от неё ф. R1 = N*front.alphaF() которые попадают в приёмник и имеют компоненты соответствующего front - цвета. Число прошедших ф. D1 = N*(1 - front.alphaF()) которые имеют по-прежнему компоненты (1, 1, 1) и попадают на back - пластинку. Число отразившихся от неё составит: R2 = D1 * back.alphaF() после чего они попадают в приёмник. И так, в приёмнике у нас имеется R1 "фотонов" с компонентами front и R2 "фотонов" с компонентами back. Общие число испущенных ф. N. 1) Считаем итоговый альфа-канал: alpha = (R1 + R2)/N = front.alphaF() * (1 - back.alphaF()) + back.alphaF() 2) Считаем итоговый цвет: R = a1 * front.redF() + a2 * back.redF(); G = ... B = ... где a1 + a2 = 1 a1/a2 = R1/R2 т.е. a1 = front.alphaF() / (front.alphaF() + back.alphaF() * (1 - front.alphaF())) a2 = back.alphaF() * (1 - front.alphaF()) / (front.alphaF() + back.alphaF() * (1 - front.alphaF())) Вобщем это всего лишь один из вариантов, просто как аналогия некого процесса, который можно себе представить. Название: Re: Объединение двух QColor Отправлено: Igors от Июль 27, 2011, 21:19 a1 = front.alphaF() / (front.alphaF() + back.alphaF() * (1 - front.alphaF())) Теперь все верно, но записывать надо аккуратно и не лениться создавать локальные переменные.a2 = back.alphaF() * (1 - front.alphaF()) / (front.alphaF() + back.alphaF() * (1 - front.alphaF())) Если говорить о фотонах то лучше в терминах "фотонной карты". Да, действительно, изначально испускается N фотонов. Проходя через материал, цвет фотонов не изменяется, просто их разное число проходит. Если материал полностью прозрачен (alpha = 0) то все фотоны пройдут и наоборот ни один при (alpha = 1). То есть с альфой все прекрасно сходится, и мы быстро приходим к тому же численному выражению экспоненты. А вот с RGB такого нет. Если материал напр. зеленый - мы не можем сказать что, мол, он отражает зеленую компоненту а остальные пропускает - тогда бы зеленая бутылка бросала фиолетовую тень, но в жизни этого нет. Но мы всегда можем взвеситься по альфе - и в принятой модели это 100% корректно. А вообще хотя это самая популярная модель прозрачности "subtractive" (вычитающая) - не надо считать что это "корректно и единственно правильно" - это всего лишь "удобно". Материал может напр поглощать какие-то цветовые компоненты (и совсем не в терминах RGB), "отражение" - то просто так сказано, их там вида 3 только популярных и.т.д. и.т.п Название: Re: Объединение двух QColor Отправлено: m_ax от Июль 27, 2011, 21:41 Цитировать Если говорить о фотонах то лучше в терминах "фотонной карты". Да, действительно, изначально испускается N фотонов. Проходя через материал, цвет фотонов не изменяется, просто их разное число проходит. Если материал полностью прозрачен (alpha = 0) то все фотоны пройдут и наоборот ни один при (alpha = 1). То есть с альфой все прекрасно сходится, и мы быстро приходим к тому же численному выражению экспоненты. А вот с RGB такого нет. Если материал напр. зеленый - мы не можем сказать что, мол, он отражает зеленую компоненту а остальные пропускает - тогда бы зеленая бутылка бросала фиолетовую тень, но в жизни этого нет. Но мы всегда можем взвеситься по альфе - и в принятой модели это 100% корректно. На все вопросы, касательно света, ответит КЭД :)Название: Re: Объединение двух QColor Отправлено: Igors от Июль 28, 2011, 09:45 На все вопросы, касательно света, ответит КЭД :) Со своим провинциальным политехом полагаю что это "квантовая электродинамика" (поправьте если не так). Действительно, уравнение Максвелла первое что тыкается человеку в морду почти в любой статье. Вот только толку от него как от козла молока :) Есть конечно фанаты "смотрите какой прекрасный результат 640x480 и всего-навсего после 30 часов рендера!". Но в реальной жизни упрощенные CG модели рулят. Название: Re: Объединение двух QColor Отправлено: Fregloin от Июль 29, 2011, 12:26 я делал проще (не учитывая альфа канал правда)
uint32_t raw1 = color1.red()+color1.green()<<8+color1.blue()<<16; uint32_t raw2 = color2.red()+color2.green()<<8+color2.blue()<<16; uint32_t raw = raw1|raw2; result.setRed(raw & 0x000000FF); result.setGreen(raw & 0x0000FF00); result.setBlue(raw & 0x00FF0000); и такой подход работает, но вот на счет прозрачности скорее всего не сработает.. |