简体   繁体   English

OpenGL-仅显示纹理

[英]OpenGL - Show Texture Only

I'm working on a 2D isometric game, using pygame and pyopengl. 我正在使用pygame和pyopengl开发2D等距游戏。

I'm drawing sprites as quads, with a texture. 我正在将精灵绘制为带有纹理的四边形。 I managed to get the alpha transparency to work for the texture, but the quad itself is still filled in a solid color (whatever colour gl pipeline is set with at the time). 我设法使Alpha透明度适用于纹理,但是四边形本身仍然填充有纯色(无论何时设置了gl gl管道)。

How do I hide the quad shape, and just show the texture? 如何隐藏四边形形状,仅显示纹理?

Here is a pic showing the problem (gl pipeline set to pink/purple color): 这是一张显示问题的图片(gl管线设置为粉红色/紫色):

在此处输入图片说明

The code is a bit messy, and I've been blindly copy 'n pasting gl calls hoping it solves the problem so there are bound to be quite a few calls in the wrong place or duplicated (or both). 代码有点混乱,我一直在盲目复制'n粘贴gl调用,希望它能解决问题,所以肯定有很多调用在错误的位置或重复的(或同时重复)。

GL Setup code (called once at start of script) 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)

Drawing setup code (called once at the start of each frame) 绘图设置代码(在每帧开始时调用一次)

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 draw code (called for every sprite draw call): 四边形绘制代码(每次子图绘制调用都会调用):

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

Well, either use blending , so that the alpha value actually has effect on opacity. 好吧,可以使用blending ,以便alpha值实际上对不透明度有影响。 Or use alpha testing, so that incoming fragments with an alpha below/above a certain threshold are discarded. 或使用Alpha测试,以丢弃Alpha低于/高于特定阈值的传入片段。

Blending requires to sort geometry back to front. 混合需要将几何图形从背面排序。 And given what you want to do alpha testing may be the easier, more straightforward solution. 鉴于您要进行的Alpha测试,可能是更简单,更直接的解决方案。

Update: 更新:

Either way it's imperative that the texture's alpha value makes it through to the fragment. 无论哪种方式,都必须使纹理的Alpha值直达片段。 If you were using shaders this would be as simple as making sure that the fragment output alpha would receive its value from the texture. 如果您使用的是着色器,那么就像确保片段输出alpha将从纹理接收其值一样简单。 But you're using the fixed function pipeline and the mess that's the texture environment state machine. 但是,您使用的是固定功能管道,并且使用的是纹理环境状态机。

Using only a single texture your best bet would be a GL_REPLACE texture mode (completely ignores the vertex color). 仅使用单个纹理,最好的选择是GL_REPLACE纹理模式(完全忽略顶点颜色)。 Or GL_MODULATE that takes the vertex color into account. 或GL_MODULATE将顶点颜色考虑在内。 Right now you're assumingly using GL_DECAL mode. 现在,您假设正在使用GL_DECAL模式。

My suggestion: Drop the fixed function pipeline and use shaders. 我的建议:删除固定功能管道并使用着色器。 Much easier to get things related to texturing working. 与纹理化工作相关的事情要容易得多。 Also you'll hard pressed to find hardware that's not using shaders anyway (unless you're planning to run your program on stuff that's been built before 2004). 另外,您将很难找到仍然不使用着色器的硬件(除非您计划在2004年前构建的程序上运行程序)。

The colored background behind your tiles is probably due to this line when you set up your texture: 设置纹理时,瓷砖后面的彩色背景可能是由于此线所致:

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)

Just remove this as the default texture environment settings are probably fine for standard tile rendering. 只需删除此选项即可,因为默认纹理环境设置可能适合标准图块渲染。 As an example of what messing with these parameters can do, if you wanted glColor calls to "tint" your texture instead, then replace GL_DECAL with GL_BLEND . 举例说明如何弄乱这些参数,如果您希望使用glColor调用来“着色”纹理,然后将GL_DECAL替换为GL_BLEND

There is no need for any of those lighting calls included in your code as far as I can tell unless you are working with 3d models and ancient per-vertex lighting (I assume you are not since this is a 2d isometric game). 据我所知,代码中不需要任何照明调用,除非您使用3d模型和古老的逐顶点照明(因为这是一个2d等距游戏,所以我认为您没有这样做)。 Also you only need blending for this, no need for alpha testing. 同样,您只需要为此而混合,无需进行alpha测试。 Assuming you are working with images with alpha (RGBA format), here is a simple demo that displays two tiles with a transparent background (supply your own image of course instead of ./images/grass.png ): 假设您正在使用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()

Let me know if this helps! 让我知道这是否有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM