我的问题相当简单:在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);
}
我在这里做错了什么?当我禁用法线时,除了模型之外,照明工作正常。但是当我启用它们时,兔子会接收光线,但没有其他表面可以做到。
答案 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();
}
但是......每张脸的法线看起来都不错......如果想要更平滑的结果,则应使用每顶点法线。这是区别:
每面:
每顶点:
确保不要使用每面法线来处理立方体,立方体是扁平的,而不是弯曲的。 Per-Vertex法线用于你想让东西看起来更光滑逼真的情况(皮肤,土豆,枕头等)。
为了计算每顶点法线,你基本上平均所有连接多边形的法线,如下所示:
如果碰巧让模型看起来完全是黑色或者面向你的部分是不可见的,请尝试颠倒将点放入getNormal()函数的顺序(或者否定正常,错误是由于正常面向内,而不是向外)。
希望这有帮助!