OpenGL - 仅显示纹理

时间:2016-10-14 23:36:27

标签: python opengl

我正在使用pygame和pyopengl进行2D等距游戏。

我正在绘制精灵作为四边形,带有纹理。我设法让alpha透明度适用于纹理,但四边形本身仍然填充纯色(当时设置的颜色gl管道)。

如何隐藏四边形,只显示纹理?

这是一张显示问题的图片(gl管道设置为粉红色/紫色):

enter image description here

代码有点混乱,我一直盲目地复制'粘贴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()

2 个答案:

答案 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()

请告诉我这是否有帮助!