2

我的问题相当简单:在 LWJGL 中绘制法线会导致光源仅应用于模型,直到在初始化后手动更新它。这是照明初始化:

static Vector3f lightPosition = new Vector3f(-500f, -100f, 500f);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_LIGHT0);
GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, asFloatBuffer(new float[]{0.05f, 0.05f, 0.05f, 1f}));
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, asFloatBuffer(new float[]{1.5f, 1.5f, 1.5f, 1f}));

这是我绘制法线的代码(从 Standford Bunny 模型加载):

for (Face f : bunnyModel.faces){
Vector3f n1 = bunnyModel.normals.get((int)f.normal.x - 1);
GL11.glNormal3f(n1.x, n1.y, n1.z);
Vector3f v1 = bunnyModel.vertices.get((int)f.vertex.x - 1);
GL11.glVertex3f(v1.x, v1.y, v1.z);
Vector3f n2 = bunnyModel.normals.get((int)f.normal.y - 1);
GL11.glNormal3f(n2.x, n2.y, n2.z);
Vector3f v2 = bunnyModel.vertices.get((int)f.vertex.y - 1);
GL11.glVertex3f(v2.x, v2.y, v2.z);
Vector3f n3 = bunnyModel.normals.get((int)f.normal.z - 1);
GL11.glNormal3f(n3.x, n3.y, n3.z);
Vector3f v3 = bunnyModel.vertices.get((int)f.vertex.z - 1);
GL11.glVertex3f(v3.x, v3.y, v3.z);
}

我在这里做错了什么?当我禁用法线时,除了模型之外的所有东西都可以正常工作。但是当我启用它们时,兔子会收到光,但其他表面没有。

4

1 回答 1

2

在 OpenGL 中启用光照时,所有多边形将根据其法线进行光照。如果没有为多边形提供法线,则该对象的法线将默认为 vec3 {0, 0, 1}。基本上,启用照明,绘制模型,然后禁用照明并绘制场景的其余部分。

计算每个面的法线相当容易,这是我写的一个 getNormal() 函数:

//Feel free to use this for whatever you want, no licenses applied or anything.

//p1, p2, p3 - Vertices of triangle
public Vector3f getNormal(Vector3f p1, Vector3f p2, Vector3f p3) {

    //Create normal vector we are going to output.
    Vector3f output = new Vector3f();

    //Calculate vectors used for creating normal (these are the edges of the triangle).
    Vector3f calU = new Vector3f(p2.x-p1.x, p2.y-p1.y, p2.z-p1.z);
    Vector3f calV = new Vector3f(p3.x-p1.x, p3.y-p1.y, p3.z-p1.z);

    //The output vector is equal to the cross products of the two edges of the triangle
    output.x = calU.y*calV.z - calU.z*calV.y;
    output.y = calU.z*calV.x - calU.x*calV.z;
    output.z = calU.x*calV.y - calU.y*calV.x;

    //Return the resulting vector.
    return output.normalise();
}

[OpenGL 文档]

[另一个类似的问题]

[更多关于叉积]

但是……每张脸的法线看起来有点……不好。如果你想要一个更平滑的结果,你应该使用每个顶点法线。区别如下:

每面: 你可以看到三角形...

每个顶点: 在此处输入图像描述

确保不要将每面法线用于立方体之类的东西,立方体是平坦的,而不是弯曲的。Per-Vertex normals 将用于您希望使某些东西看起来更平滑和逼真的情况(皮肤、土豆、枕头等)。

为了计算每个顶点的法线,你基本上平均了连接多边形的所有法线,如下所示:

这是平均水平

如果您碰巧让模型看起来完全是黑色的或者面对您的部分是不可见的,请尝试颠倒将点放入 getNormal() 函数的顺序(或否定法线,错误是由于法线是向内,而不是向外)。

希望这有帮助!

于 2013-04-05T00:47:54.400 回答