tom speed made a nice file to help with shaders so I had a twiddle with it, had to change a few bits because of how bmax has progressed recently
heres the results of my experiments, I hope you find it useful.
test.frag
test.vert
shadertest.bmx
tom speeds modifield glsl.bmx
heres the results of my experiments, I hope you find it useful.
test.frag
uniform vec4 color; varying vec2 vPosition; varying vec3 vNormal; void main(void) { float diffuse = 0.3 + 0.5 * dot(vNormal.xy, vNormal.xy); // Create a grid pattern vec2 fp=fract(4.0*vPosition.xy); fp *= (1.0 - fp); gl_FragColor = color * (fp.x + fp.y +1.0) * diffuse; }
test.vert
//uniform float noiseRate; varying vec3 vPosition; varying vec3 vNormal; void main(void) { // Move it down a little for a better view vec4 vFinalPosition = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z , gl_Vertex.w); vFinalPosition.z=vFinalPosition.z+sin(vFinalPosition.x*320.0)*0.1; gl_Position = gl_ModelViewProjectionMatrix * vFinalPosition; // Pass position to the fragment shader vPosition = vec3(vFinalPosition); // Eye-space lighting vNormal = gl_NormalMatrix * gl_Normal; }
shadertest.bmx
Import "glsl.bmx" SetGraphicsDriver GLGraphicsDriver() GLGraphics 800,600,0,0,GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER glewInit() glClearColor(0.5, 0.5, 0.5, 0.0) ' Color to clear the screen with glClearDepth 1.0 ' The depth to clear the Zbuffer to (0.0=near clip plane, 1.0=far clip plane) glDepthFunc(GL_LESS) ' Only draw pixels if the fragment/pixel Z depth, is LESS than the Zbuffer value glEnable(GL_DEPTH_TEST) ' Enable depth testing (Z sorting of pixels) glFrontFace(GL_CW) ' Draw polys facing viewer Clockwise glShadeModel(GL_SMOOTH) glViewport(0,0,800,600) glMatrixMode(GL_PROJECTION) ' The Matrix to which subsequent Matrix operations work on glLoadIdentity() Local aspect# = Float(800)/Float(600) gluPerspective(45.0,aspect#,1.0,100.0) ' y-FoV#, Aspect#, Near#, Far# Local po:tProgramObject=New tProgramObject po=tProgramObject.create("test") Local vs:tShaderObject=New tShaderObject vs=CreateVertShader("test.vert") Local fs:tShaderObject=New tShaderObject fs=CreateFragShader("test.frag") po.AttachVertShader(vs) po.AttachFragShader(fs) Rem Global length:Int,size:Int,tp:Int,name:Byte[21] For y=0 To 5 glGetActiveUniformARB(po.program,y,20,Varptr length,Varptr size,Varptr Tp,Varptr name[0]) n$="" For Local x:Int =0 To length-1 n$=n$+Chr(name[x]) Next Print n$ Next EndRem po.Activate() po.setUF4("color",1.0,0.5,0.25,1.0) po.DeActivate() Global rtri:Float Global rquad:Float While Not KeyDown(KEY_ESCAPE) And Not AppTerminate() Local UseShader:Byte=MouseDown(1) glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT GLDrawText("hold left mouse to activate shader",20,20) glMatrixMode(GL_MODELVIEW) glLoadIdentity glTranslatef -1.5,0.0,-6.0 glRotatef rtri,0.0,1.0,0.0 ' Rotate The Triangle On The Y axis ( NEW ) glBegin GL_POLYGON glColor3f 1.0,0.0,0.0 ' Set The Color To Red glVertex3f 0.0, 1.0, 0.0 ' Top glColor3f 0.0,1.0,0.0 ' Set The Color To Green glVertex3f 1.0,-1.0, 0.0 ' Bottom Right glColor3f 0.0,0.0,1.0 ' Set The Color To Blue glVertex3f -1.0,-1.0, 0.0 ' Bottom Left glEnd glLoadIdentity glTranslatef 0.1,0.0,-6.0 ' Move Right 1.5 Units glRotatef rquad,1.0,0.0,0.0 ' Rotate The Quad On The X axis ( New ) glColor3f 0.5,0.5,1.0 ' Set The Color To Blue One Time Only If UseShader po.Activate() End If ' draw many quads so vert shader has somthing to play with! For Local vx:Float=-1 To 1 Step 0.1 For Local vy:Float=-1 To 1 Step 0.1 glBegin GL_QUADS glVertex3f vx-.05, vy+.05, 0.0 ' Top Left glVertex3f vx+.05, vy+.05, 0.0 ' Top Right glVertex3f vx+.05, vy-.05, 0.0 ' Bottom Right glVertex3f vx-.05, vy-.05, 0.0 ' Bottom Left glEnd Next Next If UseShader po.DeActivate() End If rtri = rtri + 1.2 '; Increase The Rotation Variable For The Triangle ( New ) rquad = rquad + 1 '; Decrease The Rotation Variable For The Quad ( New ) Flip Wend
tom speeds modifield glsl.bmx
'Strict Rem Module pub.glsl ModuleInfo "Version: 1.00" ModuleInfo "Author: Tom Speed set uniforms bodged by ChrisC" ModuleInfo "License: Blitz Shared Source Code" ModuleInfo "Copyrights: Unknown" ModuleInfo "Modserver: PUB" Import brl.linkedlist Import brl.standardio Import brl.filesystem Import brl.system Import pub.glew EndRem Global ProgramObjectList:TList = CreateList() Global ShaderObjectList:TList = CreateList() Global clog:Byte[1024]' = MemAlloc(linked) 'Shader Object Type Type tShaderObject Field ShaderObject:Int Field ShaderType:Int ' 1 = Vert, 2 = Frag Field Attached:TList ' Shaders can be attached, or 'referenced by', more than 1 ProgramObject Field shaderName:String End Type 'Program Object Type Type tProgramObject Field Program:Int ' The ProgramObject Field vList:TList ' Vertex shader list. A List of what Vert shaders are attached to this ProgramObject Field fList:TList ' Frag shader list. A List of what Frag shaders are attached to this ProgramObject Field progName:String Field vertShaderCount:Int Field fragShaderCount:Int '---------------------------------------------------- 'tProgramObject.Create(name:String) ' 'Creates a new Shader Program Object to which 'multiple Vert and/or Frag Shaders can be attached to ' 'Returns: The newly created Program Objects ID if ' successful, or Null if it failed. '---------------------------------------------------- Function Create:tProgramObject(name:String = "null") Local p:tProgramObject = New tProgramObject 'Create a new GL ProgramObject p.Program = glCreateProgramObjectARB() If p.Program<1 p = Null ?Debug Print "Error: glCreateProgramObjectARB() failed" ? Return Null End If '--------------------------------- 'The amount of Vert & Frag Shaders 'attached to this Program Object '--------------------------------- p.vertShaderCount = 0 p.fragShaderCount = 0 '--------------------------------------- 'These lists contain any Vert or Frag 'Shader Objects Attached to this Program '--------------------------------------- p.vList:TList = CreateList() p.fList:TList = CreateList() 'This Program Objects Name p.progName = name '------------------------------ 'Add this Program Object to the 'Global list of ProgramObjects '------------------------------ ListAddLast ProgramObjectList, p Return p End Function '--------------------------------- 'tProgramObject.Activate() ' 'Activates (uses!) a ProgramObject '--------------------------------- Method Activate() glUseProgramObjectARB(Program) End Method '---------------------------- 'tProgramObject.DeActivate() ' 'Turns off this ProgramObject '---------------------------- Method DeActivate() glUseProgramObjectARB(0) End Method ' Get the Uniform Variable Location from a ProgramObject Method GetUniLoc:Int(name:String) Return glGetUniformLocationARB(Program, Varptr name) End Method ' Get the Attribute Variable Location from a ProgramObject Method GetAttribLoc:Int(name:String) Return glGetAttribLocationARB(Program, Varptr name) End Method ' Set Uniform Variable Integer(s) Method setUI1(name:String,val:Int) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUI1" Return End If ? glUniform1iARB(loc,val) End Method Method setUI2(name:String,val1:Int,val2:Int) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUI2" Return End If ? glUniform2iARB(loc,val1,val2) End Method Method setUI3(name:String,val1:Int,val2:Int,val3:Int) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUI3" Return End If ? glUniform3iARB(loc,val1,val2,val3) End Method Method setUI4(name:String,val1:Int,val2:Int,val3:Int,val4:Int) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUI4" Return End If ? glUniform4iARB(loc,val1,val2,val3,val4) End Method Method getUI1:Int(name:String) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method getUI1" Return End If ? Local val:Int = 10 glGetUniformivARB(Program, loc, Varptr(val)) Return val End Method ' Set Uniform Variable Float(s) Method setUF1(name:String,val:Float) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUF1" Return End If ? glUniform1fARB(loc,val) End Method Method setUF2(name:String,val1:Float,val2:Float) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString() ) ?Debug If loc<0 Print ">Error getting Uniform Var Location '"+name+"' in Method setUF2" Return End If ? glUniform2fARB(loc,val1,val2) End Method Method setUF3(name:String,val1:Float,val2:Float,val3:Float) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUF3" Return End If ? glUniform3fARB(loc, val1, val2, val3) End Method Method setUF4(name:String,val1:Float,val2:Float,val3:Float,val4:Float) Local loc:Int = glGetUniformLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Uniform Var Location '"+name+"' in Method setUF4" Return End If ? glUniform4fARB(loc,val1,val2,val3,val4) End Method ' Set Attribute Variable Short(s) Method setAS1(name:String, val1:Short) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAS1" Return End If ? glVertexAttrib1sARB(loc, val1) End Method Method setAS2(name:String, val1:Short, val2:Short) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAS2" Return End If ? glVertexAttrib2sARB(loc, val1, val2) End Method Method setAS3(name:String, val1:Short, val2:Short, val3:Short) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAS3" Return End If ? glVertexAttrib3sARB(loc, val1, val2, val3) End Method Method setAS4(name:String, val1:Short, val2:Short, val3:Short, val4:Short) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAS4" Return End If ? glVertexAttrib4sARB(loc, val1, val2, val3, val4) End Method ' Set Attribute Variable Float(s) Method setAF1(name:String, val1:Float) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAF1" Return End If ? glVertexAttrib1fARB(loc, val1) End Method Method setAF2(name:String, val1:Float, val2:Float) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAF2" Return End If ? glVertexAttrib2fARB(loc, val1, val2) End Method Method setAF3(name:String, val1:Float, val2:Float, val3:Float) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAS3" Return End If ? glVertexAttrib3fARB(loc, val1, val2, val3) End Method Method setAF4(name:String, val1:Float, val2:Float, val3:Float, val4:Float) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAF4" Return End If ? glVertexAttrib4fARB(loc, val1, val2, val3, val4) End Method ' Set Attribute Variable Double(s) Method setAD1(name:String, val1:Double) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAD1" Return End If ? glVertexAttrib1fARB(loc, val1) End Method Method setAD2(name:String, val1:Double, val2:Double) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAD2" Return End If ? glVertexAttrib2fARB(loc, val1, val2) End Method Method setAD3(name:String, val1:Double, val2:Double, val3:Double) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAD3" Return End If ? glVertexAttrib3fARB(loc, val1, val2, val3) End Method Method setAD4(name:String, val1:Double, val2:Double, val3:Double, val4:Double) Local loc:Int = glGetAttribLocationARB(Program, name.ToCString()) ?Debug If loc<0 Print "Error getting Attribute Var Location '"+name+"' in Method setAD4" Return End If ? glVertexAttrib4fARB(loc, val1, val2, val3, val4) End Method '---------------------------------------------------------- 'Attach & Link a Vertex Shader Object to this ProgramObject '---------------------------------------------------------- Method AttachVertShader:Int(myShader:tShaderObject) ?Debug If Program = 0 Print "Error: Invalid tProgramObject in method AddVertShader()" Print "-------------------------------------------------------" Print Else If Not myShader Print "Error: Invalid tShaderObject passed to method AddVertShader()" Print "-------------------------------------------------------------" Print Return End If ? '-------------------------- 'Attach & Link a VertShader '-------------------------- glAttachObjectARB(Program, myShader.ShaderObject) glLinkProgramARB(Program) '------------------------------- 'Check if it Linked successfully '------------------------------- Local linked:Int glGetObjectParameterivARB(Program,GL_OBJECT_LINK_STATUS_ARB, Varptr(linked)) If Not linked ?Debug 'An Error occured during Linking 'dump the error logfile to console ' Local clog:Byte Ptr Local slen:Int = 0 glGetInfoLogARB(Program,1023,Varptr slen, Varptr clog[0]) Local err:String Local i:Int For i = 0 To slen-1 err:+Chr(clog[i]) Next Print Print "Failed to link VertexShader "+myShader.shaderName Print Print err+" "+slen ? ' FlushMem Return 0 End If ?Debug Print "VertexShader "+myShader.shaderName+" attached & linked ok!" Print ? 'Add this VertShaderObject to this ProgramObjects list ListAddLast vList, myShader 'Add this ProgramObject to this Shaders 'attached to' list ListAddLast myShader.Attached, Self Return 1 End Method '------------------------------------------------------------ 'Attach & Link a Fragment Shader Object to this ProgramObject '------------------------------------------------------------ Method AttachFragShader:Int(myShader:tShaderObject) ?Debug If Program = 0 Print "Error: Invalid tProgramObject in method AddFragShader()" Print "-------------------------------------------------------" Print Else If Not myShader Print "Error: Invalid tShaderObject passed to method AddFragShader()" Print "-------------------------------------------------------------" Print Return End If ? '-------------------------- 'Attach & Link a FragShader '-------------------------- glAttachObjectARB(Program, myShader.ShaderObject) glLinkProgramARB(Program) '------------------------------- 'Check if it Linked successfully '------------------------------- Local linked:Int glGetObjectParameterivARB(Program,GL_OBJECT_LINK_STATUS_ARB, Varptr(linked)) If Not linked ?Debug 'An Error occured during Linking 'dump the error logfile to console ' Local clog:Byte Ptr Local slen:Int = 0 glGetInfoLogARB(Program,1023,Varptr slen, Varptr clog[0]) Local err:String Local i:Int For i = 0 To slen-1 err:+Chr(clog[i]) Next Print Print "Failed to link FragShader '"+myShader.shaderName+"'" Print Print err ? ' FlushMem Return 0 End If ?Debug Print "FragShader '"+myShader.shaderName+"' attached & linked ok!" Print ? 'Add this FragShaderObject to this ProgramObjects list ListAddLast fList, myShader 'Add this ProgramObject to this Shaders 'attached to' list ListAddLast myShader.Attached, Self 'Return Ok! Return 1 End Method '------------------------------------------------------- 'Detach a VertShader:tShaderObject from a tProgramObject '------------------------------------------------------- Method DetachVertShader(vShader:tShaderObject) If ListContains(vList,vShader) glDetachObjectARB(Program, vShader.ShaderObject) RemoveLink(ListFindLink(vList,vShader)) RemoveLink(ListFindLink(vShader.Attached, Self)) ?Debug Print "Detached '"+vShader.shaderName+"' from ProgramObject '"+Self.progName+"'" ? End If End Method '------------------------------------------------------- 'Detach a FragShader:tShaderObject from a tProgramObject '------------------------------------------------------- Method DetachFragShader(fShader:tShaderObject) If ListContains(fList,fShader) glDetachObjectARB(Program, fShader.ShaderObject) RemoveLink(ListFindLink(fList,fShader)) RemoveLink(ListFindLink(fShader.Attached, Self)) ?Debug Print "Detached '"+fShader.shaderName+"' from ProgramObject '"+Self.progName+"'" ? End If End Method '------------------------------------------------------ 'Dump a list of Shaders attached to this tProgramObject '------------------------------------------------------ Method ListAttachedShaders() Print "Vertex Shader(s) attached to ProgramObject '"+Self.progName+"'" Print "----------------------------------------------------------------------" If vList.Count() = 0 Print "No Vertex Shaders attached" Else For Local v:tShaderObject = EachIn vList Print v.shaderName Next End If Print Print "Fragment Shader(s) attached to ProgramObject '"+Self.progName+"'" Print "-----------------------------------------------------------------------" If fList.Count() = 0 Print "No Fragment Shaders attached" Else For Local f:tShaderObject = EachIn fList Print f.shaderName Next End If Print End Method End Type '----------------------------------------------------------- 'CreateVertShader:tShaderObject(shaderFileName:String) ' 'Creates a Vertex Shader Object from a File ' 'Returns: A tShaderObject if successful, or Null if it fails '----------------------------------------------------------- Function CreateVertShader:tShaderObject(shaderFileName:String) ' Load the shader and dump it into a Byte Array Local file:TStream = ReadFile(shaderFileName) If Not file ?Debug Print "Error, can not load file: "+shaderFileName ? Return Null End If Local tempShaderName:String = StripAll(shaderfileName)+"."+ExtractExt(shaderfileName) Local FileLength:Int = FileSize(shaderFileName) Local ShaderObject:Int Local myShader:tShaderObject = New tShaderObject myShader.ShaderObject = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB) myShader.shaderType = 1 ' 1 = Vert, 2 = Frag/Pixel Local i:Int = 0 Local shaderSrc:Byte[FileLength+1] While Not Eof(file) shaderSrc[i] = ReadByte(file) i:+1 If i>FileLength Then i = FileLength Wend CloseFile(file) ' Null terminate it shaderSrc[i] = 0 'Null terminate (important!) Local shaderLen:Int[1] shaderLen[0] = i Local shaderPtr:Byte Ptr[1] shaderPtr[0] = Varptr(shaderSrc[0]) ' Send shader to ShaderObject, then compile it glShaderSourceARB(myShader.ShaderObject,1, shaderPtr, Null) Local time:Int = MilliSecs() glCompileShaderARB(myShader.ShaderObject) time = (MilliSecs()-time) ' Did the shader compile successfuly? Local compiled:Int glGetObjectParameterivARB(myShader.ShaderObject,GL_OBJECT_COMPILE_STATUS_ARB, Varptr(compiled)) If Not compiled ?Debug ' Get the cause of the error Local logLength:Int glGetObjectParameterivARB(myShader.ShaderObject,GL_OBJECT_INFO_LOG_LENGTH_ARB, Varptr(logLength)) Print "Failed to compile "+tempShaderName Print ' Local clog:Byte Ptr Local slen:Int = 0 glGetInfoLogARB(myShader.ShaderObject,1023,Varptr(slen), Varptr clog[0]) Local err:String For i = 0 To logLength-1 err:+Chr(clog[i]) Next Print err ? myShader = Null ' FlushMem Return Null End If ?Debug Print "Compiled: "+tempShaderName+" successfuly in "+time+"ms" Print ? myShader.Attached = New TList myShader.shaderName = tempShaderName ListAddLast ShaderObjectList, myShader ' FlushMem Return myShader End Function '----------------------------------------------------------- 'CreateFragShader:tShaderObject(shaderFileName:String) ' 'Creates a Fragment Shader Object from a File ' 'Returns: A tShaderObject if successful, or Null if it fails '----------------------------------------------------------- Function CreateFragShader:tShaderObject(shaderFileName:String) 'Check the File exists Local file:TStream = ReadFile(shaderFileName) If Not file ?Debug Print "Error: Could not Load File: "+shaderFileName ? Return Null End If Local tempShaderName:String = StripAll(shaderfileName)+"."+ExtractExt(shaderfileName) Local FileLength:Int = FileSize(shaderFileName) Local ShaderObject:Int Local myShader:tShaderObject = New tShaderObject myShader.ShaderObject = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB) myShader.shaderType = 2 Local i:Int = 0 'Create a Byte Array to which the Shader Source will be copied to 'The extra Array Byte (FileLength+1) is so we can Null terminate the array Local shaderSrc:Byte[FileLength+1] While Not Eof(file) shaderSrc[i] = ReadByte(file) i:+1 If i>FileLength Then i = FileLength Wend CloseFile(file) 'Null terminate it shaderSrc[i] = 0 'Null terminate (important!) 'The Length of the Source Local shaderLen:Int[1] shaderLen[0] = i 'A Byte Pointer Array that points to the Shader Source Local shaderPtr:Byte Ptr[1] shaderPtr[0] = Varptr(shaderSrc[0]) 'Send the Shader to the ShaderObject, then Compile it glShaderSourceARB(myShader.ShaderObject,1, shaderPtr, Null) Local time:Int = MilliSecs() glCompileShaderARB(myShader.ShaderObject) time = (MilliSecs()-time) 'Did the shader compile successfuly? Local compiled:Int glGetObjectParameterivARB(myShader.ShaderObject,GL_OBJECT_COMPILE_STATUS_ARB, Varptr(compiled)) If Not compiled ?Debug 'Get the cause of the error Local logLength:Int glGetObjectParameterivARB(myShader.ShaderObject,GL_OBJECT_INFO_LOG_LENGTH_ARB, Varptr(logLength)) Print "Failed to compile "+tempShaderName Print ' Local clog:Byte Ptr Local slen:Int = 0 ' clog = GCMalloc(logLength) glGetInfoLogARB(myShader.ShaderObject,1024,Varptr(slen), Varptr clog[0]) Local err:String For i = 0 To logLength-1 err:+Chr(clog[i]) Next Print err ? myShader = Null ' FlushMem Return Null End If ?Debug Print "Compiled: "+tempShaderName+" successfuly in "+time+"ms" Print ? 'Create a list of what ProgramObjects this Shader is Attached to myShader.Attached = New TList myShader.shaderName = tempShaderName ListAddLast ShaderObjectList, myShader ' FlushMem Return myShader End Function Function DeleteVertShader(vShader:tShaderObject Var) If Not vShader Return RemoveLink(ListFindLink(ShaderObjectList,vShader)) ' Detach this ShaderObject from all ProgramObjects it was attached to For Local p:tProgramObject = EachIn ProgramObjectList If ListContains(p.vList, vShader) p.DetachVertShader(vShader) End If Next ' Delete the shader glDeleteObjectARB(vShader.ShaderObject) ?Debug Print "Deleted ShaderObject '"+vShader.shaderName+"'" Print ? vShader = Null ' FlushMem End Function Function DeleteFragShader(fShader:tShaderObject Var) If Not fShader Return RemoveLink(ListFindLink(ShaderObjectList,fShader)) ' Detach this ShaderObject from all ProgramObjects it was attached to For Local p:tProgramObject = EachIn ProgramObjectList If ListContains(p.fList, fShader) p.DetachFragShader(fShader) End If Next ' Delete the shader glDeleteObjectARB(fShader.ShaderObject) ?Debug Print "Deleted ShaderObject '"+fShader.shaderName+"'" Print ? fShader = Null ' FlushMem End Function ' FlushMem 'End Function