You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyglet中半透明精灵渲染与深度测试问题求助

解决Pyglet半透明精灵深度测试重叠问题

问题根源

启用GL_DEPTH_TEST后,OpenGL会为所有绘制的像素(包括精灵的透明区域)写入深度缓冲,导致后方精灵的像素被透明区域错误遮挡。仅启用混合(GL_BLEND)只能处理颜色叠加,无法解决深度缓冲的遮挡逻辑问题。


方案1:调整绘制顺序 + 控制深度写入

半透明物体需要从远到近绘制,同时关闭深度写入,让透明区域不阻挡后方像素:

import pyglet as pg
from pyglet.gl import *

window = pg.window.Window(width=320, height=320)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

im1 = pg.image.load('resources/sprites/npc/soldier/walk/0.png')
sprite1 = pg.sprite.Sprite(im1, x=100, y=100, z=1)
im2 = pg.image.load('resources/sprites/npc/soldier/walk/0.png')
sprite2 = pg.sprite.Sprite(im2, x=150, y=150, z=0)

@window.event
def on_draw():
    window.clear()
    # 按z值升序排序(远的先画,近的后画)
    sorted_sprites = sorted([sprite1, sprite2], key=lambda s: s.z)
    
    glDepthMask(GL_FALSE)  # 关闭深度写入,透明区域不遮挡后方像素
    for sprite in sorted_sprites:
        sprite.draw()
    glDepthMask(GL_TRUE)  # 恢复深度写入,用于后续不透明物体绘制

pg.app.run()

若使用Batch,需按z值将精灵分组到不同Batch,因为Batch内部按添加顺序渲染,无法自动排序。


方案2:自定义着色器实现Discard(丢弃透明像素)

通过片段着色器丢弃Alpha值低于阈值的像素,让这些像素不写入深度缓冲,后方精灵可透过透明区域显示:

import pyglet as pg
from pyglet.gl import *

# 自定义片段着色器:丢弃Alpha<0.1的透明像素
fragment_shader = """
#version 120
uniform sampler2D texture0;
void main() {
    vec4 color = texture2D(texture0, gl_TexCoord[0].xy);
    if (color.a < 0.1) {
        discard; // 丢弃透明像素,不写入深度缓冲
    }
    gl_FragColor = color * gl_Color;
}
"""

window = pg.window.Window(width=320, height=320)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

# 创建着色器程序
shader_program = pg.graphics.shader.ShaderProgram(
    pg.graphics.shader.Shader(fragment_shader, 'fragment')
)

im1 = pg.image.load('resources/sprites/npc/soldier/walk/0.png')
sprite1 = pg.sprite.Sprite(im1, x=100, y=100, z=1, shader=shader_program)
im2 = pg.image.load('resources/sprites/npc/soldier/walk/0.png')
sprite2 = pg.sprite.Sprite(im2, x=150, y=150, z=0, shader=shader_program)

@window.event
def on_draw():
    window.clear()
    sprite1.draw()
    sprite2.draw()

pg.app.run()

注意:此方案需Pyglet 1.5+版本支持ShaderProgram,适合需要精确控制透明像素的场景。


内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 20:15:28