BackBufferToTex solution for MiniB3D


Tweet blitzmax graphics opengl code-archives minib3d
(Posted 5 months ago) RonTek

Converting code from B3D? problem is that when 'copying' to the texture it gets flipped.

Tracing the problem leads to glCopyTexImage2D which copies from the bottom left instead of the top left.

Here is a fix for the normal texture in TTexture.bmx:

Author: Ked
Updated by: markcwm

    Method BackBufferToTex(mipmap_no:Int=0,frame:Int=0,fastinvert:Int=True)

        If flags&128=0 ' normal texture

            Local x:Int=0,y:Int=0

            glBindtexture GL_TEXTURE_2D,gltex[frame]
            If fastinvert=True
                glCopyTexImage2D(GL_TEXTURE_2D,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Self.ScaleTexture(1.0,-1.0) ' fix by Ked
            Else
                pixmap=GrabPixmap(x,y,width,height) ' should always be in PF_RGBA8888
                gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixmap.pixels)
            EndIf

        Else ' cubemap texture

            Local x:Int=0,y:Int=0

            glBindtexture GL_TEXTURE_CUBE_MAP_EXT,gltex[0]
            Select cube_face
                Case 0 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 1 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 2 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 3 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 4 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 5 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
            End Select

        EndIf

    End Method
(Posted 5 months ago) markcwm commented:

This is wierd, I'm sure I had a perfect working example of CreateTexture with the texture the right way up and no need to invert uvs. But this solution seems right as the OpenGL back buffer is upside-down and glCopyTexImage2d grabs the back buffer so it will also be upside-down. There are some alternatives, either copy the back buffer to pixel buffer and invert it, then use gluBuild2DMipmaps as in BufferToTex, or use glCopyPixels and glPixelZoom to invert, this would be preferrable to me but I've never tried this before. I think it might be confusing if some GL textures are top-bottom and others are bottom-top so I don't like just flipping the uvs.

(Posted 5 months ago) RonTek commented:

Hey Mark, Yes, this is for MiniB3D only as I have tagged it.

Thanks for the addtional info and just updated the title for clarity.

(Posted 5 months ago) markcwm commented:

Oh right okay.

Well I was wrong I wasn't using BackBufferToTex in my CreateTexture example, I was using GrabPixmap and BufferToTex as GrabPixmap includes YFlipPixmap which inverts the actual pixels. Also, the alternative using glCopyPixels and glPixelZoom to invert is really for drawing, you just use glReadPixels which is actually what GrabPixmap uses.

I added this tweak to BackBufferToTex with an extra parameter called fastinvert, true by default to use Ked's tweak and false to actually flip the pixels which is slower.

    Method BackBufferToTex(mipmap_no:Int=0,frame:Int=0,fastinvert:Int=True)

        If flags&128=0 ' normal texture

            Local x:Int=0,y:Int=0

            glBindtexture GL_TEXTURE_2D,gltex[frame]
            If fastinvert=True
                glCopyTexImage2D(GL_TEXTURE_2D,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Self.ScaleTexture(1.0,-1.0) ' fix by Ked
            Else
                pixmap=GrabPixmap(x,y,width,height) ' should always be in PF_RGBA8888
                gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixmap.pixels)
            EndIf

        Else ' cubemap texture

            Local x:Int=0,y:Int=0

            glBindtexture GL_TEXTURE_CUBE_MAP_EXT,gltex[0]
            Select cube_face
                Case 0 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 1 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 2 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 3 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 4 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
                Case 5 glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,mipmap_no,GL_RGBA8,x,TGlobal.height-y-height,width,height,0)
            End Select

        EndIf

    End Method
(Posted 5 months ago) RonTek commented:

That's great. I just updated the code as well. Thanks Mark!

Reply To Topic (minimum 10 characters)

Please log in to reply