2013-08-20 7 views
1

GLSL에서 퐁 쉐이딩을 구현하려하지만 스펙 큘러 구성 요소에 문제가 있습니다.GLSL 퐁 쉐이더의 이상한 스페 큘러 결과

Strange specular result

녹색광은 반사 요소이다. 빛 (점 광원)은 평면 위로 원을 그리며 이동합니다. 반 사면 강조는 항상 Y 축을 향해 안쪽을 향하게하여 빛이 회전하고 이미지에서 보듯이 확산 반사쪽으로 펼쳐집니다. 그것은 카메라의 위치에 의해 전혀 영향을받지 않는 것으로 보이고 어디서 잘못 될지 잘 모르겠습니다.

버텍스 쉐이더 코드 :

#version 330 core 

/* 
* Phong Shading with with Point Light (Quadratic Attenutation) 
*/ 

//Input vertex data 
layout(location = 0) in vec3 vertexPosition_modelSpace; 
layout(location = 1) in vec2 vertexUVs; 
layout(location = 2) in vec3 vertexNormal_modelSpace; 

//Output Data; will be interpolated for each fragment 
out vec2 uvCoords; 

out vec3 vertexPosition_cameraSpace; 
out vec3 vertexNormal_cameraSpace; 

//Uniforms 
uniform mat4 mvMatrix; 
uniform mat4 mvpMatrix; 
uniform mat3 normalTransformMatrix; 


void main() 
{ 
    vec3 normal = normalize(vertexNormal_modelSpace); 

    //Set vertices in clip space 
    gl_Position = mvpMatrix * vec4(vertexPosition_modelSpace, 1); 

    //Set output for UVs 
    uvCoords = vertexUVs; 

    //Convert vertex and normal into eye space 
    vertexPosition_cameraSpace = mat3(mvMatrix) * vertexPosition_modelSpace;  
    vertexNormal_cameraSpace = normalize(normalTransformMatrix * normal); 

} 

조각 쉐이더 코드 :

#version 330 core 

in vec2 uvCoords; 

in vec3 vertexPosition_cameraSpace; 
in vec3 vertexNormal_cameraSpace; 

//out 
out vec4 fragColor; 

//uniforms 
uniform sampler2D diffuseTex; 
uniform vec3 lightPosition_cameraSpace; 

void main() 
{ 
    const float materialAmbient = 0.025; //a touch of ambient 

    const float materialDiffuse = 0.65; 
    const float materialSpec = 0.35; 

    const float lightPower = 2.0; 
    const float specExponent = 2; 

    //--------------Set Colors and determine vectors needed for shading-----------------   

    //reflection colors- NOTE- diffuse and ambient reflections will use the texture color 
    const vec3 colorSpec = vec3(0,1,0); //Green spec color 
    vec3 diffuseColor = texture2D(diffuseTex, uvCoords).rgb; //Get color from the texture at fragment 

    const vec3 lightColor = vec3(1,1,1);  //White light 

    //Re-normalize normal vectors : after interpolation they make not be unit length any longer 
    vec3 normVertexNormal_cameraSpace = normalize(vertexNormal_cameraSpace); 

    //Set camera vec 
    vec3 viewVec_cameraSpace = normalize(-vertexPosition_cameraSpace); //Since its view space, camera at origin 

    //Set light vec 
    vec3 lightVec_cameraSpace = normalize(lightPosition_cameraSpace - vertexPosition_cameraSpace); 

    //Set reflect vect 
    vec3 reflectVec_cameraSpace = normalize(reflect(-lightVec_cameraSpace, normVertexNormal_cameraSpace));  //reflect function requires incident vec; from light to vertex 

    //----------------Find intensity of each component--------------------- 

    //Determine Light Intensity 
    float distance = abs(length(lightPosition_cameraSpace - vertexPosition_cameraSpace)); 
    float lightAttenuation = 1.0/((distance > 0) ? (distance * distance) : 1); //Quadratic 

    vec3 lightIntensity = lightPower * lightAttenuation * lightColor; 

    //Determine Ambient Component 
    vec3 ambientComp = materialAmbient * diffuseColor * lightIntensity; 

    //Determine Diffuse Component 
    float lightDotNormal = max(dot(lightVec_cameraSpace, normVertexNormal_cameraSpace), 0.0); 
    vec3 diffuseComp = materialDiffuse * diffuseColor * lightDotNormal * lightIntensity; 

    vec3 specComp = vec3(0,0,0); 
    //Determine Spec Component 
    if(lightDotNormal > 0.0) 
    { 
     float reflectDotView = max(dot(reflectVec_cameraSpace, viewVec_cameraSpace), 0.0); 
     specComp = materialSpec * colorSpec * pow(reflectDotView, specExponent) * lightIntensity; 
    } 

    //Add Ambient + Diffuse + Spec 
    vec3 phongFragRGB = ambientComp + 
      diffuseComp + 
      specComp; 

    //----------------------Putting it together----------------------- 

    //Out Frag color 
    fragColor = vec4( phongFragRGB, 1); 
} 

그냥 버텍스 쉐이더에서 볼 수있는 normalTransformMatrix 모델 뷰 행렬의 역 전치이라고 지적.

저는 카메라 공간의 모든 점, 카메라 및 반사 벡터에 대한 정점 위치에서 벡터로 설정합니다. 확산 계산의 경우 라이트 벡터와 법선 벡터의 내적을 취하고 반사 성분의 경우 반사 벡터와 뷰 벡터의 내적을 취하고 있습니다. 아마도 알고리즘에 대한 근본적인 오해가 있을까요?

처음에는 보간 후에 프래그먼트 셰이더에 입력하는 법선을 표준화하지 않았지만 정규화 할 라인을 추가해도 이미지에 영향을 미치지 않는다고 생각했습니다. 나는 어디에서 봐야할지 모르겠다.

사이트에 phong shading 질문이 많이 있지만 모든 사람들이 약간 다른 문제가있는 것으로 알고 있습니다. 누군가 내가 잘못 가고있는 곳을 볼 수 있다면 알려주십시오. 어떤 도움을 주셔서 감사합니다.

편집 : 이제 알았습니다! jozxyqk이 아래에 제안한 것처럼 정점 위치에 mat4 * vec4 연산을 수행하거나 번역 정보를 잃어 버렸습니다. 내가 처음 shader에 전달하기 전에 lightPosition_cameraSpace에 대한 OpenGL 코드에서 동일한 실수를하고 있음을 깨달을 때까지 나는 이상한 결과를 얻었습니다 (실수는 뷰 매트릭스를 mat3으로 캐스팅했음을 의미합니다). 라이트 위치 벡터를 vec4로 설정하는 대신 계산을 위해). 일단 그 라인을 편집하면 셰이더가 제대로 작동하는 것처럼 보입니다! 도와 줘서 고마워, jozxqk!

답변

2

나는 옳지 않은 두 부분을 볼 수 있습니다.

  1. 는 "vertexPosition_cameraSpace = mat3 (mvMatrix)는 * vertexPosition_modelSpace"는 mat4/vec4이어야한다 (X는, Y, Z, 1), 곱하기 그렇지는 모델 뷰 매트릭스의 변환 부분을 무시한다.

2. distance는 카메라가 아닌 카메라 기준으로 밝은 위치를 사용합니다. lightVec_cameraSpace를 대신 사용하십시오. (편집 : 중복 된 계산 누락)

+0

흠 내가 시도했을 때 개체의 조명이 개체에서 카메라까지의 거리에 따라 달라지는 장면이 있습니다. 카메라를 당기면 물체가 검게 변합니다. – StackAttack

+0

잘 작동합니다! 위의 편집을 참조하십시오. – StackAttack