ShaderrControl

BlitzMax Forums/BlitzMax OpenGL Programming/ShaderrControl

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.

Meant to put this in the showcase..

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 )



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

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)

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....