2013-04-10 72 views
0

我的场景中有一个点光源。我认为它工作正常,直到我用相机从不同角度观察照亮的物体进行测试,发现光照区域在网格上移动(在我的情况下是简单平面)。我正在使用典型的ADS Phong照明方法。我将光照位置转换到客户端的相机空间,然后使用模型视图矩阵转换顶点着色器中的插值顶点。OpenGL点光源在相机旋转时移动

我的顶点着色器看起来是这样的:

#version 420 

layout(location = 0) in vec4 position; 
layout(location = 1) in vec2 uvs; 
layout(location = 2) in vec3 normal; 

uniform mat4 MVP_MATRIX; 
uniform mat4 MODEL_VIEW_MATRIX; 
uniform mat4 VIEW_MATRIX; 
uniform mat3 NORMAL_MATRIX; 

uniform vec4 DIFFUSE_COLOR; 

//======= OUTS ============// 
out smooth vec2 uvsOut; 
out flat vec4 diffuseOut; 

out vec3 Position; 
out smooth vec3 Normal; 


out gl_PerVertex 
{ 
    vec4 gl_Position; 
}; 

void main() 
{ 
    uvsOut = uvs; 
    diffuseOut = DIFFUSE_COLOR; 
    Normal = normal; 
    Position = vec3(MODEL_VIEW_MATRIX * position); 

    gl_Position = MVP_MATRIX * position; 
} 

片段着色器:

//==================== Uniforms =============================== 
struct LightInfo{ 

vec4 Lp;///light position 
vec3 Li;///light intensity 
vec3 Lc;///light color 
int Lt;///light type 

}; 

const int MAX_LIGHTS=5; 

uniform LightInfo lights[1]; 


// material props: 
uniform vec3 KD; 
uniform vec3 KA; 
uniform vec3 KS; 
uniform float SHININESS; 
uniform int num_lights; 

////ADS lighting method : 

vec3 pointlightType(int lightIndex,vec3 position , vec3 normal) { 

    vec3 n = normalize(normal); 
    vec4 lMVPos = lights[0].Lp ; // 
    vec3 s = normalize(vec3(lMVPos.xyz) - position); //surf to light 
    vec3 v = normalize(vec3(-position)); // 
    vec3 r = normalize(- reflect(s , n)); 
    vec3 h = normalize(v+s); 

    float sDotN = max(0.0 , dot(s, n)); 

    vec3 diff = KD * lights[0].Lc * sDotN ; 
    diff = clamp(diff ,0.0 ,1.0); 

    vec3 spec = vec3(0,0,0); 

    if (sDotN > 0.0) { 
     spec = KS * pow(max(0.0 ,dot(n,h)) , SHININESS); 
     spec = clamp(spec ,0.0 ,1.0); 
    } 

    return lights[0].Li * (spec+diff); 
} 

我已经研究了很多的教程,但这些都不给出了全过程透彻的解释,当谈到以转换空间。我怀疑它与相机空间有关,我将光线和顶点位置转换为。在我的情况下,视图矩阵创建为

glm::lookAt() 

它总是否定“眼睛”向量,所以它在于我的着色器中的视图矩阵否定了翻译部分。是否应该是这样?有人可以详细解释在可编程管道中它是如何正确完成的吗?我的着色器是基于书“OpenGL 4.0 Shading language cookbook”实现的。笔者似乎也使用了相机空间。但它不能正常工作,除非这是它应该工作的方式......

我只是将计算转移到了世界空间中。现在点光源仍然在现场。但是如何使用相机空间实现相同的效果?

+0

您的片段着色器是否也使用'#version 420'? – genpfault 2013-04-10 16:14:15

+0

是的,没有着色器本身的问题,所有的制服和属性都没问题。 – 2013-04-10 16:17:46

+0

看起来你并没有将自己的法线转变为相机空间(使用MV矩阵,就像你对位置做的那样)。这可能是问题吗? – 2013-04-13 13:25:46

回答

1

我确定了这个bug,它非常愚蠢。但对于那些对数学友好的人来说,这可能是有帮助的。我在着色器中的光照位置用vec3定义。现在,在客户端,它是用vec4表示。我之前每次都有效地将vec4的.w分量设置为等于零,然后再用视图矩阵进行转换。这样做,我相信,光位置向量没有得到正确的转换,并且从这个所有的光位置问题源于着色器。解决方案是保持光源位置向量的w分量始终等于1.