线条不会在具有完全黑色纹理的屏幕外帧缓冲区上渲染

Posted

技术标签:

【中文标题】线条不会在具有完全黑色纹理的屏幕外帧缓冲区上渲染【英文标题】:Lines do not render on an offscreen frame buffer with a completely black texture 【发布时间】:2010-01-09 20:12:30 【问题描述】:

如果我有一个绑定了纹理的帧缓冲区,它只是带有完整 alpha 的黑色,我尝试在其上画一条线,即使该线具有完整的 alpha,它也不会渲染。我不傻,所以线条肯定不是黑色的。如果纹理是白色的,那么线条会突然正确渲染,就好像它后面的纹理颜色会影响线条的颜色一样,这是愚蠢的。只有线条有透明度,后面的颜色才会有效果。

我正在使用线条平滑。我使用以下混合功能,这显然是要使用的功能,

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

使用帧缓冲对象在屏幕或 Surface 对象的纹理上绘制大量线条的功能:

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

【问题讨论】:

您如何显示代码以绘制线条和/或您观察到的一些图片?另外,你的命名很奇怪。绑定到帧缓冲区的纹理?你的意思是你已经在帧缓冲区中绘制了一个纹理? 背景和线条的渲染需要贴更多代码吗? 我添加了很多代码。我的意思是使用绑定纹理:glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface.texture, 0) 在未启用 GL_BLEND 或未启用 GL_LINE_SMOOTH 的情况下,您的代码是否按预期工作? 禁用所有内容或仅线条的混合似乎会使直接渲染到屏幕的线条起作用,而不是渲染到纹理的线条。禁用线条平滑没有任何区别。 【参考方案1】:

至少有一件事看起来很可疑:您在初始化代码中打开了纹理,却忘记了它。

所以你的线条是用纹理绘制的(和恒定的纹理坐标),大概是选择你要写入的纹理。

这可能不是您想要的(我不记得 fbo 规范对此有何规定,但它不会起作用)。渲染线条时关闭纹理如何?

【讨论】:

非常感谢。以后我会记住的。

以上是关于线条不会在具有完全黑色纹理的屏幕外帧缓冲区上渲染的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 中的离屏帧缓冲区

通过帧缓冲区对象渲染到纹理

如何将图像后处理着色器的结果添加到场景中

OpenGL ES 2.0 Framebuffer 渲染到纹理 iOS:没有显示

渲染到窗口帧缓冲区和 FBO 以保存全尺寸纹理图像

如何计算帧缓冲区间距?