完全黑色纹理的离屏帧缓存上不渲染线条

1 投票
1 回答
813 浏览
提问于 2025-04-15 17:50

我有一个帧缓冲区,上面绑定了一个纹理,这个纹理是全黑的,透明度也是满的。当我尝试在上面画一条线的时候,即使这条线的透明度也是满的,它也不会显示出来。我不是傻瓜,所以这条线肯定不是黑色的。如果纹理变成白色,线条就能正常显示了,感觉就像是纹理的颜色影响了线条的颜色,这真是让人困惑。只有当线条有透明度的时候,后面的颜色才应该有影响。

我在使用线条平滑处理。我用的混合函数是下面这个,听说这是正确的选择:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

我该怎么解决这个问题呢?

有很多代码:

用于绘制线条的代码:

def draw_line(a,b,c,w,antialias):
    if antialias:
        glEnable(GL_LINE_SMOOTH) #Enable line smoothing.
    c = [float(sc)/255.0 for sc in c] #Divide colours by 255 because OpenGL uses 0-1
    if len(c) != 4:
        c.append(1) #Add a value for aplha transparency if needed
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity() #Loads model matrix
    glColor4fv(c)
    glLineWidth(w)
    glBegin(GL_LINES)
    glVertex2fv(a)
    glVertex2fv(b)
    glEnd()
    if antialias:
        glDisable(GL_LINE_SMOOTH) #Disable line smoothing.

设置帧缓冲对象的代码:

def setup_framebuffer(surface):
    #Create texture if not done already
    if surface.texture == None:
        create_texture(surface)
    #Render child to parent
    if surface.frame_buffer == None:
        surface.frame_buffer =  glGenFramebuffersEXT(1)
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surface.frame_buffer)
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface.texture, 0)
    glPushAttrib(GL_VIEWPORT_BIT)
    glViewport(0,0,surface.surface_size[0],surface.surface_size[1])
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity() #Load the projection matrix
    gluOrtho2D(0,surface.surface_size[0],0,surface.surface_size[1])

def end_framebuffer():
    glPopAttrib()
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity() #Load the projection matrix
    gluOrtho2D(0,1280,720,0) #Set an orthorgraphic view

创建纹理的代码:

def create_texture(surface):
    surface.texture = glGenTextures(1)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity() #Loads model matrix
    glBindTexture(GL_TEXTURE_2D, surface.texture) #Binds the current 2D texture to the texture to be drawn
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) #Required to be set for maping the pixel data
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) #Similar as above
    if surface.data == None:
        surf = pygame.Surface((1,1),SRCALPHA)
        surf.fill(surface.colour[:-1])
        surface.data = pygame.image.tostring(surf, "RGBA") * (surface.surface_size[0] * surface.surface_size[1])
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface.surface_size[0], surface.surface_size[1], 0, GL_RGBA,GL_UNSIGNED_BYTE, surface.data) #Put surface pixel data into texture

一个函数,用来在屏幕上或在带有帧缓冲对象的表面对象的纹理上绘制很多线条:

def add_lines(surface, c, coordinates, w = 1, antialias = True):
    if surface.__class__ == Surface: #Only use a frame buffer if the line isn't being drawn to the screen.
        setup_framebuffer(surface)
    last = None
    for coordinate in coordinates: #Loop though the coordinates and draw the lines
        if last != None:
            draw_line(last,coordinate,c,w,antialias)
        last = coordinate
    if surface.__class__ == Surface: #Only use a frame buffer if the line isn't being drawn to the screen.
        end_framebuffer()

这就是我能看到的重要内容。也许还有初始化的代码:

glutInit(sys.argv)
glutInitWindowPosition(0,0)
glutInitWindowSize(*game_size)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA)
glutCreateWindow(title)
glutSetIconTitle(title)
glutReshapeFunc(self.reshaped)
glutKeyboardFunc(self.keydown)
glutKeyboardUpFunc(self.keyup)
glutSpecialFunc(self.specialdown)
glutSpecialUpFunc(self.specialup)
glViewport(0,0,self.first_screen[0],self.first_screen[1]) #Creates the viewport which is mapped to the window
glEnable(GL_BLEND) #Enable alpha blending
glEnable(GL_TEXTURE_2D) #Enable 2D Textures
glEnable(GL_POLYGON_SMOOTH) #Enable antialiased polygons
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glMatrixMode(GL_PROJECTION)
glLoadIdentity() #Load the projection matrix
gluOrtho2D(0,1280,720,0) #Set an orthorgraphic view

1 个回答

1

有一件事情看起来有点可疑:你在初始化代码中开启了纹理功能,但之后就忘了这件事。

所以你的线条是在开启纹理的情况下绘制的(而且纹理坐标是固定的),很可能是选中了你想写入的那个纹理。

这可能不是你想要的效果(我记不清fbo的规范是怎么说的,但这肯定是行不通的)。要不你在绘制线条的时候把纹理功能关掉?

撰写回答