ShaderrControl

BlitzMax Forums/OpenGL Module/ShaderrControl

AntonyWells(Posted 2005) [#1]
Just a little lib that lets you very easily load and use either vertex/pixel shader glsl progs in blitzmax.

Type ShaderControl
	
	Method New()
		
		pObj = glCreateProgramObjectArb()
		If Not pObj Throw "Unable to find asscoitable gl context for shader instance"
				
	End Method
	
	Function Load(VertFile:String,PixFile:String )
		
'		Local out:shaderCotrol = New ShaderControl
'		out.loadFile
		
	End Function
	
	Method loadFile(vertFile:String,pixFile:String)
	
		If vertFile<>"" 
			
			Vert = VertexShader.Create()
			Vert.LoadFile( vertFile )
							
		EndIf
		
		If pixFile<>""
		
			Frag = PixelShader.Create()
			Frag.LoadFile( pixFile )
			
		EndIf
					
	End Method
		
	Method Register( VertShader:Shader,PixShader:Shader )
		
		Vert=VertShader
		Frag=PixShader
		Self.Compile()
				
	End Method
	
	'Function Create:ShaderControl(VertShader:Shader,PixShader:Shader)
		
	'	Local out:ShaderControl = New shadercontrol
	'	out.vert = vertShader
	'	out.frag = pixShader
	'	Return out
		
	'End Function
	
	Method Compile()
		
		If vert<>Null vert.compile()
		If frag<>Null frag.compile()
		isAttached = False
		attachShaders()
		glLinkProgramArb(pobj)
		
	End Method
	
	Method bind()
	
		If Not isAttached
			
			self.attachShaders()
		
		EndIf
		
		If frag<>Null
		glEnable(GL_FRAGMENT_PROGRAM_ARB)
		
		EndIf
		If vert<>Null
		
		EndIf
		
		glUseProgramObjectArb(pobj)
		
	End Method
	
	Method unbind()

		glUseProgramObjectArb(0)
	
	End Method
	
	
	Method detachShaders()
		
		If vert<>Null
		gldetachobjectarb( pObj,vert.objId )
		EndIf
		
		If frag<>Null
			gldetachobjectarb( pobj,frag.objId )
		EndIf
				
	
	End Method
		
	Method attachShaders()
		
		If vert<>Null
		glAttachObjectArb( pObj,vert.objid )
		EndIf
	
		If frag<>Null
			glattachobjectArb( pobj,frag.objId)
		End If
		
		isAttached = True
	
	End Method
	
	
	Method reload()
	
		If vert<>Null vert.reload()
		If frag<>Null frag.reload()
		isAttached=False
					
	End Method
			
	Field Vert:Shader,Frag:Shader
	Field pObj
	Field isAttached:Byte
	
End Type


Type Shader
	'Function create:shader() Abstract
	
	Method Delete()
	
		glDeleteObjectArb( objId )
			
	End Method
	
	Method LoadFile( File:String,andCompile = True)
		
		Local fileIn=ReadFile( file )
		If Not fileIn Throw "Shader "+File+" Not found"
		Local siz=FileSize( file )
		source = New Byte[siz+1]
				
		Local j	
		
		While Not Eof( fileIn )
			
			source[j] = ReadByte( fileIn )
			j:+1
			If j>siz j=siz
					
		Wend
		CloseFile fileIn
		source[j]=0
		Local shaderPtr:Byte Ptr[1]
		shaderPtr[0] = Varptr(source[0])	
		glShaderSourceArb( objId,1,shaderPtr,Null)
		isCompiled=False	
		If andCompile self.compile()
		
	End Method
	
	Method Compile()
	
		If Not isCompiled
			glCompileShaderArb(objId)
			isCompiled=True
		EndIf
			
	End Method
	
	Method Reload()
	
		loadFile( lastFile )
		If isCompiled 
			isCompiled=False
			compile()
		End If
		
	End Method
	
	
	Field lastFile:String
	Field objID,isCompiled:Byte
	Field source:Byte[]
		
End Type

Type PixelShader Extends Shader

	Function create:Shader()
		
		Local out:shader = New PixelShader
		out.objId = glCreateShaderObjectArb( GL_FRAGMENT_SHADER )
		Return out
		
	End Function
		
End Type

Type VertexShader Extends Shader
	
	Function create:Shader()

		Local out:shader = New vertexshader
		out.objid = glCreateShaderObjectARB( GL_VERTEX_SHADER )
		Return out
			
	End Function
	
End Type


example

Local SC:ShaderControl = New ShaderControl
Local VS:Shader = New vertexShader
Local PS:Shader = New PixelShader

ps.LoadFile("shader\fragmentShader.glsl")
Sc.Register( Null,Ps )
Sc.Bind() 'activate shader. will be mapped to any following gl drawings. (I.e don't use maxdx7 drivers or it won't work.)

use sc.unbind() to deactivate.


You can dynamically reload/recompile shaders by calling Shader.Reload()

or call reload from the shader controller to reload any shaders asscoiated with it.


AntonyWells(Posted 2005) [#2]
Meant to put this in the showcase..


AntonyWells(Posted 2005) [#3]
new version. you can now set uniform and dynamic variables in glsl programs from within blitz at runtime.

Type ShaderControl
	
	Method New()
		
		pObj = glCreateProgramObjectArb()
		If Not pObj Throw "Unable to find asscoitable gl context for shader instance"
				
	End Method
	
	Function Load(VertFile:String,PixFile:String )
		
'		Local out:shaderCotrol = New ShaderControl
'		out.loadFile
		
	End Function
	
	Method loadFile(vertFile:String,pixFile:String)
	
		If vertFile<>"" 
			
			Vert = VertexShader.Create()
			Vert.LoadFile( vertFile )
							
		EndIf
		
		If pixFile<>""
		
			Frag = PixelShader.Create()
			Frag.LoadFile( pixFile )
			
		EndIf
					
	End Method
		
	Method Register( VertShader:Shader,PixShader:Shader )
		
		Vert=VertShader
		Frag=PixShader
		Self.Compile()
				
	End Method
	
	'Function Create:ShaderControl(VertShader:Shader,PixShader:Shader)
		
	'	Local out:ShaderControl = New shadercontrol
	'	out.vert = vertShader
	'	out.frag = pixShader
	'	Return out
		
	'End Function
	
	Method Compile()
		
		If vert<>Null vert.compile()
		If frag<>Null frag.compile()
		isAttached = False
		attachShaders()
		glLinkProgramArb(pobj)
		
	End Method
	
	Method bind()
	
		If Not isAttached
			
			self.attachShaders()
		
		EndIf
		
		If frag<>Null
	
			glEnable(GL_FRAGMENT_PROGRAM_ARB)
		
		EndIf
	
		If vert<>Null
	
			glenable(GL_VERTEX_PROGRAM_ARB)
	
		EndIf
		
		glUseProgramObjectArb(pobj)
		
	End Method
	
	Method unbind()

		glUseProgramObjectArb(0)
		If frag<>Null gldisable(GL_FRAGMENT_PROGRAM_ARB)
		If vert<>Null gldisable(GL_VERTEX_PROGRAM_ARB)
				
	End Method
	
	
	Method detachShaders()
		
		If vert<>Null
			gldetachobjectarb( pObj,vert.objId )
		EndIf
				
		If frag<>Null
			gldetachobjectarb( pobj,frag.objId )
		EndIf
				
	
	End Method
		
	Method attachShaders()
		
		If vert<>Null
			glAttachObjectArb( pObj,vert.objid )
		EndIf
	
		If frag<>Null
			glattachobjectArb( pobj,frag.objId)
		End If
		
		isAttached = True
	
	End Method
	
	
	Method reload()
	
		If vert<>Null vert.reload()
		If frag<>Null frag.reload()
		isAttached=False
					
	End Method
	
	Method GetStaticFloat:shaderVar(name:String,size:Int=1)
		
		Local out:ShaderVar = New shaderFloatStatic
		out.setup( pObj,name )
		Return out
	
	End Method
		
	Method GetDynamicFloat:ShaderVar(name:String,size:Int=1)

		Local out:ShaderVar = New shaderFloatDynamic
		out.setup( pObj,name )
		Return out
		
	End Method
				
	Field Vert:Shader,Frag:Shader
	Field pObj
	Field isAttached:Byte
	
End Type

Type ShaderVar

	Method Set( Val:Float ) Abstract
		
	Method Setup( programObject,VariableName:String ) Abstract
	
	
	Field vId
		
End Type


Type ShaderFloatStatic Extends ShaderVar

	Method Set( Val:Float)
	
		glUniform1farb(vid,val)
	
	End Method
	
	Method Setup( programObject,VariableName:String ) 
		
		vid = glGetUniformlocationArb( programObject,variableName )
	
	End Method
	
End Type

Type ShaderFloatDynamic Extends ShaderVar

	Method Set( Val:Float)
	
		glVertexAttrib1fARB(vid,val)
	
	End Method
	
	Method Setup( programObject,VariableName:String ) 
		
		vid = glGetAttribLocationARB( programObject,variableName )
	
	End Method
	
End Method

Type Shader
	'Function create:shader() Abstract
	
	Method Delete()
	
		glDeleteObjectArb( objId )
			
	End Method
	
	Method LoadFile( File:String,andCompile = True)
		
		Local fileIn=ReadFile( file )
		If Not fileIn Throw "Shader "+File+" Not found"
		Local siz=FileSize( file )
		source = New Byte[siz+1]
		lastFile = fileIn
		Local j	
		
		While Not Eof( fileIn )
			
			source[j] = ReadByte( fileIn )
			j:+1
			If j>siz j=siz
					
		Wend
		CloseFile fileIn
		source[j]=0
		Local shaderPtr:Byte Ptr[1]
		shaderPtr[0] = Varptr(source[0])	
		glShaderSourceArb( objId,1,shaderPtr,Null)
		isCompiled=False	
		If andCompile self.compile()
		
	End Method
	
	Method Compile()
	
'		If Not isCompiled
			glCompileShaderArb(objId)
			isCompiled=True
'		EndIf
			
	End Method
	
	Method Reload()
	
		loadFile( lastFile )
		If isCompiled 
			isCompiled=False
			compile()
		End If
		
	End Method
	
	
	Field lastFile:String
	Field objID,isCompiled:Byte
	Field source:Byte[]
		
End Type

Type PixelShader Extends Shader

	Method New()
		objId = glCreateShaderObjectArb( GL_FRAGMENT_SHADER )
	End Method
	
	Function create:Shader()
		
		Return New PixelShader
		
	End Function
		
End Type

Type VertexShader Extends Shader
	
	Method New()
	
		objid = glCreateShaderObjectARB( GL_VERTEX_SHADER )
		
	End Method
		
	Function create:Shader()

	 	Return New vertexshader
					
	End Function
	
End Type



Local VS:Shader = New vertexShader
Local PS:Shader = New pixelshader

vs.loadfile("shader\lightvert.glsl")
ps.LoadFile("shader\lightfrag.glsl")

Global SC:ShaderControl = New ShaderControl
Sc.Register( vs,Ps )
Sc.Bind()

Global Scale:ShaderVar = Sc.GetStaticFloat( "Scale" )

Scale.Set( 5 )




Chris C(Posted 2005) [#4]
If you'd like to put together a working example I'd be happy to host it, I'd like to put together a collection of slick working examples for blitzmax


AntonyWells(Posted 2005) [#5]
Thanks for the offer, but I recently bought my own domain etc for this (www.dreamspaced.com - nowt there yet tho)
But I'm fine with you including the demos I do in your set of examples. (Will be using vivid2.0 though, even the ones using this)


visionastral(Posted 2005) [#6]
Thank you for the code, i was looking for that! :-)
are you the vivid lite creator? because I paid a copy long long ago and i still haven't a vivid lite copy....