我正在使用pygame和pyopengl进行2D等距游戏。
我正在绘制精灵作为四边形,带有纹理。我设法让alpha透明度适用于纹理,但四边形本身仍然填充纯色(当时设置的颜色gl管道)。
如何隐藏四边形,只显示纹理?
这是一张显示问题的图片(gl管道设置为粉红色/紫色):
代码有点混乱,我一直盲目地复制'粘贴gl调用希望它解决问题所以在错误的地方或重复(或两者)必然会有很多调用。
GL设置代码(在脚本开始时调用一次)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glViewport(0, 0, screen_size[0], screen_size[1])
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, screen_size[0], 0.0, screen_size[1], 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
绘制设置代码(在每帧开始时调用一次)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glViewport(0, 0, screen_size[0], screen_size[1])
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, screen_size[0], 0.0, screen_size[1], 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
Quad绘制代码(为每个精灵绘图调用调用):
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_TEXTURE_2D)
glEnable(GL_ALPHA_TEST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
# Start new transformation matrix
glPushMatrix()
# Apply translation
glTranslatef(self.rect.centerx, self.rect.centery, 0.0)
# Start gl drawing cursor
glColor4f(1.0, 0.0, 1.0, 1.0)
# Bind the texture to this draw session
glBindTexture(GL_TEXTURE_2D, self.texture.id)
# Start drawing a quad
glBegin(GL_QUADS)
# Grab new copy of rect, and move to the origin
r = self.rect.copy()
r.center = (0, 0)
# Draw top left point
glTexCoord2f(1.0, 0.0)
glVertex2f(*r.topleft)
# Draw top right point
glTexCoord2f(0.0, 0.0)
glVertex2f(*r.topright)
# Draw bottom right point
glTexCoord2f(0.0, 1.0)
glVertex2f(*r.bottomright)
# Draw bottom left point
glTexCoord2f(1.0, 1.0)
glVertex2f(*r.bottomleft)
# End quad
glEnd()
# Apply transformation matrix
glPopMatrix()
答案 0 :(得分:2)
好吧,使用混合,这样alpha值实际上对不透明度有影响。或者使用alpha测试,以便丢弃alpha低于/高于某个阈值的传入片段。
混合需要将几何体从前面排序。鉴于您想要做什么,alpha测试可能是更简单,更直接的解决方案。
<强>更新强>
无论哪种方式,纹理的alpha值都必须通过片段。如果您使用着色器,这将简单到确保片段输出alpha将从纹理接收其值。但是你正在使用固定功能管道和纹理环境状态机的混乱。
仅使用单个纹理,最好的选择是GL_REPLACE纹理模式(完全忽略顶点颜色)。或者考虑顶点颜色的GL_MODULATE。现在你假设使用了GL_DECAL模式。
我的建议:删除固定功能管道并使用着色器。更容易得到与纹理工作相关的事情。此外,您还很难找到不使用着色器的硬件(除非您计划在2004年之前构建的内容上运行程序)。
答案 1 :(得分:2)
设置纹理时,瓷砖背后的彩色背景可能是由于此线:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
只需删除它,因为默认纹理环境设置可能适用于标准图块渲染。作为弄乱这些参数的例子,如果你想要glColor
调用&#34; tint&#34;改为使用纹理,然后将GL_DECAL
替换为GL_BLEND
。
除非你正在使用3d模型和古老的每顶点照明(我假设你不是因为这是一个二维等距游戏),否则你的代码中不需要包含任何照明调用。 。此外,您只需要混合,不需要进行alpha测试。假设您正在使用带有alpha(RGBA格式)的图像,这是一个简单的演示,它显示两个具有透明背景的图块(当然提供您自己的图像而不是./images/grass.png
):
import pygame
from pygame.locals import *
from OpenGL.GL import *
import sys
class Sprite(object):
def __init__(self):
self.x = 0
self.y = 0
self.width = 0
self.height = 0
self.texture = glGenTextures(1)
def load_texture(self, texture_url):
tex = pygame.image.load(texture_url)
tex_surface = pygame.image.tostring(tex, 'RGBA')
tex_width, tex_height = tex.get_size()
glBindTexture(GL_TEXTURE_2D, self.texture)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_surface)
glBindTexture(GL_TEXTURE_2D, 0)
self.width = tex_width
self.height = tex_height
def set_position(self, x, y):
self.x = x
self.y = y
def render(self):
#glColor(1, 1, 1, 1)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glBindTexture(GL_TEXTURE_2D, self.texture)
glBegin(GL_QUADS)
glTexCoord(0, 0)
glVertex(self.x, self.y, 0)
glTexCoord(0, 1)
glVertex(self.x, self.y + self.height, 0)
glTexCoord(1, 1)
glVertex(self.x + self.width, self.y + self.height, 0)
glTexCoord(1, 0)
glVertex(self.x + self.width, self.y, 0)
glEnd()
glBindTexture(GL_TEXTURE_2D, 0)
def init_gl():
window_size = width, height = (550, 400)
pygame.init()
pygame.display.set_mode(window_size, OPENGL | DOUBLEBUF)
glEnable(GL_TEXTURE_2D)
glMatrixMode(GL_PROJECTION)
glOrtho(0, width, height, 0, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
if __name__ == "__main__":
init_gl()
tile1 = Sprite()
tile1.load_texture("./images/grass.png")
tile1.set_position(50, 100)
tile2 = Sprite()
tile2.load_texture("./images/grass.png")
tile2.set_position(80, 130)
tiles = [tile1, tile2]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
glClear(GL_COLOR_BUFFER_BIT)
glColor(1, 0, 0, 1)
for tile in tiles:
tile.render()
pygame.display.flip()
请告诉我这是否有帮助!