2009-12-11 5 views
2

카메라 공간으로 방향 빛을 변환하는 I 조명에 대해 다음과 GLSL 코드가 있습니다어떻게 GLSL

uniform vec3 lightDir; // Parallel light 
uniform float ambient; 
uniform vec3 lightColour; 

void main() 
{ 
    gl_Position = ftransform(); 

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal); 
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); 

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity; 
} 

빛 벡터는 세계 공간에서 지정됩니다. gluLookAt을 사용하여 카메라 방향과 위치를 설정했습니다. OpenGL은 라이트 벡터가 카메라 공간에있는 것으로 가정하므로 라이트는 고정 된 방향으로 머물러 있지 않고 카메라로 이동합니다.

gluLookAt을 호출하기 전과 후에 쉐이더를 활성화하고 라이트 벡터를 설정하려고했지만 동일한 효과가 나타납니다. 라이트 벡터를 올바르게 변형하려면 정확히 무엇을해야합니까?

답변

-1

쉐이더 문제는 눈 공간 법선과 월드 스페이스 라이트가 있다는 것입니다.
잘 모르겠지만 라이트 매트릭스를 변형하여 문제를 해결해야합니다.

또는보다 효율적으로 (프로그램 코드에서) 오브젝트 공간의 광 vec를 변환 할 수 있으며, 각 법선에 대한 변환은 다시 요청되지 않습니다.

+0

나는 쉐이더에 gl_NormalMatrix에 의해 빛의 방향 광선을 곱한 시도하고 아무런 효과가 없었다. 다음과 같이 gl_ModelViewMatrix를 곱해 보았습니다. vec3 lightEyeDir = normalize (vec3 (gl_ModelViewMatrix * vec4 (-lightDir, 1.0))); 이렇게하면 확산 기여도가 완전히 사라집니다. 프로그램 코드에서 라이트 벡터를 변형하려면 어떤 변환이 필요합니까? – Aaron

+0

역 모델 행렬을 사용하여 light 디렉토리를 변환하면 모형 공간 광원을 얻어야합니다. – Tryum

+1

NormalMatrix는 ModelView 행렬의 회전 부분입니다 (변환 및 축척 없음). 빛에 곱하면 모델 회전을 적용한다는 의미입니다. – MaR

-2

쉐이더의 코드는 빛의 위치에 따라 변하지 않는 방향성 빛을 계산하므로 spotLight 또는 pointLight 함수를 사용해야합니다.

이러한 광원에 대한 쉐이더를 찾으십시오. 네가 찾을 수 없다면 나 한테 보낼거야.

2

조명을 배치 할 공간을 결정해야합니다. "표준"OpenGL을 따르고 싶다면 보기 공간입니다. shader로 전달하기 전에 뷰 매트릭스의 회전 부분으로 라이트 벡터를 회전해야합니다 (가장 간단한 해결책).

조명을 다른 공간 (접선, 객체, 세계 또는 심지어는 화면 공간 - 적용된 음영)에도 적용 할 수 있지만 다른 주제입니다. 또한 고급 사용을 위해서는 OpenGL을 잊어 버리고 모든 매트릭스 및 쉐이더 (기본 조명/변환 항목 없음)로 모든 작업을 수행해야합니다.

3

일반적인 문제가 있습니다. 온라인 GLSL 자습서에서 자주 볼 수 있습니다. 조명 값을 유니폼을 통해 전달하고 있습니다. 고정 함수 렌더링과 같이 glLight 호출을 사용하고 gl_LightSource[n]에서 값을 가져 오지 않는 이유는 무엇입니까? 차이점은 OpenGL이 뷰 공간에서 모든 것을 자동으로 변환한다는 것입니다. 주제에

void main() 
{ 
    // remember: directional lights are GL_POSITION with w = 0 
    vec3 lightDir = vec3(gl_LightSource[0].position); 
    float ambient = gl_LightSource[0].ambient; 
    vec3 lightColour = vec3(gl_LightSource[0].diffuse); 


    gl_Position = ftransform(); 

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal); 
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); 

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity; 
} 

항상 훌륭한 자원 : 항상 http://www.lighthouse3d.com/opengl/glsl/index.php?lights

그리고 유용는 GLSL 치트 치트입니다 : float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); : http://www.cs.brown.edu/courses/cs123/resources/glslQuickRef.pdf

+0

하지만이 경우에는 'position'필드의 값이 이미 빛에 벡터 (이론상 무한대의 위치) 여야하므로 광원 방향을 무효화 할 필요가 없다고 생각합니다. –

+1

조명 값을 유니폼으로 전달하는 것과 달리 glLight 호출을 사용하는 것이 더 이상 사용되지 않습니다. –

-1

내가 문제의 일부에있다 생각한다.

앰비언트 용어는 램버트 기반 쉐이더에서 내적으로 스케일링됩니다. 여기서 주변 용어는 점 내적 값보다 클 가능성이 높기 때문에 자주 사용됩니다. gl_NormalMatrix의 사용은 위에서 언급 한 것처럼 lightDir이 객체 공간에 있고 법선 벡터가 객체 공간에서 눈 좌표로 변환 되었기 때문에 문제가됩니다.

시도 :

vec3 n=normalize(normal); 
float ndotl=max(0.0, dot(n, normalize(lightDir))); 

vec3 diffuse=ambient * ndotl; 
+0

잘못되었습니다. 이제'lightDir'이 모델 공간에 있다고 가정합니다. 그리고 주위 조건은 방향성 빛이 없더라도 항상 빛을내는 속임수 용어이므로, 내적 (dot product)이 곱 해져서는 안되며, 덧붙여 져야합니다 (또는 그가했던 것처럼 빛이 충분하지 않을 때에 만 사용됩니다) . 당신이 의미하는 것은 빛의 내재적 강도입니다. 그의 경우에는 점 product로 곱하는'lightColour'에 의해 표현됩니다. –