| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Программирование игр, графики и искусственного интеллекта > Множественные источники света |
| Автор: Coridas 2.12.2006, 12:34 |
| Добрый день, попытался создать шейдер для двух направленных источников света (использовал RenderMonkey), вот код: float4x4 matViewProjection; float4 lightDir1; float4 lightDir2; struct VS_INPUT { float4 Position : POSITION0; float3 normal:NORMAL0; }; struct VS_OUTPUT { float4 Position : POSITION0; float3 normal:TEXCOORD0; float4 dir1:TEXCOORD1; float4 dir2:TEXCOORD2; }; VS_OUTPUT vs_main( VS_INPUT Input ) { VS_OUTPUT Output; Output.Position = mul( matViewProjection, Input.Position ); Output.normal=Input.normal; Output.dir1=lightDir1; Output.dir2=lightDir2; return( Output ); } float4 ambientColor; float ambientPower; float4 diffuseColor1; float4 diffuseColor2; float diffusePower1; float diffusePower2; float4 ps_main(float3 normal:TEXCOORD0,float4 dir1:TEXCOORD1,float4 dir2:TEXCOORD2) : COLOR0 { return ambientPower*ambientColor+diffusePower1*diffuseColor1*dot(normalize(normal),normalize(dir1))+ diffusePower2*diffuseColor2*dot(normalize(normal),normalize(dir2)); } Но че-то не так, направления источников взаимно перпендикулярны: 1-й источник: Потом 2-й источник: Все вроде бы хорошо, но вот финальный результат, который в принципе таким не должен быть: Посмотрите, может че в шейдере напортачил, или совсем не то делаю.... |
| Автор: Bitter 2.12.2006, 21:34 |
| Я не очень разбераюсь в шейдерах, но заметил, что ты используешь формулу Id * Pd * (sm / |s||m|), где I - интенсивность освещения, Pd - собственно коэфициент диффузной составляющей, (sm / |s||m|) - косинус угла между векторами, ОДНАКО есть более правильная формула: Id * Pd * max(sm / |s||m| , 0). Дело в том, что если микрогрань направлена в сторону ОТ глаза, то скалярное произведение отрицательно и в этом случае результат должен быть равен 0. Но всё это только для диффузной составляющей. Полная же формула выглядит так: Color = Ia*Pa + Id*Pd * lambert + Is*Ps * phong^f, (^f - в степени f) где lambert - max( 0, sm/|s||m| ) phong - max ( 0, hm/|h||m|), f - подбирается эксперементально и обычно в пределах 1..200 Ia*Pa - ambient Id*Pd * lambert - diffuse Is*Ps * phong^f - specular где h=s+v; Ух... где: m - нормаль микрограни s - вектор от микрограни к источнику света v - вектор от микрограни к камере |
| Автор: Vel 16.12.2006, 15:38 |
| 2 coridas Буду проще Bittera... Для понимания немного dot(normalize(normal),normalize(dir1))+dot(normalize(normal),normalize(dir2)); Попробуй так max(0,dot(normalize(normal),normalize(dir1)))+max(0,dot(normalize(normal),normalize(dir2))); |
| Автор: Bitter 16.12.2006, 19:50 | ||
да уж... теория всегда сложна |
| Автор: Vel 17.12.2006, 01:19 |
| to Bitter Каков вопрос таков ответ,я так думаю... Хотя конечно ёсли смотреть на даный вопрос болеё обширно, так можно начать с уравнения нахождения середины триугольника, а закончить где-то в области теории света... |
| Автор: Coridas 25.12.2006, 11:55 |
| На самом деле все было очень просто, и как всегда виновата невнимательность, и недосыпание return ambientPower*ambientColor+diffusePower1*diffuseColor1*saturate(dot(normalize(normal),normalize(dir1)))+ diffusePower2*diffuseColor2*saturate(dot(normalize(normal),normalize(dir2))); всем спасибо |
| Автор: arilou 26.12.2006, 20:42 |
| Вот и хорошо, а то флейм пошел. |