Does BlitzMax support EXT_framebuffer_object?(FBO)

BlitzMax Forums/BlitzMax OpenGL Programming/Does BlitzMax support EXT_framebuffer_object?(FBO)

I'd like to fool around with OpenGL FBOs (framebuffer objects) and apparantly it needs the EXT_framebuffer_object OpenGL extension.

Is this built into BlitzMax v1.24? If not, can it be easily added?

Ok, it looks like it is infact supported, but I'm having a problem...

At the top of my program I have this:

SetGraphicsDriver(GLGraphicsDriver())
GLGraphics(320, 200)

GlewInit() ' Is this needed??

...and then I do this to create the FBO object:
Local fbo : Int;
glGenFramebuffersEXT(1, Varptr fbo) ;

...but when it calls that function I get an unhandled memory exception error.

What am I doing wrong?

Thanks...

Yes it is needed to use GlewInit, without it there is no GLEW -> only OpenGL 1.2

And your setgraphicsdriver is unneeded. if you go for pure OpenGL max2d commands do not work

Ahh, thanks.

Any idea why I'm getting the unhandled memory exception then?

You cant just immediately access the extension. You have to do something to do with adding extensions first. I dont know what, but it springs to mind.

You mean like bind it as with any OpenGL buffer?

I'm not sure. If you use any commands that are not in OpenGL 1.1 you have to do then via extensions and you have to use, I think, the glew library to `detect` them and activate them.

In Bmax you dont have to detect them, you only need to check the support string for this extension and if it is not supported you have to find a work around.

Here is a small code snippet how I'm currently implementing them in miniB3D (yes they already work) ;)

Import klepto.MiniB3D
Local width=1024,height=768,depth=16,mode=0
Graphics3D width,height,depth,mode
ClearTextureFilters()



Local cam:TCamera=CreateCamera()
PositionEntity cam,0,10,-15
Local light = CreateLight(1)
PositionEntity light,20,10,0
Local ent = LoadMesh("media/teapot.b3d")
PositionEntity(ent,0,4,0)
Local Plane:TMEsh = LoadMesh("media/grid.b3d")
EntityColor Plane,128,52,12
PointEntity light ,ent
TurnEntity light,0,45,0
Local SunPlane:TMesh = CreateCube()
PositionEntity sunplane , 12 , 8 , 0
ScaleEntity sunplane ,3,1,3
Local T:Float = 0



Local testtex:TTexture = CreateTexture(512,512,1,1)
EntityTexture sunplane,testtex




Global rb:Int[1]
Global fb:Int[1]
   

Function InitRenderToTexture(Texture:TTexture)

   glGenFramebuffersEXT(1, fb )
   glGenRenderbuffersEXT(1 , rb) 
   
   glGenTextures(1, texture.gltex)
   glBindTexture(GL_TEXTURE_2D, texture.gltex[0]);
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 
   
   
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, Null);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
   
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture.gltex[0], 0);
   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[0]);
   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 512, 512);
   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 Function

Function RenderToTexture(texture:TTexture)
   

   
   
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , fb[0]) ; 

   RenderWorld 
   
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT , 0)
   

   
End Function




InitRenderToTexture(testtex)
While Not(KeyDown(KEY_ESCAPE) Or AppTerminate() )      

   MoveEntity ent,Sin(t*10)*0.1,Cos(t*10)*0.1,Sin(t*10)*0.1
   TurnEntity sunplane,0.5,0.5,0.5
   T:+0.5   
   
   
   mxs#=mxs#+(MouseXSpeed()/5.0)
   mys#=mys#+(MouseYSpeed()/5.0)
   RotateEntity cam , mys# , - mxs# , 0
   MoveMouse width/2,height/2
   MouseXSpeed() 
   MouseYSpeed() 

   If KeyDown(KEY_UP)=True Then MoveEntity Cam,0,0,0.5 ;' move camera forward
   If KeyDown(KEY_DOWN)=True Then MoveEntity Cam,0,0,-0.5# ' move camera back

   If KeyDown(KEY_LEFT)=True Then MoveEntity Cam,-0.5#,0,0 ' move camera left
   If KeyDown(KEY_RIGHT)=True Then MoveEntity Cam,0.5#,0,0 ' move camera Right
     

   Local x2:Float  = EntityX(cam)
   Local y2:Float  = EntityY(cam)
   Local z2:Float  = EntityZ(cam)
   Local rx:Float  = EntityPitch(cam)
   Local ry:Float = EntityYaw(cam)
   Local rz:Float = EntityRoll(cam)
   
   CameraViewport(cam,0,0,1024,1024)
   cam.PositionEntity(EntityX(light),EntityY(light),EntityX(light) )
   cam.RotateEntity(EntityPitch(light), EntityYaw(light), EntityRoll(light) )
   RenderWorld 

   RenderToTexture(testtex)
   

   cam.PositionEntity(x2,y2,z2)
   cam.RotateEntity(rx,ry,rz)
   CameraViewport(Cam,0,0,1024,768)   
   RenderWorld   
   Flip 
   
Wend

EndGraphics
End




This is cool, I was just reading about the frame buffer objects.

However, I see nowhere in your code where you do what you said you needed to do - check if the support string includes the extension you're using. Can you show code that includes how this would be done in BlitzMax?

Also, what extensions do you suggest might be needed to set up a floating point texture and use it as a framebuffer?

Here is my current code how to detect the extensions available by your Graphicscard.

Import klepto.minib3d

Graphics3D 800,600,32,2

THardwareInfo.GetInfo()
THardwareInfo.DisplayInfo()

If THardwareInfo.FBOSupport = True Then
	Print "FBO supported!"
Else
	Print "FBO not supported!"
EndIf

Type THardwareInfo
	Global ScreenWidth  : Int
	Global ScreenHeight : Int
	Global ScreenDepth  : Int
	Global ScreenHertz  : Int

	Global Vendor     : String
	Global Renderer   : String
	Global OGLVersion : String

	Global Extensions      : String
	Global VBOSupport      : Int ' Vertex Buffer Object
	Global GLTCSupport     : Int ' OpenGL's TextureCompression
	Global S3TCSupport     : Int ' S3's TextureCompression
	Global AnIsoSupport    : Int ' An-Istropic Filtering
	Global MultiTexSupport : Int ' MultiTexturing
	Global TexBlendSupport : Int ' TextureBlend
	Global CubemapSupport  : Int ' CubeMapping
	Global DepthmapSupport : Int ' DepthTexturing
	Global VPSupport       : Int ' VertexProgram (ARBvp1.0)
	Global FPSupport       : Int ' FragmentProgram (ARBfp1.0)
	Global ShaderSupport   : Int ' glSlang Shader Program
	Global VSSupport       : Int ' glSlang VertexShader
	Global FSSupport       : Int ' glSlang FragmentShader
	Global SLSupport       : Int ' OpenGL Shading Language 1.00
	Global FBOSupport		  : Int 'FBOSupport

	Global MaxTextures : Int
	Global MaxTexSize  : Int
	Global MaxLights   : Int

	Function GetInfo()
		Local Extensions:String

		' Get HardwareInfo
		Vendor     = String.FromCString(Byte Ptr(glGetString(GL_VENDOR)))
		Renderer   = String.FromCString(Byte Ptr(glGetString(GL_RENDERER))) 
		OGLVersion = String.FromCString(Byte Ptr(glGetString(GL_VERSION)))

		' Get Extensions
		Extensions = String.FromCString(Byte Ptr(glGetString(GL_EXTENSIONS)))
		THardwareInfo.Extensions = Extensions

		' Check for Extensions
		THardwareInfo.VBOSupport      = Extensions.Find("GL_ARB_vertex_buffer_object") > -1
		THardwareInfo.GLTCSupport     = Extensions.Find("GL_ARB_texture_compression")
		THardwareInfo.S3TCSupport     = Extensions.Find("GL_EXT_texture_compression_s3tc") > -1
		THardwareInfo.AnIsoSupport    = Extensions.Find("GL_EXT_texture_filter_anisotropic")
		THardwareInfo.MultiTexSupport = Extensions.Find("GL_ARB_multitexture") > -1
		THardwareInfo.TexBlendSupport = Extensions.Find("GL_EXT_texture_env_combine") > -1
		THardwareInfo.CubemapSupport  = Extensions.Find("GL_ARB_texture_cube_map") > -1
		THardwareInfo.DepthmapSupport = Extensions.Find("GL_ARB_depth_texture") > -1
		THardwareInfo.VPSupport       = Extensions.Find("GL_ARB_vertex_program") > -1
		THardwareInfo.FPSupport       = Extensions.Find("GL_ARB_fragment_program") > -1
		THardwareInfo.ShaderSupport   = Extensions.Find("GL_ARB_shader_objects") > -1
		THardwareInfo.VSSupport       = Extensions.Find("GL_ARB_vertex_shader") > -1
		THardwareInfo.FSSupport       = Extensions.Find("GL_ARB_fragment_shader") > -1
		THardwareInfo.SLSupport = Extensions.Find("GL_ARB_shading_language_100") > - 1
		THardwareInfo.FBOSupport = Extensions.Find("GL_EXT_framebuffer_object")
		
		If THardwareInfo.VSSupport = False Or THardwareInfo.FSSupport = False Then
			THardwareInfo.ShaderSupport = False
		EndIf

		' Get some numerics
		glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(THardwareInfo.MaxTextures))
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, Varptr(THardwareInfo.MaxTexSize))
		glGetIntegerv(GL_MAX_LIGHTS, Varptr(THardwareInfo.MaxLights))
	End Function

	Function DisplayInfo(LogFile:Int=False)
		Local position:Int, Space:Int, stream:TStream

		If LogFile Then
			stream = WriteStream("MiniB3DLog.txt") 
			stream.WriteLine("MiniB3D Hardwareinfo:")
			stream.WriteLine("")

			' Display Driverinfo
			stream.WriteLine("Vendor:         "+Vendor)
			stream.WriteLine("Renderer:       "+Renderer)
			stream.WriteLine("OpenGL-Version: "+OGLVersion)
			stream.WriteLine("")

			' Display Hardwareranges
			stream.WriteLine("Max Texture Units: "+MaxTextures)
			stream.WriteLine("Max Texture Size:  "+MaxTexSize)
			stream.WriteLine("Max Lights:        "+MaxLights)
			stream.WriteLine("")

			' Display OpenGL-Extensions
			stream.WriteLine("OpenGL Extensions:")
			While position < Extensions.length
				Space = Extensions.Find(" ", position)
				If Space = -1 Then Exit
				stream.WriteLine(Extensions[position..Space])
				position = Space+1
			Wend

			stream.WriteLine("")
			stream.WriteLine("- Ready -")
			stream.Close()
		Else
			Print("MiniB3D Hardwareinfo:")
			Print("")

			' Display Driverinfo
			Print("Vendor:         "+Vendor)
			Print("Renderer:       "+Renderer)
			Print("OpenGL-Version: "+OGLVersion)
			Print("")

			' Display Hardwareranges
			Print("Max Texture Units: "+MaxTextures)
			Print("Max Texture Size:  "+MaxTexSize)
			Print("Max Lights:        "+MaxLights)
			Print("")

			' Display OpenGL-Extensions
			Print("OpenGL Extensions:")
			While position < Extensions.length
				Space = Extensions.Find(" ", position)
				If Space = -1 Then Exit
				Print(Extensions[position..Space])
				position = Space+1
			Wend

			Print("")
			Print("- Ready -")
		EndIf
	End Function
End Type



And for the floating point extension I would suggest to check for : 'GL_ARB_texture_float' for floating point textures. But I haven't used them yet. For what are these textures needed?

Nice, thanks.

Floating point would be for HDR image buffers and rendering. I'm working towards a graphics app and it would be extremely useful to use framebuffer objects with more than just RGBA8888 data, e.g. Float16, Float32, Float64, also 16 or 32 bits per color component. If this can be utilized in the graphics card with video ram and being able to render to/from it with hardware acceleration that would be MUCH preferred and MUCH faster than the software-driven code I would otherwise have to write.

btw klepto your code is missing a couple of >-1 on the end of the tests for extensions - particularly for the frame buffer object and texture compression.

Add >-1 on the end to properly report.

FBO wouldn't be my first choice of things to play around with... PBuffers / CopyTex are faster, less ambiguous and have better state management mechanisms.

But if your just playing around :) it's your time.

You know the difference between PBuffers and Pixel Buffer Objects? It seems you throw things together.
FBOs are the currently most supported and fastest method to do rendertotexture. PBuffers are a lot harder to implement and to handle. CopyTex, it is as fast as FBOs on some machines but tests by some friends of mine (my ATI seems to be corrupted on RTT) gives around 20% better speed with FBOs. At least because
you don't have to transfer the pixeldata to the texture instead it is dirctly rendered to it.

I would agree, haven't done a speed test but from what I've read FBO's supercede all functionality of pbuffers, are more flexible and dont require a separate context for each buffer. I would think definitely the FBO is faster than drawing to the backbuffer, grabbing the backbuffer, then clearing the screen.

I think I know the difference :)

PBuffer vs FBO, it's sort of a religion thing. There are equal trade offs for both but since I implemented PBuffers and I work on the Opengl Framework on Mac OS X I think I understand a bit more than most on this :)

But when using a shared context a PBuffer is a very fast mechanism to do render to texture and the shared context retains your opengl state and there are other benefits for PBuffers.

If I wanted to hold the company line I would say FBO FBO FBO... but I think people should make up their own mind on this.

I tried this sample and after compiling prg show that FBO isn't suported, but it's strange because i have NV 8800 GTX. What is problem?

If THardwareInfo.FBOSupport = True Then
	Print "FBO supported!"
Else
	Print "FBO not supported!"
EndIf

Am I Wrong ?
+> Extensions.Find("ARGUMENT") will return a number if found ( else -1).
So Extensions.Find("GL_EXT_framebuffer_object") might return any number if available

if you check :
If THardwareInfo.FBOSupport = True

if will test only if FBOSupport=1 and might return false

so it should be :
If THardwareInfo.FBOSupport > -1


Of course you're right, it was a small bug. I've forgotten to add "> -1" after the find method. So the correct line should be this:
		THardwareInfo.FBOSupport = Extensions.Find("GL_EXT_framebuffer_object") > -1


Whatever, really a good job on this module !
I don't use minib3d at all, but parts of your code help me sometimes to solve problems on my own engine, So many thanks for that :)