Code archives/Graphics/OpenGL Render2Texture (FBOs)

This code has been declared by its author to be Public Domain code.

Download source code

OpenGL Render2Texture (FBOs) by klepto22008
Render2Texture with Alpha and so on for OpenGL.
SuperStrict


Type TImageBuffer
	Field Image:TImage
	Field rb:Int[1]
	Field fb:Int[1]
	Field Imageframe:TGLImageframe
	Field Frame:Int = 0
	Field OrigX:Int
	Field OrigY:Int
	Field OrigW:Int
	Field OrigH:Int

	Function SetBuffer:TImageBuffer(Image:TImage,Frame:Int = 0 )
		Local IB:TImageBuffer = New TImageBuffer
		IB.Image = Image
		IB.Frame = Frame
		IB.GenerateFBO()
		IB.BindBuffer()
		Return IB
	End Function
	
	Function Init(Width:Int,Height:Int,Bit:Int=0,Mode:Int=60)
		SetGraphicsDriver(GLMax2DDriver())
		Graphics Width , Height,bit,Mode
		glewInit()
	End Function
	
	Method GenerateFBO()
		ImageFrame = TGLImageFrame(Image.frame(Frame) )
			
		imageframe.v0 = imageframe.v1
		imageframe.v1 = 0.0
	
		Local W:Int = Image.width
		Local H:Int = Image.Height
		
		AdjustTexSize(W , H) 

		
		glGenFramebuffersEXT(1, fb )
	    glGenRenderbuffersEXT(1 , rb) 
	   
	    glBindTexture(GL_TEXTURE_2D, Imageframe.name);
	    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
	   
	   
	 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,  Imageframe.name, 0);
	    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
	    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, W, H);
	    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , rb[0])
	   
	    Local status:Int =  glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)
	   
	    Select status
	       Case GL_FRAMEBUFFER_COMPLETE_EXT 
	          Print "all right" + " : " + Status
	       Case GL_FRAMEBUFFER_UNSUPPORTED_EXT
	          Print "choose different formats"
	       Default
	          End 
	    EndSelect 
   
	End Method
	
	Method BindBuffer()
		GetViewport(OrigX,OrigY,OrigW,OrigH)
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0])
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,Image.Width,Image.Width,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , Image.Width , Image.Height)
		glScissor 0,0, Image.Width , Image.Height
	End Method
	
	Method UnBindBuffer()
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,OrigW ,Origh,0,-1,1
		glMatrixMode GL_MODELVIEW 
		glViewport(0 , 0 , OrigW, OrigH)
		glScissor 0,0, OrigW ,OrigH
	End Method
	
	Method Cls(r#=0.0,g#=0.0,b#=0.0,a#=1.0)
		glClearColor r,g,b,a
		glClear GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
	End Method
	
	Method BufferWidth:Int()
		Return Image.Width
	End Method
	
	Method BufferHeight:Int()
		Return Image.Height
	End Method

End Type


Function AdjustTexSize( width:Int Var,height:Int Var )
	'calc texture size
	width=Pow2Size( width )
	height=Pow2Size( height )
	Repeat
		Local t:Int
		glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
		glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
		If t Return
		If width=1 And height=1 RuntimeError "Unable to calculate tex size"
		If width>1 width:/2
		If height>1 height:/2
	Forever
End Function

Function Pow2Size:Int( n:Int )
	Local t:Int=1
	While t<n
		t:*2
	Wend
	Return t
End Function




TImageBuffer.Init(800,600) 'Same as Graphics but set to GLDriver + glewinit


Global Img:TImage = CreateImage(512, 512)
MidHandleImage Img

Local IB:TImageBuffer = TImageBuffer.SetBuffer(Img) 

Local x:Float = 0
Local Speed:Float = 0.1

Local Angle:Float = 0

While Not KeyHit(Key_Escape)
	SetClsColor 0 , 0 , 255

	Cls
		SetColor 0,255,0
		DrawRect 272,172,256,256
		SetBlend ALPHABLEND
		SetAlpha 1.0
		SetColor 255,255,255
		SetRotation Angle
		DrawImageRect Img , 256+144,256+44,512,512
		SetRotation 0
		SetAlpha 1.0
		Angle:+0.3 
	Flip	
	
	
		IB.BindBuffer()
		IB.Cls(1.0,,,0.4)
		SetColor 255,255,255
		DrawLine 0,0,512,512
		DrawLine 0,512,512,0
		
		IB.UnBindBuffer()
		SetViewport 0,0,800,600
		
Wend

Comments

Pete Rigz2008
I moved this question to the openGL forum: http://www.blitzbasic.com/Community/posts.php?topic=77025


tesuji2011
Apologies for digging this up.

Thanks for posting this snippet as it helped me get my head around FBOs and is nice and lightweight.

Hope you don't mind but I've refactored it slightly and couldn't resist adding a simple feedback example :)
Not sure exactly why the image is mirrored. Guess it might just be max2d uv coords.



*Updated - included y mirror fix. Thanks for that GW.
**Updated - added some interactivity.


GW2011

Changing the glortho command in 'Enablebuffer' to
glortho 0,width,0,width,-1,1
should fix the y flipping issue


I spoke too soon,
I think the real way to fix it is to to do a translation when you bind and unbind the buffer.
After glLoadIdentity add glScalef(1,-1,1.0)
and of course undo it in the unbind function with glScalef(1,1,1)

EDIT#2
It works and fixes the original FBO post, but not with the second.


Code Archives Forum