1

我目前正在尝试使用 glsl 和使用 Phong 模型在球体上制作镜面光照。

这就是我的片段着色器的样子:

#version 120
uniform vec4 color;
uniform vec3 sunPosition;
uniform mat4 normalMatrix;
uniform mat4 modelViewMatrix;
uniform float shininess;
// uniform vec4 lightSpecular;
// uniform vec4 materialSpecular;

varying vec3 viewSpaceNormal;
varying vec3 viewSpacePosition;

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) {
    vec3 r = -l+2*(n*l)*n;
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess);
}

void main(){
    vec3 normal = normalize(viewSpaceNormal);
    vec3 viewSpacePosition = (modelViewMatrix * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)).xyz;
    vec4 specular = calculateSpecular(sunPosition, normal, viewSpacePosition, vec4(0.3,0.3,0.3,0.3), vec4(0.3,0.3,0.3,0.3));
    gl_FragColor = color+specular;
}

sunPosition 没有移动并设置为值 (2.0f, 3.0f, -1.0f)。

问题是如果镜面反射计算正确,图像看起来什么都不是。

这是它的样子:http: //i.imgur.com/Na2C6.png

我在此代码中没有任何环境光/发射光/消散光的原因是因为我想让镜面光部分首先工作。

感谢您的帮助!

编辑:@Darcy Rayner 那不死者帮助了很多艰难,它似乎仍然是不正确的东西......

当前代码如下所示:

顶点着色器:

viewSpacePosition = (modelViewMatrix*gl_Vertex).xyz;
viewSpaceSunPosition = (modelViewMatrix*vec4(sunPosition,1)).xyz;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
viewSpaceNormal = (normalMatrix * vec4(gl_Position.xyz, 0.0)).xyz;

片段着色器:

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) {
    vec3 r = -l+2*(n*l)*n;
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess);
}

void main(){
    vec3 normal = normalize(viewSpaceNormal);
    vec3 viewSpacePosition = normalize(viewSpacePosition);
    vec3 viewSpaceSunPosition = normalize(viewSpaceSunPosition);
    vec4 specular = calculateSpecular(viewSpaceSunPosition, normal, viewSpacePosition,     vec4(0.7,0.7,0.7,1.0), vec4(0.6,0.6,0.6,1.0));
    gl_FragColor = color+specular;
}

球体看起来像这样:

-->图片链接<--

太阳位置: sunPosition = new Vector(12.0f, 15.0f, -1.0f);

4

1 回答 1

0

尽量不要使用 gl_FragCoord,因为它存储在屏幕坐标中(而且我认为通过 modelViewMatrix 对其进行转换不会将其恢复为视图坐标)。最简单的做法是,在顶点着色器中将 viewSpacePosition 设置为:

// Change gl_Vertex to whatever attribute you are using.
viewSpacePosition = (modelViewMatrix * gl_Vertex).xyz; 

这应该让您在视图坐标中获得 viewSpacePosition(即在应用投影之前)。然后,您可以继续在片段着色器中规范化 viewSpacePosition。不确定您是否将太阳矢量存储在世界坐标中,但您可能希望将其转换为视图空间,然后对其进行规范化。试一试,看看会发生什么,这些事情往往很容易出错。

于 2011-12-19T01:11:37.593 回答