문제

나는 Phong 셰이딩에 대한 간단한 테스트를 작성 중이며 반사 구성 요소가 작동하도록 하기 위해 벽돌 벽에 머리를 부딪히고 있습니다.반사광이 물체의 전면과 후면 모두에 적용되는 것을 제외하면 올바르게 작동하는 것으로 보입니다.(객체 자체는 투명하며 CPU 측에서 수동으로 얼굴을 정렬합니다.)

확산 구성요소는 완벽하게 작동합니다(광원을 향하는 측면에만 표시됨). 이는 프래그먼트 셰이더에 도착하는 법선 관련 문제를 배제하는 것처럼 보입니다.

내가 이해하는 바에 따르면, 반사광 성분은 눈 벡터와 반사광 벡터 사이의 각도 cos에 비례합니다.

매우 단순하게 유지하기 위해 내 테스트 코드는 월드 공간에서 이 작업을 수행하려고 합니다.카메라 위치와 조명 벡터는 다음과 같이 하드 코딩되어 있습니다(죄송합니다). (0,0,4) 그리고 (-0.707, 0, -0.707) 각기.따라서 눈 벡터는 다음과 같습니다. (0,0,4) - fragPosition.

모델 행렬은 회전만 수행하므로 정점 셰이더는 단순히 모델 행렬에 의해 정점 법선을 변환합니다.(메모: 많은 유형의 변환이 일반적인 직교성을 유지하지 않기 때문에 이는 좋은 습관이 아닙니다.일반적으로 정규 행렬의 경우, 당신은 사용해야합니다 모델 행렬의 왼쪽 상단 3x3의 역 전치.) 일을 단순하게 유지하기 위해 조각 셰이더는 단일 부동 소수점 색상 채널에서 작동하고 반사 지수를 건너뜁니다(/지수 1 사용).

정점 셰이더:

#version 140

uniform mat4 mvpMtx;
uniform mat4 modelMtx;

in vec3 inVPos;
in vec3 inVNormal;

out vec3 normal_world;
out vec3 fragpos_world;

void main(void) {
  gl_Position = mvpMtx * vec4(inVPos, 1.0);
  normal_world = vec3(modelMtx * vec4(inVNormal, 0.0));
  fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 
}

조각 셰이더:

#version 140

uniform float
    uLightS,
    uLightD,
    uLightA;

uniform float uObjOpacity;

in vec3 normal_world, fragpos_world;
out vec4 fragOutColour;

void main(void) {

    vec3 vN = normalize(normal_world);
    vec3 vL = vec3(-0.707, 0, -0.707);

    // Diffuse:
    // refl in all directions is proportional to cos(angle between -light vector & normal)
    // i.e. proportional to -l.n
    float df = max(dot(-vL, vN), 0.0);

    // Specular:
    // refl toward eye is proportional to cos(angle between eye & reflected light vectors)
    // i.e. proportional to r.e
    vec3 vE = normalize(vec3(0, 0, 4) - fragpos_world);
    vec3 vR = reflect(vL, vN);
    float sf = max(dot(vR, vE), 0.0);

    float col = uLightA + df*uLightD + sf*uLightS;

    fragOutColour = vec4(col, col, col, uObjOpacity);

}

여기서는 오류를 찾을 수 없습니다.왜 거울 성분이 물체의 빛을 향하는 쪽뿐만 아니라 뒤쪽에도 나타나는지 설명할 수 있는 사람이 있나요?

많은 감사를 드립니다.

도움이 되었습니까?

해결책

GLSL이 있기 때문에 반사 기여도는 실제로 앞면과 뒷면에 대해 동일할 것입니다. reflect 법선의 부호에 둔감합니다.에서 이 참조:

reflect(I, N) = I - 2.0 * dot(N, I) * N

따라서 N 기호를 뒤집으면 취소되는 두 개의 빼기 기호가 나타납니다.말로하면 뭐 reflect 구성요소의 부호를 반대로 바꾸는 것입니다. I 와 같은 축에 있는 것 N.이것은 어느 방향으로 가느냐에 따라 달라지지 않습니다 N 직면하고 있습니다.

뒷면에서 반사광 구성요소를 제거하려면 명시적으로 확인해야 할 것 같습니다. dot(vE,vN).

다른 팁

바꿔보세요

fragpos_world = vec3(modelMtx * vec4(inVPos, 0.0)); 

에게

fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 

왜냐하면 http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#Homogeneous_coordinates

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top