2013-05-17 5 views
4

GLSL에서 작동하는 간단한 확산 조명을 얻으려고합니다. 점의 배열로 전달되는 큐브를 가지고 있고 기하 도형 쉐이더 내부에서면 법선을 계산하고 있습니다 (실행시 메쉬를 변형하려고하므로 새면 법선이 필요합니다)조각 카메라 위치/회전에 따라 달라지는 확산 값

제 문제는 카메라를 전세계로 이동시킬 때 확산 값이 변하는 것입니다. 그래서 카메라가 움직이면서 제 큐브 얼굴의 음영이 바뀝니다. 나는 이것이 무엇을 놓치고 있는지 알아낼 수 없었다.

정점을 : 다음과 같이 내 쉐이더은

#version 330 core 

layout(location = 0) in vec3 vertexPosition_modelspace; 

uniform mat4 MVP; 

void main(){  
    gl_Position = MVP * vec4(vertexPosition_modelspace,1); 
} 

기하학 :

#version 330 

precision highp float; 

layout (triangles) in; 
layout (triangle_strip) out; 
layout (max_vertices = 3) out; 

out vec3 normal; 
uniform mat4 MVP; 
uniform mat4 MV; 

void main(void) 
{ 
    for (int i = 0; i < gl_in.length(); i++) { 
     gl_Position = gl_in[i].gl_Position; 


     vec3 U = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz; 
     vec3 V = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz; 

     normal.x = (U.y * V.z) - (U.z * V.y); 
     normal.y = (U.z * V.x) - (U.x * V.z); 
     normal.z = (U.x * V.y) - (U.y * V.x); 

     normal = normalize(transpose(inverse(MV)) * vec4(normal,1)).xyz; 

     EmitVertex(); 
    } 
    EndPrimitive(); 
} 

조각 :

#version 330 core 

in vec3 normal; 
out vec4 out_color; 
const vec3 lightDir = vec3(-1,-1,1); 

uniform mat4 MV; 

void main() 
{ 
    vec3 nlightDir = normalize(vec4(lightDir,1)).xyz; 
    float diffuse = clamp(dot(nlightDir,normal),0,1); 

    out_color = vec4(diffuse*vec3(0,1,0),1.0); 
} 

감사

답변

8

잘못된 일을 많이가 있습니다 당신의 코드. 대부분의 문제는 다양한 벡터가 들어있는 공간을 완전히 잊어 버린 것에 기인합니다. 다른 공간에있는 벡터 간에는 의미있는 계산을 할 수 없습니다.

normal = normalize(transpose(inverse(MV)) * vec4(normal,1)).xyz; 

정상의 네 번째 구성 요소로 1을 사용하면이 계산을 완전히 중단 할 수 있습니다. 정상으로 인해 으로 변환되며 이는 적절하지 않습니다.

또한 normal 값은 gl_Position을 기반으로 계산됩니다. gl_Position클립 공간에 있으며 모형 공간이 아닙니다. 그래서 당신이 얻는 것은 clip-space 정상입니다. 이것은 당신이 필요로하거나, 원하거나 사용할 수있는 것이 아닙니다.

카메라 공간 법선을 계산하려면 카메라 공간 위치에서 계산하십시오. 또는 모형 공간 위치로부터 모형 공간 법선을 계산하고 모형 /보기 행렬을 사용하여 카메라 공간으로 변환합니다.

또한 CPU에서 역변환을 수행하고 셰이더로 전달하십시오. 아, 모든 정상적인 계산을 루프에서 제거하십시오. 삼각형 당 한 번만 수행하면됩니다 (로컬 변수에 저장하고 각 정점의 출력에 복사). 수동으로 교차 제품을 중지하십시오. 내장 GLSL cross 기능을 사용하십시오.

vec3 nlightDir = normalize(vec4(lightDir,1)).xyz; 

이전에는 변환에서 네 번째 구성 요소로 1을 사용하는 것보다 의미가 없습니다. 그냥 lightDir 정상화. 당신이 카메라 공간에 조명을 수행하는 경우

은 마찬가지로 중요한 것은, 다음, 빛의 방향은이 세계에서 같은 명백한 방향으로 유지하기 위해 카메라와 함께 변경해야합니다. 따라서 여러분은 월드 와이드 라이트 라이트 포지션을 취하여 카메라 공간 (일반적으로 유니폼으로 전달 된 CPU)으로 변환해야합니다.