LWJGL - 简单的照明

时间:2013-04-07 15:24:15

标签: opengl lwjgl lighting

我想编写一个小型的Minecraft克隆。现在我试图插入一些简单的灯光,但我的结果非常糟糕。我读了很多,我尝试了不同的解决方案,没有任何结果。

这就是我得到的东西。

初​​始化:

    GL11.glViewport(0, 0, Config.GAME_WIDTH, Config.GAME_HEIGHT);
    GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
    GL11.glLoadIdentity(); // Reset The Projection Matrix

    GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
    GL11.glLoadIdentity(); // Reset The Modelview Matrix

    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glEnable(GL11.GL_CULL_FACE);
    GL11.glFrontFace(GL11.GL_CCW);

    GL11.glLightModeli(GL11.GL_LIGHT_MODEL_LOCAL_VIEWER, GL11.GL_TRUE);
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glEnable(GL11.GL_LIGHT0);

    FloatBuffer qaAmbientLight  = floatBuffer(0.0f, 0.0f, 0.0f, 1.0f);
    FloatBuffer qaDiffuseLight  = floatBuffer(1.0f, 1.0f, 1.0f, 1.0f);
    FloatBuffer qaSpecularLight = floatBuffer(1.0f, 1.0f, 1.0f, 1.0f);

    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, qaAmbientLight);
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, qaDiffuseLight);
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, qaSpecularLight);

    FloatBuffer qaLightPosition = floatBuffer(lightPosition.x, lightPosition.y, lightPosition.z, 1.0f);
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, qaLightPosition);

所以现在每次渲染之前我都试过这个:

    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glClearColor(0.0f, 100.0f, 100.0f, 1.0f);
    GL11.glShadeModel(GL11.GL_FLAT);
    GL11.glLoadIdentity();
    FloatBuffer qaLightPosition = floatBuffer(lightPosition.x, lightPosition.y, lightPosition.z, 1.0f);
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, qaLightPosition);

    FloatBuffer ambientMaterial = floatBuffer(0.2f, 0.2f, 0.2f, 1.0f);
    FloatBuffer diffuseMaterial = floatBuffer(0.8f, 0.8f, 0.8f, 1.0f);
    FloatBuffer specularMaterial = floatBuffer(0.0f, 0.0f, 0.0f, 1.0f);


    GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, ambientMaterial);
    GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE, diffuseMaterial);
    GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, specularMaterial);
    GL11.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS, 50.0f);

当然这不是很多代码,但这完全是关于照明的。我弄错了吗?我读到OpenGL不如DirectX用于照明和阴影。

这就是它的样子:

http://img199.imageshack.us/img199/7014/testrender.png

有人可以给我一些提示,让它看起来更好看吗?

我发现一个帖子有一个很棒的块景观。 http://i.imgur.com/zIocp.jpg 它应该是这样的:)

2 个答案:

答案 0 :(得分:4)

  

有人可以给我一些提示,让它看起来更好看吗?

如果使用可编程管道,OpenGL和DirectX都不会与光照和阴影无关。法线只是另一个顶点属性,可用于照明计算。固定功能是旧的并且已弃用,因此如果您不被迫使用它,则不建议这样做。

更改为着色器并不是那么难,并且您不再受固定管道的限制;然后,您可以完全控制照明的计算方式,您可以轻松输出更多的调试信息(例如根据法线对表面进行着色)。

  

它应该是这样的:)

您发布的屏幕也显示ambient occlusion。在没有着色器的情况下实现这种效果将非常困难,而且根本不值得努力。

我自己正在做一个类似的项目;我不会提及它,如果它不是OpenSource并且是公开的。以下是样本结果:

Minicraft Screenie

您可以找到灯光着色器代码here

我会发布摘录以防止链接丢失:

float CalcDirectionalLightFactor(vec3 lightDirection, vec3 normal) {
    float DiffuseFactor = dot(normalize(normal), -lightDirection);

    if (DiffuseFactor > 0) {
        return DiffuseFactor;
    }
    else {
        return 0.0;
    }
}

vec3 DiffuseColor = Light0.Color * Light0.DiffuseIntensity * CalcDirectionalLightFactor(Light0.Direction, normal);

答案 1 :(得分:1)

Bartek的答案很好。您将想要编写自己的着色器,了解OpenGl为阴影和照明提供的内容,而不是依赖旧的,已弃用的照明模型。 glEnable(LIGHTING_AND_SHADOWING)要复杂得多。

但是,如果你只是想玩你的代码来看看颜色从二进制黑/白变化,一个可能的想法是关闭qaSpecularLight(它创建“光泽”全白高光,无法帮助你获得到“遮罩”外观)并调整glShadeModel设置以进行SMOOTH着色。

这应该有所帮助,但不会让你一直到达你的目标。按照Bartek建议的路径(或谷歌提出类似的想法)。