Z缓冲导致透明度降低

时间:2018-03-24 20:06:56

标签: python python-3.x opengl pygame pyopengl

我尝试使用z-buffering根据z值对纹理进行排序。我创建了一个简单的脚本,如下所示。

import pygame
import sys
from OpenGL.GL import *
from pygame.locals import *


def load_texture(path):
    surf = pygame.image.load(path)
    s = pygame.image.tostring(surf, 'RGBA')
    texID = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, texID)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf.get_width(), surf.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, s)
    glGenerateMipmap(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, 0)
    return texID


# set pygame screen
pygame.display.init()
pygame.display.set_mode((1000, 500), OPENGL | DOUBLEBUF)
info = pygame.display.Info()

# Set up opengl parameters
glMatrixMode(GL_PROJECTION)
glEnable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

# load textures
texID = load_texture('Player1.png')
texID2 = load_texture('spr_void.png')

# create pygame clock
MAINCLOCK = pygame.time.Clock()

while True:
    # get quit event
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    # prepare to render screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glEnable(GL_DEPTH_TEST)

    # draw texture 1
    glBindTexture(GL_TEXTURE_2D, texID)
    glBegin(GL_QUADS)
    glTexCoord2f(0, 1); glVertex3f(-1, -0.5, 0.2)
    glTexCoord2f(1, 1); glVertex3f(1, -0.5, 0.2)
    glTexCoord2f(1, 0); glVertex3f(1, 0.5, 0.2)
    glTexCoord2f(0, 0); glVertex3f(-1, 0.5, 0.2)
    glEnd()

    # draw texture 2
    glBindTexture(GL_TEXTURE_2D, texID2)
    glBegin(GL_QUADS)
    glTexCoord2f(0, 1); glVertex3f(-1, -1, 0.5)
    glTexCoord2f(1, 1); glVertex3f(1, -1, 0.5)
    glTexCoord2f(1, 0); glVertex3f(1, 1, 0.5)
    glTexCoord2f(0, 0); glVertex3f(-1, 1, 0.5)
    glEnd()

    # read pixels and flush
    glReadPixels(0, 0, info.current_w, info.current_h, GL_RGBA, GL_UNSIGNED_BYTE)
    glFlush()

    pygame.display.flip()
    MAINCLOCK.tick(60)

如果我运行代码注释" glEnable(GL_DEPTH_TEST)"我得到以下结果:

Without z buffering

正如预期的那样,第二个绘制的图像越过第一个,即使它具有更高的z值。现在,如果我取消注释该行,并重新运行代码,我得到:

With z buffering

尽管图像按预期排序,但顶部图像最终会失去它的透明度。 如何激活z缓冲来获得正确的透明度行为?

PS:你可以使用你选择的任何图像来重现上面的代码,不要忘记更改代码中的路径

1 个答案:

答案 0 :(得分:0)

透明度基本上将颜色缓冲区中的当前颜色与您放置的新颜色混合在一起(以某种方式依赖于glBlendFunc)。

在这个例子中,您首先要绘制宇宙飞船。透明边缘与当前像素混合(由于没有其他任何东西在那里绘制,因此是黑色),因此产生的颜色是黑色。太空人将无法改变黑色像素,因为它们仍然具有与太空船中的其他像素相同的Z值。太空人Z值。

要解决此问题,您需要从后向前绘制场景,以便混合功能正常工作。