glPushMatrix()和glBegin()之间有联系吗?

时间:2017-09-25 12:08:42

标签: c++ opengl

我正在计算很多顶点,然后使用四条带显示它们以获得3D曲面图。

我对某些顶点有一种奇怪的行为,以不可预测的方式改变颜色。我尝试修复它,巧合的是,当我在前后放置glPushMatrix()glPopMatrix时,我发现问题已经解决了。有谁知道潜在的问题是什么?我通常应该glBegin / glEnd使用推/弹吗?

这是我的工作代码:

for (int i = 1; i < vec.size(); i++) {
    glPushMatrix();
    glBegin(GL_QUAD_STRIP);
        for (int j = 0; j < vec[i].size(); j++) {
            glNormal3dv(vertex_normal[i][j]);
            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, reflectance[i][j]);
            glVertex3d(vec[i][j].x(), vec[i][j].y(),vec[i][j].z());

            glNormal3dv(vertex_normal[i-1][j]);
            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, reflectance[i-1][j]);
            glVertex3d(vec[i-1][j].x(), vec[i-1][j].y(), vec[i-1][j].z());
        }
    glEnd();
    glPopMatrix();
}

2 个答案:

答案 0 :(得分:5)

  1. 堆栈大小有限!!!

    因此vec.size()必须小于或等于 OpenGL 实现矩阵堆栈大小 - 在循环之前使用它的层。这使你的黑客有点危险。

  2. 使用glGetError

    您应该在使用的每个主要glGetError内容之后检查gl(在调试时也应用它,直到它没有返回错误为止)。还有像glIntercept这样的工具可以帮到你。它应该揭示问题的确切位置。

  3. 缺少glEnd()

    当你使用旧的api尝试在循环之前添加几次glEnd();。如果这有助于你错过glEnd();某个地方,这是新手的常见错误,因为glEnd;也是可编辑的,但什么都不做。

    在矩阵推/弹之后可以通过 OpenGL 重置,但这是我方的纯粹推测。

  4. glMaterialfv

    中调用glBegin/glEnd

    OpenGL docs州:

      

    材料参数可以随时更新。特别是,   glMaterial可以在调用glBegin和之间调用   对应的glEnd调用。如果只有一个材料参数   每个顶点都要更改,但glColorMaterial更受欢迎   glMaterial(参见glColorMaterial)。

    我会尽量避免在glMaterial内使用glBegin/glEnd,因为我的经验是糟糕的 OpenGL 实施(如英特尔)不符合规范的规格并可能导致在某些平台/情况下出现问题不常见的用法,如果现在不是,那么......

  5. 回答你的问题glBegin/glEnd不应该glPushMatrix/glPopMatrix不受glBegin/glEnd的影响,如果使用得当,则module.exports = (express) => { // Create express Router var api = express.Router(); // add routes api.route('/some_endpoint') .post((req, res) => { res.json({ message : 'some message' }) }); return api; } 不受影响(// set api as a middleware const api = require('./routes')(express); app.use('/api/v1', api); 内不允许推/弹1}}并且你不能超过堆栈限制。

答案 1 :(得分:4)

我将采取不同的立场,并说添加额外的推送和弹出应该没有区别。

在老式的OpenGL中,有几个矩阵堆栈。除了一堆操作可以修改当前位于堆栈顶部的任何操作(其中没有任何操作),还提供了push和pop。推送重复堆栈顶部的任何内容。因此,如果堆栈为A B C D,则它变为A B C D D。 Pop只会删除堆栈顶部的任何内容 - 它会将您从A B C D D带回A B C D

这给出了一个与调用堆栈完美匹配的结构。通过获取旧顶部的副本,您将继承日期更改。然后,您可以进行任何您想要的更改,然后退出,并且无论您调用的是什么都无关紧要。

这与glBeginglEnd完全正交,它只是说“开始一批几何”和“结束那批几何”。几何体受到适当堆栈顶部的当前值的影响,但实际上并没有改变该值。

所以我假设您正在遭受未定义的行为,并且发生在您的特定机器的安慰剂修复上。