基于物理的着色器不会产生所需的结果

时间:2014-05-18 20:24:56

标签: opengl glsl shader fragment-shader

在过去~2-3周内,我一直在学习基于物理的阴影,我无法解决我遇到的一些问题。

片段着色器

#version 430
#define PI 3.14159265358979323846

// Inputs
in vec3 inputNormal;
vec3 fNormal;

// Material
float reflectance = 1.0; // 0 to 1
float roughness = 0.5;
vec3 specularColor = vec3(1.0, 1.0, 1.0); // f0

// Values
vec3 lightVector = vec3(1, 1, 1); // Light (l)
vec3 eyeVector = vec3(2.75, 1.25, 1.25); // Camera (v)
vec3 halfVector = normalize(lightVector + eyeVector); // L + V / |L + V|

out vec4 fColor; // Output Color

// Specular Functions
vec3 D(vec3 h) // Normal Distribution Function - GGX/Trowbridge-Reitz
{
    float alpha = roughness * roughness;
    float alpha2 = alpha * alpha;
    float NoH = dot(fNormal, h);
    float finalTerm = ((NoH * NoH) * (alpha2 - 1.0) + 1.0);
    return vec3(alpha2 / (PI * (finalTerm * finalTerm)));
}
vec3 Gsub(vec3 v) // Sub Function of G
{
    float k = ((roughness + 1.0) * (roughness + 1.0)) / 8;
    return vec3(dot(fNormal, v) / ((dot(fNormal, v)) * (1.0 - k) + k));
}
vec3 G(vec3 l, vec3 v, vec3 h) // Geometric Attenuation Term - Schlick Modified (k = a/2)
{
    return Gsub(l) * Gsub(v);
}
vec3 F(vec3 v, vec3 h) // Fresnel - Schlick Modified (Spherical Gaussian Approximation)
{
    vec3 f0 = specularColor; // right?
    return f0 + (1.0 - f0) * pow(2, (-5.55473 * (dot(v, h)) - 6.98316) * (dot(v, h)));
}

vec3 specular()
{
    return (D(halfVector) * F(eyeVector, halfVector) * G(lightVector, eyeVector, halfVector)) / 4 * ((dot(fNormal, lightVector)) * (dot(fNormal, eyeVector)));
}
vec3 diffuse()
{
    float NoL = dot(fNormal, lightVector);
    vec3 result = vec3(reflectance / PI);
    return result * NoL;
}
void main()
{
    fNormal = normalize(inputNormal);
    fColor = vec4(diffuse() + specular(), 1.0);
    //fColor = vec4(D(halfVector), 1.0);
}

到目前为止,我已经能够解决一些问题,现在我得到了更好的结果。

Rendered Image

然而现在看来很明显,亮点太大了;这源于正态分布函数(镜面D)。

1 个答案:

答案 0 :(得分:5)

您对GGX / Trowbridge-Reitz的编码错误:

  

vec3 NxH = fNormal * h;

明星*表示您想要点积的术语产品

另外

  

float alphaTerm =(alpha * alpha - 1.0)+ 1.0;

不正确,因为在添加1.0之前公式将n.m乘以(alpha * alpha - 1.0)。你的公式等于alpha * alpha!

尝试:

// Specular
vec3 D(vec3 h) // Normal Distribution Function - GGX/Trowbridge-Reitz
{
    float alpha = roughness * roughness;
    float NxH = dot(fNormal,h);
    float alpha2 = alpha*alpha;
    float t = ((NxH * NxH) * (alpha2 - 1.0) + 1.0);
    return alpha2 / (PI * t * t);
}

在许多其他地方,您使用*代替dot。你需要纠正所有这些。另外,检查你的公式,很多似乎都不正确。