Так что я пытался реализовать модель шейдера Cook-Torrance в игрушечном проекте, над которым я работаю, и он выглядит неплохо при взгляде на правый угол : Но когда вы смотрите на мелкий угол, вы получаете яркие артефакты и обрезание.Cooker-Torrance shader отключается очень странно, когда NdotL <= 0
Отсечка происходит потому, что я проверяю, если NdotL> 0, но если я удалю его вещи начинают становиться еще более странно: цвета инвертируются, какая-то линия возникает там, где NdotL == 0 и каждый фрагмент, где NdotH < 0 становится черным, что делает его формой яйца.
Вот код шейдера:
#version 330 core
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoord;
in vec3 camPos;
in vec3 lightDir;
out vec4 color;
uniform sampler2D diffuseTexture;
uniform sampler2D glossTexture;
uniform sampler2D metalTexture;
uniform samplerCube cubemapTexture;
uniform vec3 lightPos;
float F(float ior, vec3 view, vec3 halfV) {
float F0 = abs((1.0 - ior)/(1.0 + ior));
F0 *= F0;
float VoH = dot(view,halfV);
float fresnel = F0+(1-F0) * pow(1 - VoH,5);
return fresnel;
}
float chiGGX(float v) {
return v > 0 ? 1 : 0;
}
float G(vec3 view, vec3 norm, vec3 halfV, float alpha) {
float VoH2 = clamp(dot(view,halfV),0.0,1.0);
float chi = chiGGX(VoH2/clamp(dot(view,norm),0.0,1.0));
VoH2 = VoH2 * VoH2;
float tan2 = (1-VoH2)/VoH2;
return (chi*2)/(1+sqrt(1+alpha*alpha*tan2));
}
float D(float roughness, vec3 norm, vec3 halfV) {
float NdotH = max(dot(norm, halfV), 0.0);
float r1 = 1.0/(4.0 * roughness * roughness * pow(NdotH, 4.0));
float r2 = (NdotH * NdotH - 1.0)/(roughness * roughness * NdotH * NdotH);
return r1 * exp(r2);
}
void main()
{
float gamma = 2.2f;
float roughnessValue = texture(glossTexture, TexCoord).r;
vec3 lightColor = vec3(1.0f, 0.8f, 1.0f)*4.0;
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(camPos-FragPos);
vec3 halfVector = normalize(lightDir + viewDir);
float diff = max(dot(norm, lightDir), 0.0);
float NdotL = dot(norm, lightDir);
float spec = 0;
if(NdotL > 0.0) {
spec = (F(1.45, viewDir, halfVector) * G(viewDir,norm,halfVector,roughnessValue) * D(roughnessValue,norm,halfVector))/(3.14151828 * dot(norm, viewDir) * dot(norm, lightDir));
}
vec3 specular = spec * lightColor;
vec3 ambient = vec3(0.05);
vec3 diffuse = (1 - texture(metalTexture, TexCoord).r) * diff * lightColor + ambient;
vec3 finalcolor = (diffuse * pow(texture(diffuseTexture, TexCoord).rgb, vec3(gamma))) + specular;
color = vec4(finalcolor, 1.0f);
color.rgb = pow(color.rgb, vec3(1.0/gamma));
}
Я знаю, что есть некоторые неиспользуемые значения, но это потому, что затенение еще не завершено.
Совет: вместо ручного использования гамма-коррекции фреймбуфер sRGB. Это более корректно (стандартные мониторы работают в sRGB, что совсем не просто гамма). – ybungalobill
@ybungalobill Я его реализую. Благодаря! – Gulian
На какой бумаге вы основывали свою реализацию?Ваш коэффициент G выглядит неправильно (в частности, он не зависит от шероховатости). – ybungalobill