Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Программирование игр, графики и искусственного интеллекта > Множественные источники света


Автор: 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-й источник:
user posted image
Потом 2-й источник:
user posted image
Все вроде бы хорошо, но вот финальный результат, который в принципе таким не должен быть:
user posted image

Посмотрите, может че в шейдере напортачил, или совсем не то делаю....


Автор: 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...

Для понимания немногоsmile упростим твой код
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
Цитата

Буду проще Bittera...


да уж... теория всегда сложна smile

Автор: Vel 17.12.2006, 01:19
to Bitter

Каков вопрос таков ответ,я так думаю...
Хотя конечно ёсли смотреть на даный вопрос болеё обширно, так можно начать 
с уравнения нахождения середины триугольника, а закончить где-то в области теории света... 

Автор: Coridas 25.12.2006, 11:55
На самом деле все было очень просто, и как всегда виновата невнимательность, и недосыпание smile))
return ambientPower*ambientColor+diffusePower1*diffuseColor1*saturate(dot(normalize(normal),normalize(dir1)))+
          diffusePower2*diffuseColor2*saturate(dot(normalize(normal),normalize(dir2)));

всем спасибо smile

Автор: arilou 26.12.2006, 20:42
Вот и хорошо, а то флейм пошел.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)