2011-12-07 20 views
1

我目前有一个任务是在openGL/GLSL中实现Phong照明模型。下面是我正在使用的两个着色器。问题是在片段着色器中,如果我没有将vColor添加到gl_FragColor那么整个形状都是黑色的。但是,如果我添加vColor,那么整个形状就是那种根本没有光照的颜色。我一直试图解决这个问题几个小时,现在没有运气。这是什么原因?这是在我的着色器的问题,或者在OpenGL代码中的问题?我正在使用一种材质和一种点光源,我将在着色器后显示这些光源。Phong照明模型实际上并没有照亮任何东西

编辑:如果我设置gl_FragColor = vec4(N, 1.0)那么物体看起来是这样的:

enter image description here

顶点着色器:

#version 150 

in vec4 vPosition; 
in vec3 vNormal; 

uniform mat4 vMatrix; 
uniform vec4 LightPosition; 

out vec3 fNorm; 
out vec3 fEye; 
out vec3 fLight; 

void main() { 
    fNorm = vNormal; 
    fEye = vPosition.xyz; 
    fLight = LightPosition.xyz; 

    if(LightPosition.w != 0.0) { 
    fLight = LightPosition.xyz - vPosition.xyz; 
    } 

gl_Position = vMatrix * vPosition; 
} 

片段着色器:

#version 150 

in vec3 fNorm; 
in vec3 fLight; 
in vec3 fEye; 

uniform vec4 vColor; 
uniform vec4 AmbientProduct, DiffuseProduct, SpecularProduct; 
uniform mat4 vMatrix; 
uniform vec4 LightPosition; 
uniform float Shininess; 

void main(){ 
    vec3 N = normalize(fNorm); 
    vec3 E = normalize(fEye); 
    vec3 L = normalize(fLight); 
    vec3 H = normalize(L + E); 

    vec4 ambient = AmbientProduct; 

    float Kd = max(dot(L, N), 0.0); 
    vec4 diffuse = Kd * DiffuseProduct; 

    float Ks = pow(max(dot(N, H), 0.0), Shininess); 
    vec4 specular = Ks * SpecularProduct; 
    if(dot(L,N) < 0.0) 
     specular = vec4(0.0, 0.0, 0.0, 1.0); 

    gl_FragColor = vColor + ambient + diffuse + specular; 
} 

设置材料和光:

void init() { 

    setMaterials(vec4(1.0, 0.0, 0.0, 0.0), //ambient 
      vec4(1.0, 0.8, 0.0, 1.0), //diffuse 
      vec4(1.0, 1.0, 1.0, 1.0), //specular 
      100.0); //shine 

    setLightSource(vec4(1.0, 0.0, 0.0, 1.0), //ambient 
       vec4(1.0, 0.0, 0.0, 1.0), //diffuse 
       vec4(1.0, 0.0, 0.0, 1.0), //specular 
       vec4(1.0, 2.0, 3.0, 1.0)); //position 

    setProducts(); 

    .... 
} 

/* 
* Sets the material properties for Phong lighting model. 
*/ 
void setMaterials(vec4 amb, vec4 dif, vec4 spec, GLfloat s) { 
    ambient = amb; 
    diffuse = dif; 
    specular = spec; 
    shine = s; 

    glUniform1f(vShininess, shine); 
} 

/* 
* Set light source properties. 
*/ 
void setLightSource(vec4 amb, vec4 dif, vec4 spec, vec4 pos) { 
    ambient0 = amb; 
    diffuse0 = dif; 
    specular0 = spec; 
    light0_pos = pos; 

    glUniform4fv(vLightPosition, 1, light0_pos); 
} 

/* 
* Find the products of materials components and light components. 
*/ 
void setProducts(){ 
    vec4 ambientProduct = ambient * ambient0; 
    vec4 diffuseProduct = diffuse * diffuse0; 
    vec4 specularProduct = specular * specular0; 

    glUniform4fv(vAmbientProduct, 1, ambientProduct); 
    glUniform4fv(vDiffuseProduct, 1, diffuseProduct); 
    glUniform4fv(vSpecularProduct, 1, specularProduct); 

} 
+0

编辑后,似乎很清楚,法线似乎是错误的。你有没有尝试过在很简单的东西上使用着色器,就像平面上的法线刚刚朝上或者其中一个过剩基元一样? – PeterT

+1

您需要开始通过可能性进行调试。首先,通过将这些直接写入屏幕,确保您的照明制服正确地通过。像'gl_FragColor = ambient'等等。然后通过将这些颜色写入颜色值来确保获得的法线是合理的。然后,通过写这个来看看点(N,L)是什么。等等,直到你找到停止合理的部分。 –

回答

0

你的最终组合物照明看起来不正确的:

gl_FragColor = vColor + ambient + diffuse + specular; 

这应该是这样的

gl_FragColor = vColor * (ambient + diffuse) + specular; 

即照明由对象的反射率调制。