我正在为基于LWJGL的游戏引擎添加基本点光源。我正在使用OpenGL固定功能灯来定位和颜色,但我使用着色器来进行实际的照明计算。我的问题在于从世界空间到眼睛空间坐标的转变。我的目标是光线相对于世界处于固定位置。我知道当你设置光的位置时,它会被OpenGL矩阵堆转换,就像几何一样。但是,当我移动相机时,灯光会发生变化。函数clearRenderer
在每帧的渲染阶段开始时调用(已经设置了GL_PROJECTION矩阵):
public static void clearRenderer(CameraViewpoint viewpoint) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
setupCamera3D(viewpoint);
Light.drawLights();
}
public static void setupCamera3D(CameraViewpoint viewpoint) {
Angles a = viewpoint.cameraAngle();
Vector3 pos = viewpoint.cameraPosition();
rotateZ(-a.roll);
rotateX(-a.pitch);
rotateY(-a.yaw);
translate(pos.negate());
}
以下是drawLights
类中的Light
函数,该函数在上面的代码中调用:
public static void drawLights() {
for (int i = 0; i < numLights; i++) {
lights[i].drawLight();
}
}
public void drawLight() {
FloatBuffer buff = BufferUtils.createFloatBuffer(4);
pos.store(buff); // pos is the position of the light in world-space
buff.put(1.0f);
buff.flip();
glLight(GL_LIGHT0 + index, GL_POSITION, buff);
}
顶点着色器:
uniform float time;
varying vec3 normal;
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
normal = (gl_NormalMatrix * gl_Normal);
gl_TexCoord[0] = gl_MultiTexCoord0;
}
片段着色器:
uniform float time;
uniform vec3 m_ambient;
uniform vec3 m_diffuse;
uniform vec3 m_specular;
uniform sampler2D tex;
varying vec3 normal;
void main() {
vec4 lightPos = gl_LightSource[0].position;
vec4 color = texture2D(tex, gl_TexCoord[0].st);
vec3 light = m_ambient;
float f = dot(normalize((lightPos - gl_FragCoord).xyz), normalize(normal));
f = clamp(f, 0.0, 1.0);
light += m_diffuse * f;
color.a = 1.0;
gl_FragColor = color * vec4(light, 1.0);
}
很明显,以下三件事之一未正确转换:顶点,法线或光线位置。我知道顶点被正确转换,因为几何体出现在它应该的位置。当我从光线的位置减去碎片坐标时,在碎片着色器中是否存在我做错的事情?或者光线位置是否未正确转换为眼睛空间?
答案 0 :(得分:0)
好的,修好了。我做错了一些事。主要地,gl_FragCoord实际上是指屏幕上的像素位置,这与眼睛空间不同。所以我只是制作了一个统一变量来存储顶点的眼睛空间坐标。此外,光位置和法线不会被GL_PROJECTION矩阵变换,所以我必须确保不要用它来变换我的位置变量。
另外,要设置灯光的位置,只需按位置转换GL_MODELVIEW矩阵,并使用包含0,0,0,1的缓冲区作为位置。