在PyOpenGL中绘制透明的子表面(窗口)?

1 投票
1 回答
1577 浏览
提问于 2025-04-18 06:18

我有一个简单的PyOpenGL程序,可以画一个立方体。我想在立方体的前面画一个透明的窗户。虽然我能让两个表面都显示出来,但它们的样子并不像一个窗户。

这是我用来画立方体的代码:

    # Draws the six faces of a cube
def DrawCube(self):
    # Front face - Blue
    glPushName(1)
    glBegin(GL_QUADS)
    glColor4f(0.0, 0.0, 1.0, 1.0)
    glNormal3f(0.0, 0.0, 1.0) # Allows for light to reflect off certain parts of surface
    glVertex3f(1.0, 0.0, 0.0)
    glVertex3f(1.0, 1.0, 0.0)
    glVertex3f(1.0, 1.0, 1.0)
    glVertex3f(1.0, 0.0, 1.0)
    glEnd()

    # Back face - Green
    glPushName(2)
    glBegin(GL_QUADS)
    glColor4f(0.0, 1.0, 0.0, 1.0)
    glNormal3f(0.0, 0.0,-1.0)
    glVertex3f(0.0, 0.0, 0.0)
    glVertex3f(0.0, 1.0, 0.0)
    glVertex3f(0.0, 1.0, 1.0)
    glVertex3f(0.0, 0.0, 1.0)
    glEnd()

    # Left face - Red
    glPushName(3)
    glBegin(GL_QUADS)
    glColor4f(1.0, 0.0, 0.0, 1.0)
    glNormal3f(-1.0,0.0, 0.0)
    glVertex3f(0.0, 0.0, 0.0)
    glVertex3f(1.0, 0.0, 0.0)
    glVertex3f(1.0, 0.0, 1.0)
    glVertex3f(0.0, 0.0, 1.0)
    glEnd()

    # Right face - Orange
    glPushName(4)
    glBegin(GL_QUADS)
    glColor4f(1.0, 0.55, 0.0, 1.0)
    glNormal3f(1.0, 0.0, 0.0)
    glVertex3f(1.0, 1.0, 0.0)
    glVertex3f(1.0, 1.0, 1.0)
    glVertex3f(0.0, 1.0, 1.0)
    glVertex3f(0.0, 1.0, 0.0)
    glEnd()

    # Top face - White
    glPushName(5)
    glBegin(GL_QUADS)
    glColor4f(1.0, 1.0, 1.0, 1.0)
    glNormal3f(0.0, 1.0, 0.0)
    glVertex3f(0.0, 0.0, 1.0)
    glVertex3f(1.0, 0.0, 1.0)
    glVertex3f(1.0, 1.0, 1.0)
    glVertex3f(0.0, 1.0, 1.0)
    glEnd()

    # Bottom face - Yellow
    glPushName(6)
    glBegin(GL_QUADS)
    glColor4f(1.0, 1.0, 0.0, 1.0)
    glNormal3f(0.0,-1.0, 0.0)
    glVertex3f(0.0, 0.0, 0.0)
    glVertex3f(0.0, 1.0, 0.0)
    glVertex3f(1.0, 1.0, 0.0)
    glVertex3f(1.0, 0.0, 0.0)
    glEnd()

    # Window on Front (Blue) Face
    glPushName(7)
    glBegin(GL_QUADS)
    glColor4f(0.0, 1.0, 1.0, 0.4)
    glNormal3f(0.0, 0.0, 1.0)
    glVertex3f(1.0, 0.25, 0.25)
    glVertex3f(1.0, 0.75, 0.25)
    glVertex3f(1.0, 0.75, 0.75)
    glVertex3f(1.0, 0.25, 0.75)
    glEnd()

这是我画出来的效果。

Cube Rendering

我想让这个窗户完全透明,这样就可以透过它看到立方体的另一边。请问我该怎么做呢?

1 个回答

2

你遇到了两个问题。首先,你需要设置混合模式,这样不透明的物体才能透过半透明的窗户显示出来:

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

你看到的那些问题是因为在画两个平面重合的多边形。理想情况下,它们在同一个像素上应该有相同的深度值。但由于所有的计算都是用有限的精度进行的,所以可能会有一些微小的差异,这样就会因为四舍五入的误差导致一个多边形在另一个前面。这种现象通常被称为“深度冲突”或“z冲突”。

为了避免深度冲突的问题,你需要把窗户稍微画在立方体的前面。你可以通过给窗户使用稍微更大的x坐标来做到这一点。OpenGL 也有一个内置的机制来

glPolygonOffset(1.0f, 1.0f);
glEnable(GL_POLYGON_OFFSET_FILL);

你可能需要调整一下 glPolygonOffset() 的具体参数,以获得理想的效果。

撰写回答