【问题标题】:Polygon inside another polygon in the same plane同一平面内另一个多边形内的多边形
【发布时间】:2011-06-12 22:16:45
【问题描述】:

我的 OpenGL 代码中有一个奇怪的行为。我想在地上画一张地毯。

在下面的代码中,如果 GROUND_SIZE 大于 2071 并且 CARPET_HEIGHT 小于 0.0003,则不会绘制较小的多边形。绘制顺序不会改变生成的图像。

#include <GL/glut.h>

const int GROUND_SIZE = 3000;
const bool GROUND_FIRST = true;
const float CARPET_HEIGHT = 0.0003;

void carpet(){
    glColor3f(1.0,0.0,0.0);
    glBegin(GL_QUADS);
        glNormal3f(0,1,0);
        glVertex3f(-1.0, -1.0, CARPET_HEIGHT);
        glVertex3f( 1.0, -1.0, CARPET_HEIGHT);
        glVertex3f( 1.0,  1.0, CARPET_HEIGHT);
        glVertex3f(-1.0,  1.0, CARPET_HEIGHT);
    glEnd();
}
void ground(){
    glColor3f(0.0,0.7,0.0);
    glBegin(GL_QUADS);
        glNormal3f(0,1,0);
        glVertex3f(-GROUND_SIZE, -GROUND_SIZE, 0);
        glVertex3f( GROUND_SIZE, -GROUND_SIZE, 0);
        glVertex3f( GROUND_SIZE,  GROUND_SIZE, 0);
        glVertex3f(-GROUND_SIZE,  GROUND_SIZE, 0);
    glEnd();
}

void draw(){
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    if (GROUND_FIRST) {
        ground();
        carpet();
    }
    else {
        carpet();
        ground();
    }

    glutSwapBuffers();
}

int main(){

    int argc = 1; char* argv[] = { (char*)"" };
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
    glutInitWindowPosition(100, 50);
    glutInitWindowSize(640, 640);
    glutCreateWindow("Window");

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_DEPTH_TEST);

    glClearColor(0.0f, 1.0f, 1.0f, 1.0f);

    glutDisplayFunc(draw);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, 1, 0.1, 1000.0);
    gluLookAt(0.0, -5.0, 1.0,    0.0f, 0.0f, 1.0f,    0,0,1);

    glutMainLoop();
    return 0;
}

我想了解 OpenGL 使用的规则来决定它是否会在同一平面的另一个多边形内绘制一个多边形。

谢谢

【问题讨论】:

    标签: opengl drawing 3d polygon


    【解决方案1】:

    首先,一些代码错误。

    切勿将 gluLookAt 矩阵放入 GL_PROJECTION 矩阵中。这可能会影响您的照明。 gluLookAt 的矩阵应该是你放入 GL_MODELVIEW 的第一个矩阵。

    将 GL_MODELVIEW 矩阵设为默认矩阵也是一个好主意。也就是说,任何切换到 GL_PROJECTION(或其中一个纹理矩阵)的代码都负责在处理完另一个矩阵后立即切换回 GL_MODELVIEW。

    最后,调用 glClearDepth 和 glDepthFunc 总是好的形式。默认值(1.0 和 GL_LESS)正是您想要的,但明确说明这些东西总是好的。这样,您不必搜索规范以确保默认值是您认为的那样。

    现在,进入主要问题。

    此规则只是深度缓冲区的规则。既简单又复杂。

    首先,有两个平面的斜率。虽然它们在世界空间中肯定具有相同的斜率,但它们在投影后空间中不一定具有相同的斜率。这是由于从世界空间转换到投影后空间的各种计算中的浮点错误。

    其次,如果它们之间的 Z 差异太小,那么可能发生的情况是它们将获得相同的 Z 值应用于它们。或者,由于浮点错误,地毯的 Z 值甚至可能更小。

    我想如果你为视角设置动画,你会看到地毯平面进出视野。

    您可以做的一件简单的事情是始终在地平面之后绘制地毯,并为 glDepthFunc 使用 GL_LEQUAL。由于浮点错误,这可能无法 100% 起作用。

    下一步是使用多边形偏移。这样做是使图元的 Z 值偏向某个固定值。它的工作原理对于本次讨论来说过于技术化(如果您好奇,请查看 OpenGL 规范),但基本思想是您的 carpet 函数应该如下所示:

    glEnable(GL_POLYGON_OFFSET_FILL); //Activates polygon offsets for filled triangles.
    glPolygonOffset(0, 2); //The 2 is just for safety's sake; 1 ought to be enough.
    //Draw the carpet
    glDisable(GL_POLYGON_OFFSET_FILL); //Turn off polygon offsetting.
    

    【讨论】:

    • 我通常建议在任何矩阵运算之前设置适当的矩阵模式,而不是依赖于正确切换回来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 2022-06-22
    相关资源
    最近更新 更多