OpenGL点光源未正确转换

时间:2014-06-30 07:27:38

标签: java opengl camera glsl lighting

我正在为基于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);
}

很明显,以下三件事之一未正确转换:顶点,法线或光线位置。我知道顶点被正确转换,因为几何体出现在它应该的位置。当我从光线的位置减去碎片坐标时,在碎片着色器中是否存在我做错的事情?或者光线位置是否未正确转换为眼睛空间?

1 个答案:

答案 0 :(得分:0)

好的,修好了。我做错了一些事。主要地,gl_FragCoord实际上是指屏幕上的像素位置,这与眼睛空间不同。所以我只是制作了一个统一变量来存储顶点的眼睛空间坐标。此外,光位置和法线不会被GL_PROJECTION矩阵变换,所以我必须确保不要用它来变换我的位置变量。

另外,要设置灯光的位置,只需按位置转换GL_MODELVIEW矩阵,并使用包含0,0,0,1的缓冲区作为位置。