1

所以我的 opengl 游戏中有几个不同的对象。如果我加载纹理或为顶点着色,我在游戏中的所有其他对象都会被赋予该纹理或它们的顶点被着色。所以,例如。我有一堆立方体,我将纹理“a”应用到。然后我有一个天空盒,我将纹理“b”应用到。如果我然后将两者都渲染出来,它们出于某种原因都具有纹理“b”。我调用glPushMatrix()并且glPopMatrix()在渲染立方体时,为什么它们具有天空盒的纹理?这是一些代码:

public void render() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glLoadIdentity();

    glRotatef(input.xrot, 1.0f, 0, 0);
    glRotatef(input.yrot, 0, 1.0f, 0);

    glTranslatef(-input.xpos, -input.ypos - 19, -input.zpos - 5);

    box.render();
    chunk.render();
    BitMapFont.drawString("X: " + (int)-input.xpos + " Y: " + (int)-input.ypos + " Z: " + (int)-input.zpos, 10, 0);
}

我的块类中的渲染方法:

public void render() {
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboV);
    glVertexPointer(vertSize, GL_FLOAT, 0, 0L);

    GL15.glBindBuffer(GL15.GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, vboT);
    glTexCoordPointer(3, GL_FLOAT, 0, 0L);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glPushMatrix();
    glDrawArrays(GL_QUADS, 0, vertSize * vertAmount * faceAmount * currentBlockCount);
    glPopMatrix();

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

然后是我的天空盒类:

public class SkyBox {

Texture tex;

int x, z, y, offSet;

public void bindTex() {
    tex.bind();
}

public SkyBox(int x, int z, int y) {
    this.x = x;
    this.z = z;
    this.y = y;
    this.offSet = 128;
    try {
        tex = TextureLoader.getTexture("PNG", new FileInputStream(new File("res/Blocks/air.png")));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void render() {

    glBegin(GL_QUADS);

    glTexCoord2f(0, 0);
    glVertex3f(x, z, y);
    glTexCoord2f(1, 0);
    glVertex3f(x + offSet, z, y);
    glTexCoord2f(1, 1);
    glVertex3f(x + offSet, z, y + offSet);
    glTexCoord2f(0, 1);
    glVertex3f(x, z, y + offSet);

    glTexCoord2f(1, 0);
    glVertex3f(x, z, y + offSet);
    glTexCoord2f(1, 0);
    glVertex3f(x + offSet, z, y + offSet);
    glTexCoord2f(1, 1);
    glVertex3f(x + offSet, z + offSet, y + offSet);
    glTexCoord2f(0, 1);
    glVertex3f(x, z + offSet, y + offSet);

    glTexCoord2f(0, 0);
    glVertex3f(x + offSet, z, y);
    glTexCoord2f(0, 1);
    glVertex3f(x + offSet, z + offSet, y);
    glTexCoord2f(1, 1);
    glVertex3f(x + offSet, z + offSet, y + offSet);
    glTexCoord2f(0, 1);
    glVertex3f(x + offSet, z, y + offSet);

    glTexCoord2f(0, 0);
    glVertex3f(x, z + offSet, y);
    glTexCoord2f(1, 0);
    glVertex3f(x, z, y);
    glTexCoord2f(1, 1);
    glVertex3f(x, z, y + offSet);
    glTexCoord2f(0, 1);
    glVertex3f(x, z + offSet, y + offSet);

    glTexCoord2f(0, 0);
    glVertex3f(x, z + offSet, y + offSet);
    glTexCoord2f(1, 0);
    glVertex3f(x + offSet, z + offSet, y + offSet);
    glTexCoord2f(1, 1);
    glVertex3f(x + offSet, z + offSet, y);
    glTexCoord2f(0, 1);
    glVertex3f(x, z + offSet, y);

    glTexCoord2f(0, 0);
    glVertex3f(x, z + offSet, y);
    glTexCoord2f(1, 0);
    glVertex3f(x + offSet, z + offSet, y);
    glTexCoord2f(1, 1);
    glVertex3f(x + offSet, z, y);
    glTexCoord2f(0, 1);
    glVertex3f(x, z, y);

    glEnd();
}

所以真的,为什么一切都搞砸了?

4

2 回答 2

2

推送和弹出活动矩阵仅此而已 - 它存储或检索矩阵。它不影响任何其他状态,例如纹理状态或其他属性。

在旧的 OpenGL API 中有推送和弹出某些渲染状态的功能(请参阅 参考资料glPushAttrib()),但这已从较新的版本中删除。

因此,您确实会被建议自己进行状态管理,因为这是当前编程模型(以及几乎任何其他渲染 API)中所期望的。还建议您停止使用您在此处依赖的其他不推荐使用的功能,例如一般的固定功能渲染管道。

于 2013-03-24T19:49:21.517 回答
0

OpenGL 是一个状态机,这意味着正确的用法如下所示:

render() {
    setTexture(textId_1)
    glPushMatrix();
        // set transformations related to this object
        drawObject_1()
    glPopMatrix();

    setTexture(textId_2)
    glPushMatrix();
        // set transformations related to this object
        drawObject_2()
    glPopMatrix();
}

如果您设置纹理(当您加载它时),那么所有对象都将是使用它的纹理。矩阵、材质等也是如此。当然,当我们谈论固定管道(OpenGL 1.5)时。在现代 OpenGL (3.+) 中,我们有更多选择。

glPushMatrix/glPopMatrix仅用于矩阵堆栈它可以保存矩阵机器人的状态不影响纹理、材料等。

于 2013-03-24T19:51:29.350 回答