我在白墙上遇到了问题,你可以看到:
以下是我用来制作一块墙的代码,我用这些来制作整个建筑。我只是为了更简单的坐标制作了一个立方体,添加了法线,然后根据我想要使用的地方以两种可能的方式缩放它。这是代码
private static void wallUnit(GLAutoDrawable glAutoDrawable, int param) {
GL2 gl2 = glAutoDrawable.getGL().getGL2();
gl2.glBindTexture(gl2.GL_TEXTURE_2D, 1);
if (param == 0)
gl2.glScalef(0.5f, 3f, 6f); // side wall
else
gl2.glScalef(6f, 3f, 0.5f); // front/ back walls
gl2.glBegin(gl2.GL_QUADS);
// Back face
gl2.glNormal3f(0.0f, 0.0f, -1.0f); // quad normal
gl2.glTexCoord2f(0.0f, 0.0f);
gl2.glVertex3f(-1.0f, -1.0f, -1.0f);
gl2.glTexCoord2f(2.0f, 0.0f);
gl2.glVertex3f(1.0f, -1.0f, -1.0f);
gl2.glTexCoord2f(2.0f, 2.0f);
gl2.glVertex3f(1.0f, 1f, -1.0f);
gl2.glTexCoord2f(0.0f, 2.0f);
gl2.glVertex3f(-1.0f, 1f, -1.0f);
// Bottom face
gl2.glNormal3f(1.0f, 0.0f, 0.0f); // quad normal
gl2.glTexCoord2f(0.0f, 0.0f);
gl2.glVertex3f(-1.0f, -1.0f, -1.0f);
gl2.glTexCoord2f(2.0f, 0.0f);
gl2.glVertex3f(1.0f, -1.0f, -1.0f);
gl2.glTexCoord2f(2.0f, 2.0f);
gl2.glVertex3f(1.0f, -1.0f, 1.0f);
gl2.glTexCoord2f(0.0f, 2.0f);
gl2.glVertex3f(-1.0f, -1.0f, 1.0f);
// Right side
gl2.glNormal3f(0.0f, -1.0f, 0.0f); // quad normal
gl2.glTexCoord2f(0.0f, 0.0f);
gl2.glVertex3f(1.0f, -1.0f, -1.0f);
gl2.glTexCoord2f(2.0f, 0.0f);
gl2.glVertex3f(1.0f, -1.0f, 1.0f);
gl2.glTexCoord2f(2.0f, 2.0f);
gl2.glVertex3f(1.0f, 1.0f, 1.0f);
gl2.glTexCoord2f(0.0f, 2.0f);
gl2.glVertex3f(1.0f, 1f, -1.0f);
// Top face
gl2.glNormal3f(-1.0f, 0.0f, 0.0f); // quad normal
gl2.glTexCoord2f(0.0f, 0.0f);
gl2.glVertex3f(1.0f, 1.0f, 1.0f);
gl2.glTexCoord2f(2.0f, 0.0f);
gl2.glVertex3f(1.0f, 1f, -1.0f);
gl2.glTexCoord2f(2.0f, 2.0f);
gl2.glVertex3f(-1.0f, 1f, -1.0f);
gl2.glTexCoord2f(0.0f, 2.0f);
gl2.glVertex3f(-1.0f, 1f, 1.0f);
// Left side
gl2.glNormal3f(0.0f, 1.0f, 0.0f); // quad normal
gl2.glTexCoord2f(0.0f, 0.0f);
gl2.glVertex3f(-1.0f, -1.0f, -1.0f);
gl2.glTexCoord2f(2.0f, 0.0f);
gl2.glVertex3f(-1.0f, -1.0f, 1.0f);
gl2.glTexCoord2f(2.0f, 2.0f);
gl2.glVertex3f(-1.0f, 1.0f, 1.0f);
gl2.glTexCoord2f(0.0f, 2.0f);
gl2.glVertex3f(-1.0f, 1f, -1.0f);
// Front face
gl2.glNormal3f(0.0f, 0.0f, 1.0f); // quad normal
gl2.glTexCoord2f(0.0f, 0.0f);
gl2.glVertex3f(-1.0f, -1.0f, 1.0f);
gl2.glTexCoord2f(2.0f, 0.0f);
gl2.glVertex3f(1.0f, -1.0f, 1.0f);
gl2.glTexCoord2f(2.0f, 2.0f);
gl2.glVertex3f(1.0f, 1f, 1.0f);
gl2.glTexCoord2f(0.0f, 2.0f);
gl2.glVertex3f(-1.0f, 1f, 1.0f);
gl2.glEnd();
}
现在你可以看到有一个问题,两块墙彼此相邻的法线相同,所以应该是相同的颜色,对吧?但相反,墙的一部分只是更暗。出了什么问题?
答案 0 :(得分:0)
使用旧版固定管道,您当前的模型 - 视图转换将应用于法线。或者更准确地说,模型 - 视图变换的左上3×3子矩阵的逆转置应用于法线。这正是将相同的变换正确应用于法线向量所需要的。
您需要注意的一件事是,在应用此转换后,法线可能不再被标准化。默认情况下,它们不会自动重新规范化。非标准化法线的典型症状是错误的光照计算,正如您在示例中看到的那样。
只要您的模型 - 视图转换仅包含旋转和翻译,您就无需担心。旋转不会更改矢量的长度,并且平移部分甚至不会应用于法线。但是,如果任何其他类型的变换是模型 - 视图矩阵的一部分,则法线必须在变换后重新规范化。
有两种方法可以在转换后强制重新标准化法线。如果除了旋转和平移之外,您的模型视图矩阵只包含统一缩放,您可以使用:
glEnable(GL_RESCALE_NORMAL);
这比更通用的选项更有效:
glEnable(GL_NORMALIZE);
这将执行法线的完全重新标准化,适用于任何类型的转换。需要此选项的典型转换类型是非均匀缩放或剪切变换。