【问题标题】:OpenGL weird results when applying normals to quads将法线应用于四边形时的 OpenGL 奇怪结果
【发布时间】:2015-03-22 17:41:13
【问题描述】:

如您所见,我的白墙上有照明问题:

以下是我用来制作一面墙的代码,我用这些代码来制作整个建筑。我只是为更简单的坐标制作了一个立方体,添加了法线,然后根据我想要使用它的位置以两种可能的方式对其进行缩放。这是代码

    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();
}

现在您可以看到存在一个问题,即相邻的两块墙具有相同的法线,因此应该是相同的颜色,对吧?但相反,墙的一部分只是更暗。出了什么问题?

【问题讨论】:

  • 您可以尝试在设置代码中添加glEnable(GL_RESCALE_NORMAL) 吗?由于您进行了缩放转换,因此您的法线将与位置一起缩放。
  • 太棒了,这正是我所需要的。我不知道规范也会得到扩展。

标签: opengl lighting normals


【解决方案1】:

使用旧的固定管道,您当前的模型视图转换将应用于您的法线。或者更准确地说,模型视图变换的左上角 3x3 子矩阵的反转置应用于法线。这是正确地将相同的变换应用于法线向量所需要的。

您需要注意的一件事是,在应用此转换后,法线可能不再被规范化。默认情况下,它们不会自动重新规范化。正如您在示例中看到的那样,非归一化法线的典型症状是错误的光照计算。

只要您的模型视图转换仅包含旋转和平移,您就无需担心。旋转不会改变向量的长度,平移部分甚至不会应用于法线。但是,如果任何其他类型的变换是模型视图矩阵的一部分,则必须在变换后对法线进行重新归一化。

有两个选项可以在转换后强制对法线进行重新归一化。如果除了旋转和平移之外,您的模型视图矩阵仅包含统一缩放,您可以使用:

glEnable(GL_RESCALE_NORMAL);

这可能比更通用的选项更有效:

glEnable(GL_NORMALIZE);

这将对法线进行完全重新归一化,适用于任何类型的转换。需要此选项的典型变换类型是非均匀缩放或剪切变换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 2013-11-16
    • 2011-04-12
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多