Russian Qt Forum
Сентябрь 30, 2024, 10:25 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Бросить тень используя PNG с прозрачными областями  (Прочитано 4780 раз)
Majestio
Гость
« : Июнь 10, 2013, 15:46 »

Нужен алгоритм применения эффекта "тень" (а-ля Фотошоп) над непрозрачными областями PNG-картинки. Может кто видел хоть какие нить-реализации? В идеале - на Qt. Не в идеале - на любом языке.

Пример (светлосерый цвет - область прозрачности)

Есть:



Нужно:

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Июнь 10, 2013, 16:08 »

Ну а почему бы ее просто не посчитать как (в принципе) делает raytracer?
Записан
Majestio
Гость
« Ответ #2 : Июнь 10, 2013, 16:27 »

Ну а почему бы ее просто не посчитать как (в принципе) делает raytracer?

Вот и ищу алгоритм расчета. Нужно (пока) тройное наложение PNG, каждое из которых бросает тень на "предыдущий" результат.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июнь 10, 2013, 17:23 »

Вот и ищу алгоритм расчета. Нужно (пока) тройное наложение PNG, каждое из которых бросает тень на "предыдущий" результат.
Для каждого пикселя берем матрицу напр 3x3 "вверх-влево" т.е. целевой пиксель в правом нижнем углу. Псевдокод
Код:
// сколько света проникает
float light = 0;
for (int i = x - 2; i <= x; ++i)
 for (int j = y - 2; j <= y; ++j)
  light += 1 - src_pixel[i][j].alpha;  // alpha от 0 до 1
light /= 9;

// учтем альфу - непрозрачный пиксель не принимает ни тени ни backgroud,
// полностью прозрачный принимает всю
float bias = src_pixel[x][y].alpha; 
dst_pixel[x][y].color =  src_pixel[x][y].color * bias + background[x][y] * (1 - bias) *  light;  // финальный пиксель
dst_pixel[x][y].alpha = 1;
Где
src_pixel - пиксели бросающие тень (картинка с альфой)
background - картинка фона
dst_pixel - пиксель финальной картинки
x, y - целевая точка

Можно "подкрутить" - напр возвести light в степень или складывать с коэффициентами

Очень может быть что найдется какой-нибудь "GraphicsEffect" - класс делающий то же, ну "каждому - свое"
Записан
Majestio
Гость
« Ответ #4 : Июнь 10, 2013, 17:39 »

Спасибо, возьму на заметочку.

Для каждого пикселя берем матрицу напр 3x3 "вверх-влево" т.е. целевой пиксель в правом нижнем углу.

Попутно вопрос: почему 3x3?

В классических настройках есть два параметра - расстояние тени и радиус размытия. В соседнем форуме присоветовали посмотреть в сторону размытия по Гаусу, вот нашел интересный линк.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Июнь 10, 2013, 18:17 »

Попутно вопрос: почему 3x3?

В классических настройках есть два параметра - расстояние тени и радиус размытия. В соседнем форуме присоветовали посмотреть в сторону размытия по Гаусу, вот нашел интересный линк.
Ну возьмите 4х4, чем больше матрица тем плавнее тень, но и больше время счета. Не пугайтесь, это актуально с размерами десятка и больше. Расстояние - просто смещение матрицы относительно целевой точки

Под Гауссом обычно понимаются 2 вещи

а) сложение с коэффициентами (вес ближних больше по "колокольчику" Гаусса)
b) блюр сначала по строкам, потом по столбцам, что может быть заметно быстрее при больших радиусах

В принципе никто не мешает это реализовать, просто будет "развесистей" чем цикл for. Есть еще техники быстрого сложения. Напр на фазе предрасчета для каждого пикселя запоминается сумма всех значений сверху и слева от него. Тогда интеграл по любой площади находится напрямую. Но оно Вам надо лезть во все тонкости/толстости? Улыбающийся Для тени что Вы показали достаточен простейший код
Записан
Majestio
Гость
« Ответ #6 : Июнь 10, 2013, 18:49 »

Но оно Вам надо лезть во все тонкости/толстости? Улыбающийся Для тени что Вы показали достаточен простейший код

Оке, пасип, учту ... пока это все в форме интереса. На последних этапах проекта начну "разукрашивать" )
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #7 : Июнь 17, 2013, 17:41 »

Полезь в сорцы Qt в QGraphicsBlurEffect, дерни оттуда код для размытия по гауссу. Потом заменяешь в оригинале RGB пикселей на нужный цвет (как правило черный), альфу не трогаешь, размываешь эту картинку и получаешь тень.

Кстати, есть QGraphicsDropShadowEffect, его можно использовать в некоторых случаях, даже с обычными виджетами..
Записан

Гугль в помощь
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.059 секунд. Запросов: 23.