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

发布于 2024-08-17 11:41:05 字数 4261 浏览 7 评论 0原文

如果我有一个绑定了纹理的帧缓冲区,它只是黑色且具有完整的 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

If I have a frame buffer which has a textured binded to it which is simply black with full alpha and I try to draw a line to it, even if the line has full alpha it wont render. I'm not stupid, so the lines definitely aren't black. If the texture is white instead the line suddenly render correctly as if the colour of the texture behind it effects the colour of the lines which is dumb. Only if the lines have transparency, should the colour behind them have effect.

I'm using line smoothing. I use the following blend function which is apparently the one to use,

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

How do I fix this?

Lots of code:

For drawing lines:

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.

Setting up framebuffer object:

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

Creation of texture:

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

Function to draw lots of lines to the screen or to the texture of a Surface object with a frame buffer object:

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

That's all I can see as important. Except maybe the initialisation code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小红帽 2024-08-24 11:41:05

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

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

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

There is at least one thing that looks suspicious: you're turning on Texturing in your init code, and forgetting about it.

So your lines are drawn with texturing on (and constant texture coordinates), presumably picking the texture that you're trying to write to.

This is likely not what you want (I don't remember what the fbo spec has to say on this, but it's not going to work). How about you turn off texturing when rendering the lines ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文