Я пытался реализовать физически основанный рендеринг, используя следующие ресурс. Он описывает уравнения, которые можно использовать для реализации затенения физически. Вот мой код шейдера:
#define M_PI 3.1415926535897932384626433832795
#ifdef SHADER_VERTEX
layout (location = 0) in vec3 position;
layout (location = 2) in vec3 normal;
out vec3 Position;
out vec3 Normal;
uniform mat4 model;
uniform mat4 mvp;
void main()
{
gl_Position = mvp * vec4(position, 1.0);
Position = vec3(model * vec4(position, 1.0));
Normal = vec3(model * vec4(normal, 0.0));
}
#endif
#ifdef SHADER_FRAGMENT
in vec3 Position;
in vec3 Normal;
out vec4 color;
uniform vec3 lightPos;
uniform vec3 objectColor;
uniform vec3 cameraPos;
uniform float roughness;
uniform vec3 specularColor;
vec3 D(vec3 normal, vec3 h)
{
float a2 = roughness * roughness * roughness * roughness;
float NdotH = dot(normal, h);
float x = (NdotH * NdotH) * (a2 - 1) + 1;
return vec3(a2 / (M_PI * (x * x)));
}
vec3 G1(vec3 normal, vec3 v)
{
float k = ((roughness + 1) * (roughness + 1)) / 8.0f;
float NdotV = dot(normal, v);
return vec3(NdotV / ((NdotV * (1 - k) + k)));
}
vec3 G(vec3 normal, vec3 l, vec3 v)
{
return G1(normal, l) * G1(normal, v);
}
vec3 F(vec3 v, vec3 h)
{
vec3 f0 = specularColor;
float VdotH = dot(v, h);
float exponent = (-5.55473 * VdotH - 6.98316) * VdotH;
return vec3(f0 + ((vec3(1, 1, 1) - f0) * pow(2, exponent)));
}
vec3 specular(vec3 n, vec3 l, vec3 h, vec3 v)
{
float NdotL = dot(n, l);
float NdotV = dot(n, v);
return (D(n, h) * F(v, h) * G(n, l, v)) / ((4 * NdotL * NdotV));
}
vec3 diffuse(vec3 normal, vec3 lightDir)
{
float NdotL = dot(normal, lightDir);
vec3 result = objectColor / M_PI;
return result * NdotL;
}
void main()
{
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - Position);
vec3 eyeVector = normalize(cameraPos - Position);
vec3 halfVector = normalize(lightDir + eyeVector);
color = vec4(diffuse(norm, lightDir) + specular(norm, lightDir, halfVector, eyeVector), 1.0);
}
#endif
Вот результаты:
Как видите, посередине странная белая полоса. Положение света над сферой, а камера перед сферой. Переменная шероховатости в настоящее время установлена на 0,2. Я не знаю, правильно ли я реализовал уравнения или как они должны выглядеть с параметрами, которые я передал.
Q: Что происходит, когда n
перпендикулярно l
?
vec3 specular(vec3 n, vec3 l, vec3 h, vec3 v)
{
float NdotL = dot(n, l);
float NdotV = dot(n, v);
return (D(n, h) * F(v, h) * G(n, l, v)) / ((4 * NdotL * NdotV));
}
A: Эта функция вернет 0/0, за исключением того, что вместо 0 будут ошибки округления, так что вы можете получить что угодно.
Вам нужно будет перестроить уравнение, чтобы вы нигде не получили 0/0.