在LWJGL中绘制法线可以照明

时间:2013-04-03 02:15:58

标签: opengl lwjgl lighting

我的问题相当简单:在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);
}

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

1 个答案:

答案 0 :(得分: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 Documentation]

[Another similar question]

[More on the cross product]

但是......每张脸的法线看起来都不错......如果想要更平滑的结果,则应使用每顶点法线。这是区别:

每面: You can see the triangles...

每顶点: enter image description here

确保不要使用每面法线来处理立方体,立方体是扁平的,而不是弯曲的。 Per-Vertex法线用于你想让东西看起来更光滑逼真的情况(皮肤,土豆,枕头等)。

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

It's de average

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

希望这有帮助!