Скобки в HLSL приводят к неправильной работе функции ослабления света?
У меня есть диффузное + зеркальное уравнение в моем пиксельном шейдере, и оно работает довольно хорошо, за исключением одной проблемы:
Когда я изменяю это: затухание с плавающей точкой = 1.0f / d*d;
Для этого: затухание с плавающей точкой = 1.0f / ( d*d);
Моя модель больше не горит, а вместо этого является цветом моей окружающей интенсивности. Я нахожу это чрезвычайно странным. Причина, по которой мне нужны скобки, заключается в том, что я могу использовать другую функцию затухания, например ( 1 + 0,045*d + 0,0075*d*d).
Вот весь мой пиксельный шейдер:
void ps( in v2p input, out float4 final_color : SV_TARGET )
{
float3 ambient_intensity = float3( 0.3f, 0.3f, 0.3f );
float3 diffuse_color = float3( 0.8f, 0.8f, 0.8f);
float3 specular_color = float3( 1.0f, 1.0f , 1.0f );
float3 tmp_light;
tmp_light.x = light_vector.x;
tmp_light.y = light_vector.y;
tmp_light.z = light_vector.z;
float3 norm_light = normalize( tmp_light );
float3 tmp_pos;
tmp_pos.x = input.pos.x;
tmp_pos.y = input.pos.y;
tmp_pos.z = input.pos.z;
float3 tmp_norm;
tmp_norm.x = input.norm.x;
tmp_norm.y = input.norm.y;
tmp_norm.z = input.norm.z;
float3 tmp_cam = float3( 0.0f, 0.0f, -20.0f ); // todo: make this stuff work right in cbuffer
// light intensity
float d = distance( tmp_light, tmp_pos );
float attenuation = 1.0f / d*d;
float3 pointlight = attenuation*light_color;
// diffuse lighting
float diffuse = max( dot( tmp_norm, norm_light) , 0.0f );
float3 diffuse_final = diffuse_color*ambient_intensity + diffuse_color*pointlight*diffuse;
// specular lighting
float3 reflect_vect = 2*dot( tmp_norm, norm_light )*tmp_norm - norm_light;
float ref_max = max( dot( reflect_vect, normalize(tmp_cam) ), 0.0f );
float spec_exponent = pow ( ref_max, 1.0f );
float3 spec_final;
if( dot( tmp_norm, norm_light ) <= 0 )
{
spec_final = float3( 0.0f, 0.0f, 0.0f );
}
if( dot( tmp_norm, norm_light ) > 0 )
{
spec_final = specular_color*pointlight*spec_exponent;
}
final_color = float4( diffuse_final + spec_final, 1.0f );
}
Без скобок: http://i48.tinypic.com/357rmnq.png
С круглыми скобками: http://i45.tinypic.com/70jscy.png
1 ответ
Линия float attenuation = 1.0f / d*d;
равно float attenuation = 1.0f;
и именно поэтому вы получаете затененный объект без затухания.
Предполагая, что ваш объект находится рядом с началом координат и является небольшим по сравнению с его расстоянием до камеры, при использовании вы получаете затухание, близкое к нулю. float attenuation = 1.0f / (d*d);
, Это потому что d
вокруг 20.0
и attenuation
является 1.0 / 400.0 = 0.0025
, Таким образом, единственный видимый свет на модели - окружающий. На самом деле это правильно - точечный светильник имеет очень большое затухание и, таким образом, почти не воздействует на объект. Попробуйте другую функцию ослабления, например 1.0f / (0.003*d*d)
и вы увидите разницу.