简体   繁体   English

OpenGL点光源转换不正确

[英]OpenGL Point Light not Transformed Correctly

I am working on adding basic point lighting to my LWJGL-based game engine. 我正在为基于LWJGL的游戏引擎添加基本的点光源。 I am using the OpenGL fixed-function lights for position and color, but am using shaders to do the actual lighting computations. 我正在使用OpenGL固定功能的灯光来确定位置和颜色,但是正在使用着色器来进行实际的灯光计算。 My problem is somewhere in the transformation from world-space to eye-space coordinates. 我的问题是从世界空间坐标转换到眼空间坐标。 My goal is that the light is at a fixed position relative to the world. 我的目标是使灯光相对于世界处于固定位置。 I know that when you set the position of the light, it is transformed by the OpenGL matrix stack the same way geometry is. 我知道,当您设置光源的位置时,OpenGL矩阵堆栈会以与几何图形相同的方式对其进行转换。 However, when I move the camera, the lighting changes. 但是,当我移动相机时,灯光会改变。 The function clearRenderer is called at the beginning of the render phase each frame (the GL_PROJECTION matrix is already set up): 每帧渲染阶段的开始都会调用函数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());
}

Here is the drawLights function in the Light class which is called in the code above: 这是Light类中的drawLights函数,在上面的代码中被调用:

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);
}

The vertex shader: 顶点着色器:

uniform float time;

varying vec3 normal;

void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    normal = (gl_NormalMatrix * gl_Normal);
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

And the fragment shader: 和片段着色器:

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);
}

So clearly, one of the following three things is not getting transformed properly: vertices, normals, or light position. 显然,以下三件事之一不能正确地变形:顶点,法线或浅色位置。 I know that vertices are transformed correctly, since geometry appears where it should. 我知道顶点是正确变换的,因为几何体应该出现在应有的位置。 Is there something I'm doing wrong in the frag shader when I subtract the frag coordinates from the light's position? 从灯光位置减去碎片坐标时,碎片着色器中我做错什么了吗? Or is the light position not properly translated into eye-space? 还是光线位置没有正确转换成眼空间?

Ok, fixed it. 好,修复它。 I was doing a few things wrong. 我做错了几件事。 Mainly, gl_FragCoord actually refers to a pixel position on the screen, which is not the same as eye space. 主要是gl_FragCoord实际上是指屏幕上的像素位置,它与眼睛空间不同。 So I just made a uniform variable to store the eye-space coordinate of the vertex. 因此,我只做了一个统一变量来存储顶点的眼空间坐标。 Also, light positions and normals aren't transformed by the GL_PROJECTION matrix, so I had to make sure not to transform my position variable by that. 此外,GL_PROJECTION矩阵不会变换灯光位置和法线,因此我必须确保不要以此变换我的位置变量。

Also, to set the position of the light, it's easier to just translate the GL_MODELVIEW matrix by the position and use a buffer containing 0, 0, 0, 1 as the position. 另外,要设置光源的位置,只需要按位置平移GL_MODELVIEW矩阵并使用包含0、0、0、1的缓冲区作为位置就容易了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM