
(Tested in Win10)
Code: Select all
; *****************************************************************************
; Implementation of Colored Sprites and other stuff with GLSL in a PB Module
;
; www.raxntrax.com, 2021 by SQ4
; *****************************************************************************
CompilerIf #PB_Compiler_OS = #PB_OS_Windows And Subsystem("OpenGL") = #False
CompilerError "OpenGL subsystem needs to be set in compiler options!"
CompilerEndIf
DeclareModule GLSL
Enumeration
#GLSLType_Sprite
#GLSLType_Program ;Why not (needs just another fragment shader)
EndEnumeration
Declare Open(WindowID, x,y,w,h)
Declare Close()
Declare StartRender(color=$0)
Declare StopRender()
Declare.i LoadObject(Type, File.s)
Declare.i CatchObject(Type, Buffer.i,w,h)
Declare DrawObject(Object, x,y,w,h,angle.f,color=$ffffffff)
EndDeclareModule
Module GLSL
#GL_COLOR_BUFFER_BIT = $00004000
#GL_DEPTH_BUFFER_BIT = $00000100
#GL_ARRAY_BUFFER = $8892
#GL_ELEMENT_ARRAY_BUFFER = $8893
#GL_MODELVIEW = $1700
#GL_PROJECTION = $1701
#GL_SMOOTH = $1D01
#GL_DEPTH_TEST = $0B71
#GL_CULL_FACE = $0B44
#GL_STATIC_DRAW = $88E4
#GL_VERTEX_ARRAY = $8074
#GL_FLOAT = $1406
#GL_TRIANGLES = $0004
#GL_UNSIGNED_BYTE = $1401
#GL_UNSIGNED_SHORT = $1403
#GL_UNSIGNED_INT = $1405
#GL_ARRAY_BUFFER = $8892
#GL_STATIC_DRAW = $88E4
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30
#GL_TEXTURE0 = $84C0
#GL_TEXTURE1 = $84C1
#GL_BGR = $80E0
#GL_BGRA = $80E1
#GL_RGB = $1907
#GL_RGBA = $1908
Prototype glGenBuffers( n.i, *buffers)
Prototype glBindBuffer( target.l, buffer.i)
Prototype glBufferData ( target.l, size.i, *Data_, usage.l)
Prototype glBufferSubData ( target.l, offset.i, size.i, *Data_)
Prototype glGenVertexArrays (n.i, *arrays)
Prototype glBindVertexArray(n.i)
Prototype glEnableVertexAttribArray ( index.i )
Prototype glVertexAttribPointer ( index.i, size.i, type.l, normalized.b, stride.i, *pointer )
Prototype glDrawArrays ( mode.l, first.i, count.i )
Prototype glIndexPointer ( enum.i, stride.i, *length )
Prototype glDeleteBuffers ( n.i, *buffers)
Prototype glDeleteVertexArrays ( n.i, *buffers)
Prototype glDisableVertexAttribArray(index.i)
Prototype glMapBuffer(Target.i, Access.i)
Prototype glUnmapBuffer(Target.i)
Prototype glActiveTexture(Texture.l)
Prototype glUniformMatrix4fv(location.i, count.i, transpose.b, *value)
Prototype glCreateShader(type.l)
Prototype glCreateProgram()
Prototype glCompileShader(shader.l)
Prototype glDeleteShader(ShaderObj.i)
Prototype glLinkProgram(shader.l)
Prototype glUseProgram(shader.l)
Prototype glAttachShader(Program.l, shader.l)
Prototype glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) :
Prototype glGetUniformLocation(Program.i, name.p-ascii)
Prototype glUniform1i(location.i, v0.i)
Prototype glUniform2i(location.i, v0.i, v1.i)
Prototype glUniform1f(location.i, v0.f)
Prototype glUniform2f(location.i, v0.f, v1.f)
Prototype glUniform3f(location.i, v0.f, v1.f, v2.f)
Prototype glUniform4f(location.i, v0.f, v1.f, v2.f, v3.f)
Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)
Structure _2DPoint
x.f
y.f
EndStructure
Structure _2DTex
x.f
y.f
EndStructure
Structure myTexVertex
Pos._2DPoint
Tex._2DTex
EndStructure
Structure Tindex
a.l
b.l
c.l
d.l
EndStructure
Structure Object
Type.i
Shader.i ;Object specific
Texture.i
Array uModelScale.f(3,3)
Array uRotate.f(3,3)
Array uWorldScale.f(3,3)
Array uTranslate.f(3,3)
EndStructure
Structure GLSL
W.i
H.i
Shader.i ;Default Shader
Array Vertex.myTexVertex(3)
List Objects.Object()
glGenBuffers.glGenBuffers
glBindBuffer.glBindBuffer
glBufferData.glBufferData
glBufferSubData.glBufferSubData
glGenVertexArrays.glGenVertexArrays
glBindVertexArray.glBindVertexArray
glEnableVertexAttribArray.glEnableVertexAttribArray
glVertexAttribPointer.glVertexAttribPointer
glDrawArrays.glDrawArrays
glIndexPointer.glIndexPointer
glDeleteBuffers.glDeleteBuffers
glDeleteVertexArrays.glDeleteVertexArrays
glDisableVertexAttribArray.glDisableVertexAttribArray
glMapBuffer.glMapBuffer
glUnmapBuffer.glUnmapBuffer
glActiveTexture.glActiveTexture
glUniformMatrix4fv.glUniformMatrix4fv
glCreateShader.glCreateShader
glCreateProgram.glCreateProgram
glCompileShader.glCompileShader
glDeleteShader.glDeleteShader
glLinkProgram.glLinkProgram
glUseProgram.glUseProgram
glAttachShader.glAttachShader
glShaderSource.glShaderSource
glGetUniformLocation.glGetUniformLocation
glUniform1i.glUniform1i
glUniform2i.glUniform2i
glUniform1f.glUniform1f
glUniform2f.glUniform2f
glUniform3f.glUniform3f
glUniform4f.glUniform4f
glGetShaderInfoLog.glGetShaderInfoLog
EndStructure
UseJPEGImageDecoder()
UsePNGImageDecoder()
Global GLSL.GLSL
Procedure Open(WindowID, x,y,w,h)
If InitSprite() And OpenWindowedScreen(WindowID,x,y,w,h)
;InitSprite is not necessary, but you have to disable debugger
;DisableDebugger
;If OpenWindowedScreen(WindowID,x,y,w,h)
GLSL\W=w
GLSL\H=h
GLSL\glGenBuffers = wglGetProcAddress_("glGenBuffers")
GLSL\glBindBuffer = wglGetProcAddress_("glBindBuffer")
GLSL\glBufferData = wglGetProcAddress_("glBufferData")
GLSL\glBufferSubData = wglGetProcAddress_("glBufferSubData")
GLSL\glGenVertexArrays = wglGetProcAddress_("glGenVertexArrays")
GLSL\glBindVertexArray = wglGetProcAddress_("glBindVertexArray")
GLSL\glEnableVertexAttribArray = wglGetProcAddress_("glEnableVertexAttribArray")
GLSL\glVertexAttribPointer = wglGetProcAddress_("glVertexAttribPointer")
GLSL\glDrawArrays = wglGetProcAddress_("glDrawArrays")
GLSL\glIndexPointer = wglGetProcAddress_("glIndexPointer")
GLSL\glDeleteBuffers = wglGetProcAddress_("glDeleteBuffers")
GLSL\glDeleteVertexArrays = wglGetProcAddress_("glDeleteVertexArrays")
GLSL\glDisableVertexAttribArray = wglGetProcAddress_("glDisableVertexAttribArray")
GLSL\glMapBuffer = wglGetProcAddress_("glMapBuffer")
GLSL\glUnmapBuffer = wglGetProcAddress_("glUnmapBuffer")
GLSL\glActiveTexture = wglGetProcAddress_("glActiveTexture")
GLSL\glUniformMatrix4fv=wglGetProcAddress_("glUniformMatrix4fv")
GLSL\glCreateShader = wglGetProcAddress_("glCreateShader")
GLSL\glCreateProgram = wglGetProcAddress_("glCreateProgram")
GLSL\glCompileShader = wglGetProcAddress_("glCompileShader")
GLSL\glDeleteShader = wglGetProcAddress_("glDeleteShader")
GLSL\glLinkProgram = wglGetProcAddress_("glLinkProgram")
GLSL\glUseProgram = wglGetProcAddress_("glUseProgram")
GLSL\glAttachShader = wglGetProcAddress_("glAttachShader")
GLSL\glShaderSource = wglGetProcAddress_("glShaderSource")
GLSL\glGetUniformLocation = wglGetProcAddress_("glGetUniformLocation")
GLSL\glUniform1i = wglGetProcAddress_("glUniform1i")
GLSL\glUniform2i = wglGetProcAddress_("glUniform2i")
GLSL\glUniform1f = wglGetProcAddress_("glUniform1f")
GLSL\glUniform2f = wglGetProcAddress_("glUniform2f")
GLSL\glUniform3f = wglGetProcAddress_("glUniform3f")
GLSL\glUniform4f = wglGetProcAddress_("glUniform4f")
GLSL\glGetShaderInfoLog = wglGetProcAddress_("glGetShaderInfoLog")
; Vertexes in WorldSpace
; top left
GLSL\Vertex(3)\Pos\x = -1 : GLSL\Vertex(3)\Pos\y = 1
GLSL\Vertex(3)\Tex\x = 0.0 : GLSL\Vertex(3)\Tex\y = 1.0
; top right
GLSL\Vertex(2)\Pos\x = 1 : GLSL\Vertex(2)\Pos\y = 1
GLSL\Vertex(2)\Tex\x = 1.0 : GLSL\Vertex(2)\Tex\y = 1.0
; bottom left
GLSL\Vertex(0)\Pos\x = -1 : GLSL\Vertex(0)\Pos\y = -1
GLSL\Vertex(0)\Tex\x = 0.0 : GLSL\Vertex(0)\Tex\y = 0.0
; bottom right
GLSL\Vertex(1)\Pos\x = 1 : GLSL\Vertex(1)\Pos\y = -1
GLSL\Vertex(1)\Tex\x = 1.0 : GLSL\Vertex(1)\Tex\y = 0.0
;Clockwise processing of vertexes
Dim Index.Tindex(0)
Index(0)\a = 0 : Index(0)\b = 1 : Index(0)\c = 2 : Index(0)\d = 3
GLSL\glGenVertexArrays(1, @vao)
GLSL\glGenBuffers(1, @vbo)
GLSL\glGenBuffers(1, @ebo)
GLSL\glBindVertexArray(vao)
GLSL\glBindBuffer(#GL_ARRAY_BUFFER, vbo)
GLSL\glBufferData(#GL_ARRAY_BUFFER,SizeOf(myTexVertex) * (ArraySize(GLSL\Vertex())+1),@GLSL\Vertex(), #GL_STATIC_DRAW)
GLSL\glVertexAttribPointer(0, SizeOf(_2DPoint)/SizeOf(float), #GL_FLOAT, #GL_FALSE, SizeOf(myTexVertex), 0)
GLSL\glEnableVertexAttribArray(0)
GLSL\glVertexAttribPointer(1, SizeOf(_2DTex)/SizeOf(float), #GL_FLOAT, #GL_FALSE, SizeOf(myTexVertex), OffsetOf(myTexVertex\Tex))
GLSL\glEnableVertexAttribArray(1);
GLSL\glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo)
GLSL\glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 16*(ArraySize(Index())+1), @Index(0), #GL_STATIC_DRAW)
VS$ = "#version 330 core"+#CRLF$
VS$ + "layout(location = 0) in vec2 aPos;"+#CRLF$ ; the position variable has attribute position 0
VS$ + "layout(location = 1) in vec2 aTexCoord;"+#CRLF$ ; the color variable has attribute position 1
VS$ + "out vec2 TexCoord;"+#CRLF$
VS$ + "uniform mat4 uModelScale;"+#CRLF$
VS$ + "uniform mat4 uRotate;"+#CRLF$
VS$ + "uniform mat4 uWorldScale;"+#CRLF$
VS$ + "uniform mat4 uTranslate;"+#CRLF$
VS$ + "void main() {"+#CRLF$
VS$ + "vec4 Position = vec4(aPos, 1.0, 1.0);"+#CRLF$
VS$ + "Position = uModelScale*Position;"+#CRLF$
VS$ + "Position = uRotate*Position;"+#CRLF$
VS$ + "Position = uWorldScale*Position;"+#CRLF$
VS$ + "Position = uTranslate*Position;"+#CRLF$
VS$ + "gl_Position = Position;"+#CRLF$
VS$ + "TexCoord = aTexCoord;"+#CRLF$
VS$ + "}"
FS$ = "#version 330 core"+#CRLF$
FS$ + "out vec4 FragColor;"+#CRLF$
FS$ + "in vec2 TexCoord;"+#CRLF$
FS$ + "uniform vec4 uColor;"+#CRLF$
FS$ + "uniform sampler2D uImage;"+#CRLF$
FS$ + "void main()"+#CRLF$
FS$ + "{"+#CRLF$
FS$ + " FragColor = texture(uImage, TexCoord)*uColor;"+#CRLF$
FS$ + "}"+#CRLF$
*vbuff = Ascii(VS$)
*fbuff = Ascii(FS$)
vs = GLSL\glCreateShader(#GL_VERTEX_SHADER);
GLSL\glShaderSource(vs, 1, @*vbuff, #Null) ;
GLSL\glCompileShader(vs)
buffer = AllocateMemory(512)
GLSL\glGetShaderInfoLog(vs,512,#Null,buffer)
Log$=PeekS(buffer,512,#PB_Ascii)
If Log$:Debug Log$:EndIf
FreeMemory(buffer)
fs = GLSL\glCreateShader(#GL_FRAGMENT_SHADER);
GLSL\glShaderSource(fs, 1, @*fbuff, #Null);
GLSL\glCompileShader(fs)
buffer = AllocateMemory(512)
GLSL\glGetShaderInfoLog(vs,512,#Null,buffer)
Log$=PeekS(buffer,512,#PB_Ascii)
If Log$:Debug Log$:EndIf
FreeMemory(buffer)
GLSL\Shader = GLSL\glCreateProgram();
GLSL\glAttachShader(GLSL\Shader, vs)
GLSL\glAttachShader(GLSL\Shader, fs)
GLSL\glLinkProgram(GLSL\Shader)
GLSL\glDeleteShader(vs)
GLSL\glDeleteShader(fs)
EndIf
EndProcedure
Procedure Close()
EndProcedure
Procedure StartRender(rgba=$0)
glClearColor_(Red(rgba)/255, Green(rgba)/255, Blue(rgba)/255, Alpha(rgba)/255)
glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
EndProcedure
Procedure StopRender()
;Use disabledebugger when not using InitSprite()
FlipBuffers()
EndProcedure
Procedure.i LoadObject(Type, File.s)
If FileSize(File)>0
Select Type
Case #GLSLType_Sprite
Img=LoadImage(#PB_Any,File)
If IsImage(Img)
ImgDepth=ImageDepth(Img)
If ImgDepth<>32
Img2=CreateImage(#PB_Any,ImageWidth(Img), ImageHeight(Img),32)
StartDrawing(ImageOutput(Img2))
DrawImage(ImageID(Img),0,0)
StopDrawing()
FreeImage(Img)
Img=Img2
EndIf
StartDrawing(ImageOutput(Img))
mem=DrawingBuffer()
size=DrawingBufferPitch()* ImageHeight(Img)
*Buffer=AllocateMemory(size)
CopyMemory(mem, *Buffer, size)
StopDrawing()
RetVal=CatchObject(Type, *Buffer, ImageWidth(Img), ImageHeight(Img))
FreeMemory(*Buffer)
EndIf
EndSelect
EndIf
ProcedureReturn RetVal
EndProcedure
Procedure.i CatchObject(Type, *Buffer, w, h)
Select Type
Case #GLSLType_Sprite
glGenTextures_(1, @texture)
glBindTexture_(#GL_TEXTURE_2D, texture)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP_TO_EDGE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP_TO_EDGE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
glTexImage2D_(#GL_TEXTURE_2D, 0, 4, w, h, 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, *Buffer)
AddElement(GLSL\Objects())
GLSL\Objects()\Texture=Texture
RetVal=ListIndex(GLSL\Objects())
EndSelect
ProcedureReturn RetVal
EndProcedure
Procedure DrawObject(Nr,x,y,w,h,Angle.f,rgba=$ffffffff)
If SelectElement(GLSL\Objects(), Nr)
glEnable_(#GL_BLEND)
glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)
GLSL\glUseProgram(GLSL\Shader)
GLSL\glActiveTexture(#GL_TEXTURE0);
glBindTexture_(#GL_TEXTURE_2D, GLSL\Objects()\Texture)
myCos.f=Cos(Radian(360-Angle))
mySin.f=Sin(Radian(360-Angle))
Aspect_X.f=(w/h)
Scale.f=h/GLSL\H
Sprite_X.f=x+(w/2)
Sprite_Y.f=y+(h/2)
fLeft.f=((Sprite_X/GLSL\W)-0.5)*2
fTop.f=((Sprite_Y/GLSL\H)-0.5)*-2
With GLSL\Objects()
\uModelScale(0,0)=Aspect_X*Scale : \uModelScale(1,0)=0 : \uModelScale(2,0)=0 : \uModelScale(3,0)=0
\uModelScale(0,1)=0 : \uModelScale(1,1)=Scale : \uModelScale(2,1)=0 : \uModelScale(3,1)=0
\uModelScale(0,2)=0 : \uModelScale(1,2)=0 : \uModelScale(2,2)=1 : \uModelScale(3,2)=0
\uModelScale(0,3)=0 : \uModelScale(1,3)=0 : \uModelScale(2,3)=0 : \uModelScale(3,3)=1
\uRotate(0,0)=myCos : \uRotate(1,0)=-mySin : \uRotate(2,0)=0 : \uRotate(3,0)=0
\uRotate(0,1)=mySin : \uRotate(1,1)=myCos : \uRotate(2,1)=0 : \uRotate(3,1)=0
\uRotate(0,2)=0 : \uRotate(1,2)=0 : \uRotate(2,2)=1 : \uRotate(3,2)=0
\uRotate(0,3)=0 : \uRotate(1,3)=0 : \uRotate(2,3)=0 : \uRotate(3,3)=1
\uWorldScale(0,0)=GLSL\H/GLSL\W : \uWorldScale(1,0)=0 : \uWorldScale(2,0)=0 : \uWorldScale(3,0)=0
\uWorldScale(0,1)=0 : \uWorldScale(1,1)=1 : \uWorldScale(2,1)=0 : \uWorldScale(3,1)=0
\uWorldScale(0,2)=0 : \uWorldScale(1,2)=0 : \uWorldScale(2,2)=1 : \uWorldScale(3,2)=0
\uWorldScale(0,3)=0 : \uWorldScale(1,3)=0 : \uWorldScale(2,3)=0 : \uWorldScale(3,3)=1
\uTranslate(0,0)=1 : \uTranslate(1,0)=0 : \uTranslate(2,0)=0 : \uTranslate(3,0)=fLeft
\uTranslate(0,1)=0 : \uTranslate(1,1)=1 : \uTranslate(2,1)=0 : \uTranslate(3,1)=fTop
\uTranslate(0,2)=0 : \uTranslate(1,2)=0 : \uTranslate(2,2)=1 : \uTranslate(3,2)=0
\uTranslate(0,3)=0 : \uTranslate(1,3)=0 : \uTranslate(2,3)=0 : \uTranslate(3,3)=1
EndWith
GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(GLSL\Shader, "uModelScale"), 1, #GL_FALSE, @GLSL\Objects()\uModelScale());
GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(GLSL\Shader, "uRotate"), 1, #GL_FALSE, @GLSL\Objects()\uRotate());
GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(GLSL\Shader, "uWorldScale"), 1, #GL_FALSE, @GLSL\Objects()\uWorldScale());
GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(GLSL\Shader, "uTranslate"), 1, #GL_FALSE, @GLSL\Objects()\uTranslate());
GLSL\glUniform4f(GLSL\glGetUniformLocation(GLSL\Shader, "uColor"), Red(rgba)/255, Green(rgba)/255, Blue(rgba)/255, Alpha(rgba)/255)
glDrawElements_(#GL_QUADS, 4, #GL_UNSIGNED_INT, 0 )
glDisable_(#GL_BLEND)
GLSL\glUseProgram(0)
EndIf
EndProcedure
EndModule
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
OpenWindow(0, 0, 0, 800, 600, "GLSL sprites in WindowedScreen")
GLSL::Open(WindowID(0),100,50,600,500)
#ImagePath = #PB_Compiler_Home + "examples/3d/Data/Textures/"
Object1=GLSL::LoadObject(GLSL::#GLSLType_Sprite, #ImagePath+"ValetCoeur.jpg")
Object2=GLSL::LoadObject(GLSL::#GLSLType_Sprite, #ImagePath+"ValetCoeur.jpg")
Repeat
Event = WindowEvent()
GLSL::StartRender(RGBA(40,0,0,255))
GLSL::DrawObject(Object1, 0,50,300,400,Angle)
GLSL::DrawObject(Object2, 300,50,300,400,-Angle, RGBA(255,128,0,128))
Angle+1
Angle%360
GLSL::StopRender()
Until Event = #PB_Event_CloseWindow
GLSL::Close()