ПрограммированиеФорумГрафика

HLSL Beckman Normal Distribution не получается.

#0
18:05, 25 июня 2020
+ Показать

Pixel shader:

 float3 normalDirection = normalize(i.normalDir);
float3 _WorldSpaceLightPos0 = float3(1.0,1.0,0.5);
     float3 lightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - i.posWorld.xyz,0.5));
   

     float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);

     float3 halfDirection = normalize(viewDirection+lightDirection); 

     float NdotH =  max(0.0,dot( normalDirection, halfDirection));

float roughness = 0.5;
float roughnessSqr = roughness*roughness;
    float NdotHSqr = NdotH*NdotH;
    return max(0.000001,(1.0 / (3.1415926535*roughnessSqr*NdotHSqr*NdotHSqr))
* exp((NdotHSqr-1)/(roughnessSqr*NdotHSqr)));

Должно получиться так:
Изображение
А у меня черная сфера. Нормали у сферы правильные.

#1
18:16, 25 июня 2020

ronniko
> float3 lightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - i.posWorld.xyz,0.5));
Это что-то непонятное. Разве не должно быть
float3 lightDirection = normalize( _WorldSpaceLightPos0.xyz - i.posWorld.xyz);
?

#2
18:53, 25 июня 2020

float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);

#3
18:57, 25 июня 2020

Сделал так:

float roughness = 0.58;

float3 norm = normalize(i.normal);

float3 light = float3(0.0,0.0,33.1);

float3 halfDirection = normalize(  i.worldPos.xyz + light);
float NdotH =  max(0.0,dot( norm, halfDirection));
float roughnessSqr = roughness*roughness;
float NdotHSqr = NdotH*NdotH;
float Dist = max(0.00001,(1.0 / (PI*roughnessSqr*NdotHSqr*NdotHSqr))* exp((NdotHSqr-1)/(roughnessSqr*NdotHSqr)));
return Dist;

Вот скрин что вышло.
Изображение

#4
19:02, 25 июня 2020

Сделал так:

float roughness = 0.58;
 
float3 norm = normalize(i.normal);
float3 light = float3(0.0,0.0,120.1);
 
float3 halfDirection = normalize(  i.worldPos.xyz - light);
float NdotH =  (dot( norm, halfDirection));
float roughnessSqr = roughness*roughness;
float NdotHSqr = NdotH*NdotH;
float Dist = max(0.00001,(1.0 / (PI*roughnessSqr*NdotHSqr*NdotHSqr))* exp((NdotHSqr-1)/(roughnessSqr*NdotHSqr)));
return Dist;

Вот скрин что вышло.
Изображение

#5
20:19, 25 июня 2020

Сделал еще по этой статье MrShoora https://habr.com/ru/post/326852/
Совпал результат как в его статье.

Плохо что он не написал LightPos какой. 

float GGX_Distribution(float cosThetaNH, float alpha) {
    float alpha2 = alpha * alpha;
    float NH_sqr = saturate(cosThetaNH * cosThetaNH);
    float den = NH_sqr * alpha2 + (1.0 - NH_sqr);
    return alpha2 / ( PI * den * den );
}

float roughness = 0.05;
roughness *= roughness ;
float3 norm = normalize(i.normal);
float3 light = float3(0.5,-0.5,10.0);//0.5 и -0.5 что бы пятно было по центру сферы.
float3 halfDirection = normalize(  i.worldPos.xyz - light);
float Dist = GGX_Distribution(dot(norm,halfDirection), roughness);
return Dist;
#6
20:22, 25 июня 2020

И не совсем понимаю какова роль Beckman Normal Distribution.

Такое впечатление , что здесь сочитается спекуляр и шерховатость.

И если использовать текстуру roughness то  в местах где цвет меньше 60 будет спекуляр.
А где roughness >60 спадает спекуляр.

#7
4:45, 26 июня 2020

ronniko
Эта функция описывает статистическое отклонение микронормалей от макронормали. Таким образом, на выходе мы имеем кол-во микронормалей в H направлении, которые отражают свет в источник наблюдения. Логично, что при большой шероховатости отражения распределяются равномерно, а при малой, как ты сказал, будет спекуляр.

ПрограммированиеФорумГрафика

Тема в архиве.