2015-01-16 2 views
1

다음과 같은 방법을 사용하여 물리적 기반 렌더링을 구현하려고 시도했습니다. resource. 물리적 기반 음영을 구현하는 데 사용할 수있는 방정식을 설명합니다. Image물리적 기반 렌더링 결과가 올바르게 보이지 않음

당신이 볼 수 있듯이, 중간에 이상한 흰색 밴드가 :

#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로 설정됩니다. 내가 잘못 방정식을 구현하거나이 내가 전달 된 매개 변수를 같이하도록되어 무엇을 나도 몰라

+0

아마 솔기가 있을까요? –

+0

코드가 π과 같은 값을 갖는'M_PI '에 의존하는 것처럼 보입니다. 그것은 둥근에서 솔기를 닮았다. –

+0

어떻게이 문제를 해결할 수 있습니까? 반올림으로 인한 문제가있을 것이라고 생각하지 않았습니다. 방정식을 사용하는 방식에 문제가 있습니까? 숫자가 음수가 아닌지 확인하기 위해 모든 점 제품에 max 함수를 사용하여 시도했는데 흰색 밴드를 제거한 것처럼 보였지만 수학적으로 올바른지는 알 수 없습니다. – theonewhoknocks

답변

0

Q :. 어떤 일이 발생 nl에 수직 인 경우?

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으로 끝나지 않도록 방정식을 다시 정렬해야합니다.

+0

나는 본다. 분모에 정말 작은 값을 추가하여 0으로 나누지 않으며 결과가 더 좋도록 변경했습니다. 도와 주셔서 감사합니다. – theonewhoknocks

+0

분모가 약간 음수이면 실패하지 않습니까? –

+0

max 함수를 사용하여 도트 곱을 절대 음수가되도록 만들었으므로 분모는 결코 음수가 아니어야합니다. 나는 그 점들이 어쨌든 결코 부정적인 제품이 될 것이라고 생각하지 않았습니다. 그것이 맞는지 나는 모른다. – theonewhoknocks