I've made a module.
Code: Select all
;=======================================================
; Lib screen (Sprite) - pf Shadoko -2024
;=======================================================
; Module : Mesa >> Everything (constant, procedure, ...)
; beginning by 'S_' is PUBLIC
;=======================================================
;- TOP
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
;-
;- DeclareModule S_Sprite
;- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
DeclareModule S_Sprite
;init opengl to add functions
InitSprite():w=OpenWindow(#PB_Any, 0, 0, 10, 10, ""):OpenWindowedScreen(WindowID(w), 0, 0, 10, 10):CloseWindow(w)
;- ◄ PUBLIC ►
;- Constant
; (For purebasic only)
#PB_Shader_Vector2 = 2
#PB_Shader_color = 10
#GL_TEXTURE0 = $84c0
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30
; (From here is for users)
Enumeration S_unit
#S_unit_Pixel = 0
#S_unit_UV
EndEnumeration
Enumeration S_BlendingMode
#S_BlendingMode_alphablend
#S_BlendingMode_add
#S_BlendingMode_custom
EndEnumeration
Enumeration S_shader2D
#S_Shader_Blend = 1000
#S_Shader_Bump
#S_Shader_Default
#S_Shader_Flame
#S_Shader_Light
#S_Shader_Overlay
#S_Shader_New
#S_Shader_Plasma
#S_Shader_Water
EndEnumeration
;- Declare
Declare S_BlendingMode(mode, modesource=#PB_Sprite_BlendSourceAlpha, modedestination=#PB_Sprite_BlendInvertSourceAlpha);mode:Enumeration S_BlendingMode, mosesource/modedestination: cf:SpriteBlendingMode
Declare S_Camera(x.f, y.f, zoom.f=0, rotation.f=1e10)
Declare S_ClipSprite(num, x.f, y.f, dx.f, dy.f, mode=0)
Declare S_CreateSprite(num, shaderNum, image1, image2=-1, image3=-1, image4=-1)
Declare S_DisplaySprite(num, x.f, y.f, Alpha=$ff, color.l=$ffffff, z.f=0)
Declare S_DrawText(x, y, t.s, size=-1, color=$ffffffff)
Declare S_FlipBuffers()
Declare S_FreeSprite(num)
Declare S_Globalparameter()
Declare S_Init()
Declare S_InitFont(num, name.s, height.f, style=0, brush=-1, chars.s="")
Declare S_IsSprite(num)
Declare S_Light(x.f, y.f, z.f, dist.f, color.l, ambiantcolor.l, world=1)
Declare S_RotateSprite(num, angle.f, mode=0)
Declare S_Spritecollision(num1, X1, Y1, num2, X2, Y2); !!! todo
Declare S_SpriteOrigine(num, x.f, y.f, unit=#S_unit_UV) ; unit:Enumeration S_unit
Declare S_SpriteParameter(num, parameter.s, type, v0.d, v1.f=0, v2.f=0, v3.f=0); parameter: #PB_Shader_Integer/float/vector2/vector3/vector4/color
Declare S_SpriteUV(num, u1.f, v1.f, u2.f, v2.f, u3.f, v3.f, u4.f, v4.f)
Declare S_TransformSprite(num, X1.f, Y1.f, X2.f, Y2.f, X3.f, Y3.f, X4.f, Y4.f)
Declare S_ZoomSprite(num, Width.f, Height.f, unit=#S_unit_UV); unit:Enumeration S_unit
Declare S_ShaderCreate(num, fshadercode.s, vshadercode.s="", name.s="", dbg=1)
Declare S_ShaderEditor(shader)
EndDeclareModule
;-
;- Module
;- ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Module S_Sprite
;- ◄ PRIVATE ►
;- Prototype
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
ImportC "-framework OpenGL"
glActiveTexture(type.l) As "_glActiveTexture"
glCreateShader(type.l) As "_glCreateShader"
glCreateProgram() As "_glCreateProgram"
glDeleteProgram(Program.l) As "_glDeleteProgram"
glDeleteShader(shader.l) As "_glDeleteShader"
glCompileShader(shader.l) As "_glCompileShader"
glLinkProgram(shader.l) As "_glLinkProgram"
glUseProgram(shader.l) As "_glUseProgram"
glAttachShader(Program.l, shader.l) As "_glAttachShader"
glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) As "_glShaderSource"
glGetUniformLocation(Program, name.p-ascii) As "_glGetUniformLocation"
glUniform1i(location, v0) As "_glUniform1i"
glUniform2i(location, v0, v1) As "_glUniform2i"
glUniform1f(location, v0.f) As "_glUniform1f"
glUniform1d(location, v0.d) As "_glUniform1d"
glUniform2d(location, v0.d, v1.d) As "_glUniform2d"
glUniform2f(location, v0.f, v1.f) As "_glUniform2f"
glUniform3f(location, v0.f, v1.f, v2.f) As "_glUniform3f"
glUniform4f(location, v0.f, v1.f, v2.f, v3.f) As "_glUniform4f"
glGetShaderInfoLog(shader, bufSize.l, *length_l, *infoLog) As "_glGetShaderInfoLog"
EndImport
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
ImportC "/usr/lib/x86_64-linux-gnu/libGL.so"
glActiveTexture(type.l)
glCreateShader(type.l)
glCreateProgram()
glDeleteProgram(Program.l)
glDeleteShader(shader.l)
glCompileShader(shader.l)
glLinkProgram(shader.l)
glUseProgram(shader.l)
glAttachShader(Program.l, shader.l)
glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) :
glGetUniformLocation(Program, name.p-ascii)
glUniform1i(location, v0)
glUniform2i(location, v0, v1)
glUniform1d(location, v0.d)
glUniform2d(location, v0.d, v1.d)
glUniform1f(location, v0.f)
glUniform2f(location, v0.f, v1.f)
glUniform3f(location, v0.f, v1.f, v2.f)
glUniform4f(location, v0.f, v1.f, v2.f, v3.f)
glGetShaderInfoLog(shader, bufSize.l, *length_l, *infoLog)
EndImport
CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
;- Macro
Macro QUOTE:"
EndMacro
Macro _ :, :EndMacro
Macro mPrototype (nom, params=)
Prototype nom(params)
Global nom.nom=wglGetProcAddress_(QUOTE#nom#QUOTE)
EndMacro
mPrototype (glActiveTexture, type.l)
mPrototype (glCreateShader, type.l)
mPrototype (glCreateProgram)
mPrototype (glDeleteProgram, Program.l)
mPrototype (glDeleteShader, shader.l)
mPrototype (glCompileShader, shader.l)
mPrototype (glLinkProgram, shader.l)
mPrototype (glUseProgram, shader.l)
mPrototype (glAttachShader, Program.l _ shader.l)
mPrototype (glShaderSource, shader.l _ numOfStrings.l _ *strings _ *lenOfStrings)
mPrototype (glGetUniformLocation, Program _ name.p-ascii)
mPrototype (glUniform1i, location _ v0)
mPrototype (glUniform2i, location _ v0 _ v1)
mPrototype (glUniform1d, location _ v0.d)
mPrototype (glUniform2d, location _ v0.d _ v1.d)
mPrototype (glUniform1f, location _ v0.f)
mPrototype (glUniform2f, location _ v0.f _ v1.f)
mPrototype (glUniform3f, location _ v0.f _ v1.f _ v2.f)
mPrototype (glUniform4f, location _ v0.f _ v1.f _ v2.f _ v3.f)
mPrototype (glGetShaderInfoLog, shader _ bufSize.l _ *lengthl _ *infoLog)
CompilerEndIf
;- Structure
Structure sShaderinfo
num.i ;shader num
name.s
pg.i ;shader program
vcode.s
fcode.s
Map uloc.i() ;uniform location
EndStructure
Structure sparam
nom.s
type.b
v0.d
v1.f
v2.f
v3.f
EndStructure
Structure sSpriteinfo
num.i ;sprite num
sh.sShaderinfo ;shader program
List tx.i() ;texture num
Map param.sparam()
Tdx.w:Tdy.w
dx.w:dy.w
x1.f:y1.f:u1.f:v1.f
x2.f:y2.f:u2.f:v2.f
x3.f:y3.f:u3.f:v3.f
x4.f:y4.f:u4.f:v4.f
zx.f:zy.f
ag.f
xo.f:yo.f
EndStructure
Structure ssc
sx.l
sl.l
cl.l
co.l
EndStructure
Structure sscfont
ns.i
height.f
Array c.ssc(255)
EndStructure
Global ScrennFont.sscfont
;- Global
Global s_screendx, s_screendy, s_screendx2, s_screendy2
Global Shadermessage.s, codevertex.s, SHvertex
Global.f glcamx, glcamy, glcamzoom=1, glcamrot, glcami=1, glcamj
Global.f glligthx, glligthy, glligthz, glligthdist, glligthcolor.l=0, glambiantcolor.l=$ffffffff
Global NewMap SpriteInfo.sSpriteinfo()
Global NewMap ShaderInfo.sShaderinfo()
;-
;- ■ PRIVATE PROCEDURE
;- ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
Procedure ImageToGLTextures(image, free=0)
;S_CreateSprite
Protected TextureID, w, h, rgb, rgba
If #PB_OS_Windows:rgb=#GL_BGR_EXT:rgba=#GL_BGRA_EXT:Else:rgb=#GL_RGB:rgba=#GL_RGBA:EndIf
StartDrawing(ImageOutput(image))
glGenTextures_(1, @TextureID)
glBindTexture_(#GL_TEXTURE_2D, TextureID)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
W = OutputWidth() : H = OutputHeight()
;glPixelStorei_(#GL_PACK_ROW_LENGTH, DrawingBufferPitch())
Select OutputDepth()
Case 24:glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGB, W, H, 0, rgb, #GL_UNSIGNED_BYTE, DrawingBuffer());
Case 32:glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGBA, W, H, 0, rgba, #GL_UNSIGNED_BYTE, DrawingBuffer());
EndSelect
StopDrawing()
If free:FreeImage(image):EndIf
ProcedureReturn TextureID
EndProcedure
;- Brush
Procedure initIF(image, cx.w=-1, cy.w=-1)
;image : numero de l'image
;centerx/y : definit le centre de l'image
Structure sImageFont
x.b
y.b
col.l
EndStructure
Protected i, j, d, k, n, c, idx, idy, x, y
idx=ImageWidth (image):If cx=-1:cx=idx/2:EndIf
idy=ImageHeight(image):If cy=-1:cy=idy/2:EndIf
Global Dim IFdata.sImageFont(idx * idy-1)
n=-1
StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
Macro gplot(i, j):x=cx+i:y=cy+j:If x>=0 And x<idx And y>=0 And y<idy:c=Point(x, y):If c<>0:n+1:IFdata(n)\x=x:IFdata(n)\y=y:IFdata(n)\col=c:EndIf:EndIf:EndMacro
gplot(0, 0)
For d=1 To 30
For k=0 To d-1
gplot(-d+k, -k)
gplot(k, -d+k)
gplot(d-k, k)
gplot(-k, d-k)
Next
Next
ReDim IFdata(n)
StopDrawing()
EndProcedure
Procedure DrawVectorTextBrush(text.s)
Protected x.f, y.f, j, n
x=PathCursorX()
y=PathBoundsY()
n=ArraySize(IFdata())
For j=n To 0 Step -1
MovePathCursor(x+IFdata(j)\x, y+IFdata(j)\y):VectorSourceColor(IFdata(j)\col):DrawVectorText(text)
Next
EndProcedure
Procedure spriteverif(num)
;Used by a lot of procedures
; If FindMapElement(SpriteInfo(), ""+num)=0:MessageRequester("S_ Erreur", "Sprite "+num+" does not exist"):CallDebugger:EndIf
If FindMapElement(SpriteInfo(), ""+num)=0:DebuggerWarning("S_ Erreur, Sprite "+num+" does Not exist"):EndIf
EndProcedure
Procedure spritecoord(num)
;S_ClipSprite, S_RotateSprite, S_SpriteOrigine, S_ZoomSprite
Protected.f co, si, xs, ys, xx, yy, zxo, zyo
Macro rot(x, y, xs, ys)
xx=x-zxo
yy=y-zyo
xs= xx*co+yy*si
ys=-xx*si+yy*co
EndMacro
With SpriteInfo(""+num)
co=Cos(\ag):si=Sin(\ag)
zxo=\xo*\zx
zyo=\yo*\zy
rot(0 , 0 , \x1, \y1)
rot(\dx, 0 , \x2, \y2)
rot(\dx, \dy, \x3, \y3)
rot(0 , \dy, \x4, \y4)
EndWith
EndProcedure
Procedure screenpos(*sx.float, *sy.float)
;S_light, S_DisplaySprite
Protected.f xx, yy
xx=*sx\f-glcamx-s_screendx2
yy=*sy\f-glcamy-s_screendy2
*sx\f= (xx*glcami+yy*glcamj+s_screendx2)
*sy\f=(-xx*glcamj+yy*glcami+s_screendy2)
EndProcedure
Procedure shaderuniform(*sh.sShaderinfo, nom.s, type, v0.d, v1.f=0, v2.f=0, v3.f=0)
;S_DisplaySprite, s_FlipBuffers, S_globalparameter
If FindMapElement(*sh\uloc(), nom)
Select type
Case #PB_Shader_Integer :glUniform1i(*sh\uloc(), v0)
Case #PB_Shader_Float :glUniform1f(*sh\uloc(), v0)
Case #PB_Shader_Vector2 :glUniform2f(*sh\uloc(), v0, v1)
Case #PB_Shader_Vector3 :glUniform3f(*sh\uloc(), v0, v1, v2)
Case #PB_Shader_Vector4 :glUniform4f(*sh\uloc(), v0, v1, v2, v3)
Case #PB_Shader_color :Protected c.q=v0:glUniform4f(*sh\uloc(), Red(c)/255, Green(c)/255, Blue(c)/255, Alpha(c)/255)
EndSelect
EndIf
EndProcedure
Procedure.s supspace(l.s)
;ShaderCreate
Protected i
Protected.s ll, ac, c
l=ReplaceString(l, #TAB$, " ")
l=ReplaceString(l, #LF$, " ")
l=ReplaceString(l, #CR$, " ")
i=0:While i<Len(l)
Repeat
i+1
ac=c:c=Mid(l, i, 1)
Until c<>" " Or ac<>" "
ll+c
Wend
ProcedureReturn Trim(ll)
EndProcedure
Procedure shaderCompile(shadercode.s, type=#PB_Shader_Fragment, dbg=1)
;ShaderCreate, S_init
Protected shader, gltype, *TxtPointer, Program, Textlength, message.s = Space(1024)
If type=#PB_Shader_Vertex:gltype=#GL_VERTEX_SHADER:Else:gltype=#GL_FRAGMENT_SHADER:EndIf
shadercode=ReplaceString(shadercode, "%", #CRLF$)
shader = glCreateShader(gltype)
*TxtPointer = Ascii(shadercode)
glShaderSource(shader, 1, @*TxtPointer, #Null)
glCompileShader(shader)
glGetShaderInfoLog(shader, 1023, @Textlength, @message)
Shadermessage=PeekS(@message, 1023, #PB_Ascii)
If Shadermessage
If dbg:DebuggerWarning("error shader "+shader+#CRLF$+Shadermessage):EndIf
ProcedureReturn
EndIf
ProcedureReturn shader
EndProcedure
;-
;- ■ PUBLIC Procedure
;- ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
Procedure S_ShaderCreate(num, fshadercode.s, vshadercode.s="", name.s="", dbg=1)
;S_init
Static numauto=1000000
Protected vshader, fshader, Program, vfcode.s, ul, txu
If num=-1:num=numauto:numauto+1:EndIf
If fshadercode="":fshader=#S_Shader_Default:Else:fshader=ShaderCompile(fshadercode, #PB_Shader_Fragment, dbg):EndIf:If fshader=0 :ProcedureReturn :EndIf
If vshadercode="":vshadercode=codevertex:vshader=SHvertex :Else:vshader=ShaderCompile(vshadercode, #PB_Shader_Vertex, dbg):EndIf:If vshader=0 :ProcedureReturn :EndIf
Program = glCreateProgram()
glAttachShader(Program, vshader)
glAttachShader(Program, fshader)
glLinkProgram(Program)
glUseProgram(Program)
If FindMapElement(ShaderInfo(), ""+num):DeleteMapElement(ShaderInfo(), ""+num):EndIf
With ShaderInfo(""+num)
\num=num
\name=name
\pg=Program
\vcode=vshadercode
\fcode=fshadercode
Protected p, pf, l.s, n.s, t.s
vfcode=supspace(vshadercode+fshadercode)
Repeat
p=FindString(vfcode, "uniform", p+1)
pf=FindString(vfcode, ";", p)
If p
l=Mid(vfcode, p, pf-p)
n=StringField(l, 3, " ")
t=StringField(l, 2, " ")
ul=glGetUniformLocation(Program, n)
If FindString(t, "sampler"):glUniform1i(ul, txu):txu+1:Else:\uloc(n)=ul:EndIf
EndIf
Until p=0
EndWith
ProcedureReturn num
EndProcedure
;-
;.......................................................................................
;- └Shader editor ┘
Global GSE_editor, GSE_message, GSE_list, GSE_run, GSE_savecb, SE_window, shaderedit
Procedure shaderEditorcallback()
;ShaderEditor
Protected event, code.s
Macro updateshader
S_ShaderCreate(shaderedit, code, "", ShaderInfo(""+shaderedit)\name, 0)
SetGadgetText(GSE_message, Shadermessage)
If Shadermessage=""
ForEach SpriteInfo()
If SpriteInfo()\sh\num=shaderedit:SpriteInfo()\sh=ShaderInfo(""+shaderedit):EndIf
Next
EndIf
EndMacro
Select Event()
Case #PB_Event_CloseWindow:CloseWindow(EventWindow()):SE_window=0:ReleaseMouse(0)
Case #PB_Event_Menu
Select EventMenu()
Case 1111:code = GetGadgetText(GSE_editor):updateshader
Case 1112:CloseWindow(EventWindow()):SE_window=0:ReleaseMouse(0)
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
Case GSE_list:shaderedit=GetGadgetItemData(GSE_list, GetGadgetState(GSE_list)):SetGadgetText(GSE_editor, ReplaceString(ShaderInfo(""+shaderedit)\fcode, "%", #CRLF$))
Case GSE_run:code = GetGadgetText(GSE_editor):updateshader
Case GSE_savecb:code=GetGadgetText(GSE_editor):code=ReplaceString(code, #CRLF$, "%"):SetClipboardText(~"SHnew=S_ShaderCreate(-1, \""+code+~"\", \"\", \""+ShaderInfo(""+shaderedit)\name+~"\")\n")
EndSelect
EndSelect
EndProcedure
Procedure S_ShaderEditor(shader)
Protected wdx=700, xdy=600, it, ls
If SE_window:ReleaseMouse(1):SetActiveWindow(SE_window): ProcedureReturn :EndIf
shaderedit=shader
SE_window=OpenWindow(-1, 0, 0, wdx, xdy, "Shader Editor")
BindEvent(#PB_Event_Gadget, @shaderEditorcallback(), SE_window)
BindEvent(#PB_Event_Menu, @shaderEditorcallback(), SE_window)
BindEvent(#PB_Event_CloseWindow, @shaderEditorcallback(), SE_window)
GSE_editor=EditorGadget(-1, 8, 30, wdx-16, xdy-30-150)
SetGadgetText(GSE_editor, ReplaceString(ShaderInfo(""+shaderedit)\fcode, "%", #CRLF$))
GSE_message=EditorGadget(-1, 8, xdy+8-150, wdx-16, 150-16, #PB_Editor_ReadOnly)
GSE_list=ComboBoxGadget(-1, 8, 0, 90, 24):ForEach ShaderInfo():AddGadgetItem(GSE_list, -1, ShaderInfo()\name):SetGadgetItemData(GSE_list, it, ShaderInfo()\num):If ShaderInfo()\num=shader:ls=it:EndIf:it+1:Next
SetGadgetState(GSE_list, ls)
GSE_run=ButtonGadget(-1, 108 , 0, 90, 24, "run [F5]")
GSE_savecb=ButtonGadget(-1, 208 , 0, 90, 24, "save clipboard")
AddKeyboardShortcut(SE_window, #PB_Shortcut_F5, 1111)
AddKeyboardShortcut(SE_window, #PB_Shortcut_Escape, 1112)
EndProcedure
;.......................................................................................
;-
Procedure S_BlendingMode(mode, modesource=#PB_Sprite_BlendSourceAlpha, modedestination=#PB_Sprite_BlendInvertSourceAlpha); mode:Enumeration S_BlendingMode, mosesource/modedestination: cf:SpriteBlendingMode
Protected glsrc, gldst
Macro cvmode(pbmode, glmode)
Select pbmode
Case #PB_Sprite_BlendZero:glmode=#GL_ZERO
Case #PB_Sprite_BlendOne:glmode=#GL_ONE
Case #PB_Sprite_BlendSourceColor:glmode=#GL_SRC_COLOR
Case #PB_Sprite_BlendInvertSourceColor:glmode=#GL_ONE_MINUS_SRC_COLOR
Case #PB_Sprite_BlendDestinationColor:glmode=#GL_DST_COLOR
Case #PB_Sprite_BlendInvertDestinationColor:glmode=#GL_ONE_MINUS_DST_COLOR
Case #PB_Sprite_BlendSourceAlpha:glmode=#GL_SRC_ALPHA
Case #PB_Sprite_BlendInvertSourceAlpha:glmode=#GL_ONE_MINUS_SRC_ALPHA
Case #PB_Sprite_BlendDestinationAlpha:glmode=#GL_DST_ALPHA
Case #PB_Sprite_BlendInvertDestinationAlpha:glmode=#GL_ONE_MINUS_DST_ALPHA
EndSelect
EndMacro
Select mode
Case #S_BlendingMode_alphablend: glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)
Case #S_BlendingMode_add : glBlendFunc_(#GL_ONE, #GL_ONE)
Case #S_BlendingMode_custom :cvmode(modesource, glsrc):cvmode(modedestination, gldst):glBlendFunc_(glsrc, gldst)
EndSelect
EndProcedure
Procedure S_Camera(x.f, y.f, zoom.f=0, rotation.f=1e10)
glcamx=x
glcamy=y
If zoom<>0:glcamzoom=zoom:EndIf
If rotation<>1e10
glcamrot=Radian(rotation)
glcami=Cos(glcamrot)*glcamzoom
glcamj=Sin(glcamrot)*glcamzoom
EndIf
EndProcedure
Procedure S_ClipSprite(num, x.f, y.f, dx.f, dy.f, mode=0)
Spriteverif(num)
With SpriteInfo(""+num)
\u1=x/\Tdx:\v1=y/\Tdy
\u2=(x+dx)/\Tdx:\v2=y/\Tdy
\u3=(x+dx)/\Tdx:\v3=(y+dy)/\Tdy
\u4=x/\Tdx:\v4=(y+dy)/\Tdy
\dx=dx
\dy=dy
EndWith
spritecoord(num)
EndProcedure
Procedure S_CreateSprite(num, shaderNum, image1, image2=-1, image3=-1, image4=-1); shaderNum:Enumeration S_shader2D
If shaderNum=0:MessageRequester("Erreur S_CreateSprite", "Shader invalid"):CallDebugger:EndIf
Static numauto=1000000
Protected u.s, txu
If num=-1:num=numauto:numauto+1:EndIf
AddMapElement(SpriteInfo(), ""+num)
SpriteInfo()\sh = ShaderInfo(""+shaderNum)
Macro addtx(image)
If image>=0
If IsImage(image)=0:MessageRequester("Erreur S_CreateSprite", "image"+Str(txu+1)+" isn't loaded"):CallDebugger:EndIf
AddElement(SpriteInfo()\tx())
SpriteInfo()\tx()= ImageToGLTextures(image)
EndIf
EndMacro
addtx(image1)
addtx(image2)
addtx(image3)
addtx(image4)
With SpriteInfo()
\Tdx=ImageWidth(image1):\dx=\Tdx
\Tdy=ImageHeight(image1):\dy=\Tdy
\u2=1:\u3=1:\v3=1:\v4=1
\x2=\Tdx:\x3=\Tdx:\y3=\Tdy:\y4=\Tdy
\zx=1:\zy=1
EndWith
ProcedureReturn num
EndProcedure
Procedure S_DisplaySprite(num, x.f, y.f, Alpha=$ff, color.l=$ffffff, z.f=0)
Spriteverif(num)
Protected.f a=alpha/255, r=Red(color)/255, g=Green(color)/255, b=Blue(color)/255, sx, sy
Protected txu, *sp.sSpriteinfo
*sp=SpriteInfo(""+num)
glUseProgram(*sp\sh\pg)
ForEach *sp\tx()
glActiveTexture(#GL_TEXTURE0+txu):glBindTexture_(#GL_TEXTURE_2D, *sp\tx()):txu+1
Next
ForEach *sp\param()
With *sp\param()
shaderuniform(*sp\sh, \nom, \type, \v0, \v1, \v2, \v3)
EndWith
Next
With *sp
Macro glv(x, y):sx=x:sy=y:If *sp\sh\num<>#S_Shader_Overlay:screenpos(@sx, @sy):EndIf:glVertex3f_(sx, sy, z):EndMacro
glBegin_(#GL_QUADS)
glColor4f_(r, g, b, a)
glNormal3f_(Cos(*sp\ag+glcamrot), Sin(*sp\ag+glcamrot), 0); for tangent !
glTexCoord2f_(\u1, \v1):glv(x+\x1, y+\y1)
glTexCoord2f_(\u2, \v2):glv(x+\x2, y+\y2)
glTexCoord2f_(\u3, \v3):glv(x+\x3, y+\y3)
glTexCoord2f_(\u4, \v4):glv(x+\x4, y+\y4)
glEnd_()
EndWith
EndProcedure
Procedure S_DrawText(x, y, t.s, size=-1, color=$ffffffff)
Protected i, ca, cx, c.ssc, zoom.f
With ScrennFont
If size=-1:size=\height:EndIf
zoom=size/\height
For i=1 To Len(t)
c=\c(Asc(Mid(t, i, 1)))
S_ClipSprite(\ns, c\sx, 0, c\sl, \height)
S_ZoomSprite(\ns, c\sl*zoom, \height*zoom, #S_unit_Pixel)
S_DisplaySprite(\ns, x+c\co*zoom, y, 255, color)
x+c\cl*zoom
Next
EndWith
EndProcedure
Procedure S_FlipBuffers()
FlipBuffers()
ForEach ShaderInfo()
glUseProgram(ShaderInfo()\pg)
shaderuniform(ShaderInfo(), "screen", #PB_Shader_Vector2, s_screendx, s_screendy)
shaderuniform(ShaderInfo(), "campos", #PB_Shader_Vector3, s_screendx2, s_screendy2, s_screendy2)
shaderuniform(ShaderInfo(), "ambiantcolor", #PB_Shader_color, glambiantcolor)
shaderuniform(ShaderInfo(), "lightcolor", #PB_Shader_color, glligthcolor)
shaderuniform(ShaderInfo(), "lightinfo", #PB_Shader_Vector4, glligthx, glligthy, glligthz, glligthdist)
shaderuniform(ShaderInfo(), "time", #PB_Shader_Float, ElapsedMilliseconds()/1000)
Next
glEnable_(#GL_BLEND)
EndProcedure
Procedure S_FreeSprite(num)
Spriteverif(num)
glDeleteProgram(SpriteInfo(""+num)\sh\pg)
DeleteMapElement(SpriteInfo(), ""+num)
EndProcedure
Procedure S_Globalparameter()
ForEach ShaderInfo()
glUseProgram(ShaderInfo()\pg)
shaderuniform(ShaderInfo(), "screen", #PB_Shader_Vector2, s_screendx, s_screendy)
shaderuniform(ShaderInfo(), "campos", #PB_Shader_Vector3, s_screendx2, s_screendy2, s_screendy2)
shaderuniform(ShaderInfo(), "ambiantcolor", #PB_Shader_color, glambiantcolor)
shaderuniform(ShaderInfo(), "lightcolor", #PB_Shader_color, glligthcolor)
shaderuniform(ShaderInfo(), "lightinfo", #PB_Shader_Vector4, glligthx, glligthy, glligthz, glligthdist)
shaderuniform(ShaderInfo(), "time", #PB_Shader_Float, ElapsedMilliseconds()/1000)
Next
EndProcedure
Procedure S_Init()
s_screendx=ScreenWidth():s_screendx2=s_screendx/2
s_screendy=ScreenHeight():s_screendy2=s_screendy/2
codevertex="#version 120 %%uniform vec2 screen;% varying vec3 vpos;% varying vec4 vcolor;% varying vec2 vuv;% varying vec2 vtan;% void main() {% vtan = gl_Normal.xy;% gl_Position = vec4( gl_Vertex.xy/screen*2-1, gl_Vertex.z, 1 );gl_Position.y*=-1;% vcolor=gl_Color;% vuv=gl_MultiTexCoord0.xy;//invertv% vpos=gl_Vertex.xyz;%}"
If #PB_OS_Windows:codevertex=ReplaceString(codevertex, "//invertv", "vuv.y=1-vuv.y;"):EndIf
SHvertex=ShaderCompile(codevertex, #PB_Shader_Vertex)
;Debug ReplaceString(codevertex, "%", #LF$)
S_ShaderCreate(#S_Shader_Overlay, "#version 130 %%uniform sampler2D txt0;%%in vec4 vcolor;%in vec2 vuv;%%out vec4 fcolor;%%void main( void ) {% vec4 tcolor=texture(txt0, vuv);% fcolor =tcolor*vcolor;%}", "", "overlay")
S_ShaderCreate(#S_Shader_Default, "#version 130 %%uniform sampler2D txt0;%%in vec4 vcolor;%in vec2 vuv;%%out vec4 fcolor;%%void main( void ) {% vec4 tcolor=texture(txt0, vuv);% fcolor =tcolor*vcolor;%}", "", "default")
S_ShaderCreate(#S_Shader_Blend, "#version 130 %%uniform sampler2D tx0;%uniform sampler2D tx1;%uniform vec4 lightinfo;%uniform vec4 lightcolor;%uniform vec4 ambiantcolor;%uniform float blend;%%in vec4 vcolor;%in vec2 vuv;%in vec3 vpos;%%out vec4 fcolor;%%void main( void ) {% vec4 tcolor=mix(texture(tx0, vuv), texture(tx1, vuv), blend);% float lum=max(1-distance(lightinfo.xyz, vpos)/lightinfo.w, 0);% fcolor =tcolor*vcolor*(ambiantcolor+lightcolor*lum);%}", "", "blend")
S_ShaderCreate(#S_Shader_Light, "#version 130 %%uniform sampler2D txt0;%uniform vec4 lightinfo;%uniform vec4 lightcolor;%uniform vec4 ambiantcolor;%%in vec4 vcolor;%in vec2 vuv;%in vec3 vpos;%%out vec4 fcolor;%%void main( void ) {% vec4 tcolor=texture(txt0, vuv);% float lum=max(1-distance(lightinfo.xyz, vpos)/lightinfo.w, 0);% fcolor =tcolor*vcolor*(ambiantcolor+lum*lightcolor);%}", "", "light")
S_ShaderCreate(#S_Shader_Bump, "#version 130 %%uniform sampler2D tx0;%uniform sampler2D tx1;%%uniform vec3 campos;%uniform vec4 lightinfo;%uniform vec4 lightcolor;%uniform vec4 ambiantcolor;%%in vec4 vcolor;%in vec2 vuv;%in vec3 vpos;%in vec2 vtan;%%out vec4 fcolor;%%void main( void ) {% vec4 tcol=texture(tx0, vuv)*vcolor;% vec3 tnor=texture(tx1, vuv).xyz-0.5;tnor.xy*=1;% tnor.xy=vec2(vtan.x*tnor.x+vtan.y*-tnor.y, -vtan.y*tnor.x+vtan.x*-tnor.y);% tnor=normalize(tnor);% vec3 ldir=normalize(lightinfo.xyz-vpos);% vec3 cdir=normalize(campos-vpos);% float att=max(1-distance(lightinfo.xyz, vpos)/lightinfo.w, 0);% float dif=max(dot(ldir, tnor), 0)*att;% float spe=pow(max(dot(normalize(ldir+cdir), tnor), 0), 50);% fcolor =tcol*(ambiantcolor+lightcolor*(dif+spe));%}", "", "bump")
S_ShaderCreate(#S_Shader_Flame, "#version 130 %%uniform sampler2D tx;%uniform float time;%%in vec2 vuv;%in vec4 vcolor;%%out vec4 fcolor;%void main()%{%float odec=1;%vec2 uv=vuv;uv.y=pow(uv.y, 0.5);%vec2 pc=uv*2-1;%float h=1-dot(pc, pc);%if(h<0)discard;%float vx=time*0.08;%float vy=time*-0.2;%float lum=0.8*h*(texture(tx, uv+vec2(vx, vy+odec)).a+texture(tx, uv+vec2(-vx, vy+0.5+odec)).a);%fcolor=(lum*lum)*vcolor;%}", "", "flame")
S_ShaderCreate(#S_Shader_Water, "#version 130 %%uniform sampler2D tx;%%uniform float time;%uniform vec3 campos;%uniform vec4 lightinfo;%uniform vec4 lightcolor;%uniform vec4 skycolor;%%in vec4 vcolor;%in vec2 vuv;%in vec3 vpos;%in vec2 vtan;%%out vec4 fcolor;%%void main( void ) {% vec2 duv=vec2(time*0.02, 0);% vec3 tnor=(texture(tx, vuv+duv).xyz+texture(tx, vuv+0.5-duv).xyz-1).xyz;tnor.xy*=1;% tnor.xy=vec2(vtan.x*tnor.x+vtan.y*-tnor.y, -vtan.y*tnor.x+vtan.x*-tnor.y);% tnor=normalize(tnor);% vec3 ldir=normalize(lightinfo.xyz-vpos);% vec3 cdir=normalize(campos-vpos);% float spe=pow(max(dot(normalize(ldir+cdir), tnor), 0), 50);% float cfresnel = 1-abs(dot(cdir, tnor));% fcolor =mix(vcolor, skycolor, cfresnel*cfresnel)+lightcolor*spe;%}", "", "water")
S_ShaderCreate(#S_Shader_Plasma, "#version 130 %%uniform sampler2D tx;%uniform float time;%uniform vec4 color1;%uniform vec4 color2;%%in vec2 vuv;%in vec4 vcolor;%%out vec4 fcolor;%void main()%{%vec2 duv=vec2(time*0.02, 0);%float lum=(texture(tx, vuv+duv).a+texture(tx, vuv-duv+0.5).a);%fcolor=mix(color1, color2, mod(lum*2, 1))*vcolor;%//fcolor=mix(color1, color2, (1+cos(lum*3.14*4))/2)*vcolor;%}", "", "plasma")
S_ShaderCreate(#S_Shader_New, "#version 130 %%uniform sampler2D tx;%%// global parameters%uniform vec3 campos; // camera position%uniform vec4 ambiantcolor;%uniform vec4 lightcolor;%uniform vec4 lightinfo; // x, y, z:position, w:range%uniform float time; // in seconds%%// keep only if you use it%in vec3 vpos; // vertex position%in vec4 vcolor; // vertex color%in vec2 vuv; // vertex uv%in vec2 tan; // tangent (for normal mapping)%%out vec4 fcolor;%%void main()%{%vec4 tcolor=texture(tx, vuv);%fcolor=tcolor*vcolor;%}", "", "new")
EndProcedure
Procedure S_InitFont(num, name.s, height.f, style=0, brush=-1, chars.s="")
Protected i, h, l, c.s, ca, im, bx, by, cx, co, cv, cl:Global nf
If chars="":For i=32 To 128:chars+Chr(i):Next:EndIf
nf=LoadFont(-1, name, height, style)
If brush>=0:initIF(brush):bx=ImageWidth(brush):by=ImageHeight((brush)):EndIf
IM=CreateImage(-1, 1, 1)
StartDrawing(ImageOutput(im)):DrawingFont(FontID(nf))
h=TextHeight(" ")+by
l=TextWidth(chars)*1.3+Len(chars)*bx:cx=0
StopDrawing()
FreeImage(im)
IM=CreateImage(-1, l, h, 32, #PB_Image_Transparent):StartDrawing(ImageOutput(im)):DrawingMode(#PB_2DDrawing_AllChannels):Box(0, 0, l, h, $00ffffff):StopDrawing()
StartVectorDrawing(ImageVectorOutput(im)):VectorFont(FontID(nf))
For i=1 To Len(chars)
c=Mid(chars, i, 1):ca=Asc(c)
With ScrennFont\c(ca)
co=VectorTextWidth(c, #PB_VectorText_Visible|#PB_VectorText_Offset):If ca=126:co=0:EndIf
cv=VectorTextWidth(c, #PB_VectorText_Visible)
cl=VectorTextWidth(c)
\sx=cx
\sl=cv+bx+2
\cl=cl+bx/2
\co=co
;AddPathBox(\sx, 0, \sl, h):VectorSourceColor($8800ff00):FillPath()
MovePathCursor(cx-co+1, 0)
If brush<0:VectorSourceColor($ffffffff):DrawVectorText(c):Else:DrawVectorTextBrush(c):EndIf
cx+\sl+1
EndWith
Next
StopVectorDrawing()
ScrennFont\ns=S_CreateSprite(-1, #S_Shader_Overlay, im)
ScrennFont\height=h
EndProcedure
Procedure S_IsSprite(num)
If FindMapElement(SpriteInfo(), ""+num):ProcedureReturn 1:EndIf
EndProcedure
Procedure S_Light(x.f, y.f, z.f, dist.f, color.l, ambiantcolor.l, world=1)
If world:screenpos(@x, @y):EndIf
glligthx=x
glligthy=y
glligthz=z
glligthdist=dist
glligthcolor=$ff<<24 | color
glambiantcolor=$ff<<24 | ambiantcolor
EndProcedure
Procedure S_RotateSprite(num, angle.f, mode=0)
Spriteverif(num)
With SpriteInfo(""+num)
angle=Radian(angle)
If mode:\ag+angle:Else:\ag=angle:EndIf
EndWith
spritecoord(num)
EndProcedure
Procedure S_SpriteCollision(num1, X1, Y1, num2, X2, Y2)
;TODO
Spriteverif(num1)
Spriteverif(num2)
EndProcedure
Procedure S_SpriteOrigine(num, x.f, y.f, unit=#S_unit_UV) ; unit:Enumeration S_unit
Spriteverif(num)
With SpriteInfo(""+num)
If unit=#S_unit_UV
\xo=x*\Tdx
\yo=y*\Tdy
Else
\xo=x
\yo=y
EndIf
EndWith
spritecoord(num)
EndProcedure
Procedure S_SpriteParameter(num, parameter.s, type, v0.d, v1.f=0, v2.f=0, v3.f=0); parameter: #PB_Shader_Integer/float/vector2/vector3/vector4/color
Protected *sh.sShaderinfo, *p.sparam
If num=-1
;S_SpriteParameter(-1, "screenratio", #PB_Shader_Float, glratio)
EndIf
Spriteverif(num)
With SpriteInfo(""+num)
*p=\param(parameter)
*p\nom=parameter
*p\type=type
*p\v0=v0
*p\v1=v1
*p\v2=v2
*p\v3=v3
EndWith
EndProcedure
Procedure S_SpriteUV(num, u1.f, v1.f, u2.f, v2.f, u3.f, v3.f, u4.f, v4.f)
Spriteverif(num)
With SpriteInfo(""+num)
\u1=u1:\v1=v1
\u2=u2:\v2=v2
\u3=u3:\v3=v3
\u4=u4:\v4=v4
EndWith
EndProcedure
Procedure S_TransformSprite(num, X1.f, Y1.f, X2.f, Y2.f, X3.f, Y3.f, X4.f, Y4.f)
Spriteverif(num)
With SpriteInfo(""+num)
\x1=x1:\y1=y1
\x2=x2:\y2=y2
\x3=x3:\y3=y3
\x4=x4:\y4=y4
\zx=1:\zy=1
\ag=0
EndWith
EndProcedure
Procedure S_ZoomSprite(num, Width.f, Height.f, unit=#S_unit_UV); unit:Enumeration S_unit
Spriteverif(num)
With SpriteInfo(""+num)
If unit=#S_unit_UV
\dx=Width*\Tdx
\dy=Height*\Tdy
Else
\dx=Width
\dy=Height
EndIf
\zx=\dx/\tdx
\zy=\dy/\tdy
EndWith
spritecoord(num)
EndProcedure
EndModule
;====================================================================================================================================================
;====================================================================================================================================================
;====================================================================================================================================================
;-
CompilerIf #PB_Compiler_IsMainFile
;- TEST
;==================================================================================
; Module >> Everything (constant, procedure, ...) beginning by 'S_' is PUBLIC
;=================================================================================
UseModule S_Sprite
ExamineDesktops()
Define swidth=DesktopWidth(0)*0.8
Define sheight=DesktopHeight(0)*0.8
OpenWindow(0, 0, 0, swidth, sheight, "Lib 2D v1.0", #PB_Window_SystemMenu |#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, swidth, sheight)
S_init()
InitKeyboard()
InitMouse()
;---- init screen font
CreateImage(100, 8, 8, 32, #PB_Image_Transparent)
StartVectorDrawing(ImageVectorOutput(100))
VectorSourceCircularGradient(3, 3, 5)
VectorSourceGradientColor($ffffffff, 0.0)
VectorSourceGradientColor($ff0000ff, 0.5)
VectorSourceGradientColor($00000000, 1.0)
AddPathCircle(4, 4, 4):FillPath()
StopVectorDrawing()
S_InitFont(0, "ink free", 30, #PB_Font_Italic, 100)
Define i, sblend, sbump, sflare, sflame, swater, scloud, splasma, SHwobble, swobble
Define Event
;---- load images
UseJPEGImageDecoder()
UsePNGImageDecoder()
LoadImage(1, #PB_Compiler_Home+"examples/3d/Data/Textures/water.png")
LoadImage(2, #PB_Compiler_Home+"examples/3d/Data/Textures/smoke2.png")
LoadImage(3, #PB_Compiler_Home+"examples/3d/Data/Textures/flare.png")
LoadImage(4, #PB_Compiler_Home+"examples/3d/Data/Textures/sky.png")
LoadImage(5, #PB_Compiler_Home+"examples/3d/Data/Textures/nvidia/dirt_grayrocky_diffusespecular.jpg")
LoadImage(6, #PB_Compiler_Home+"examples/3d/Data/Textures/nvidia/dirt_grayrocky_normalheight.jpg")
LoadImage(7, #PB_Compiler_Home+"examples/3d/Data/Textures/waternormal.png")
CreateImage(10, 512, 512, 32, #PB_Image_Transparent):StartDrawing(ImageOutput(10)):DrawingMode(#PB_2DDrawing_AlphaBlend):For i=0 To 800:Circle(Random(512-64)+32, Random(512-64)+32, 32, Random($44ffffff)):Next:StopDrawing()
;---------------------------- init demo1
sbump=S_CreateSprite(-1, #S_Shader_Bump, 5, 6):S_SpriteOrigine(sbump, 0.5, 0.5):S_ZoomSprite(sbump, swidth*2, sheight*2, 0):S_SpriteUV(sbump, 0, 0, 2, 0, 2, 2, 0, 2)
sblend=S_CreateSprite(-1, #S_Shader_Blend, 1, 2):S_SpriteOrigine(sblend, 0.5, 0.5):S_ZoomSprite(sblend, 2, 2)
sflare=S_CreateSprite(-1, #S_Shader_Overlay, 3):S_SpriteOrigine(sflare, 0.5, 0.5):S_ZoomSprite(sflare, 2, 2)
sflame=S_CreateSprite(-1, #S_Shader_Flame, 7):S_SpriteOrigine(sflame, 0.5, 0.5):S_ZoomSprite(sflame, 1, 1.5)
;----------------------------- init demo2
swater=S_CreateSprite(-1, #S_Shader_Water, 7):S_SpriteParameter(swater, "skycolor", #PB_Shader_color, $ffffbb88):S_SpriteOrigine(swater, 0.5, 0.5):S_ZoomSprite(swater, swidth*2, swidth*2, #S_unit_Pixel)
scloud=S_CreateSprite(-1, #S_Shader_Default, 4):S_ZoomSprite(scloud, swidth*2, swidth*2, #S_unit_Pixel):S_SpriteOrigine(scloud, 0.5, 0.5)
;----------------------------- init demo3
splasma=S_CreateSprite(-1, #S_Shader_Plasma, 7):S_SpriteParameter(splasma, "color1", #PB_Shader_color, $ffff0000):S_SpriteParameter(splasma, "color2", #PB_Shader_color, $ff00ffff):S_SpriteOrigine(splasma, 0.5, 0.5):S_ZoomSprite(splasma, sheight*2, sheight*2, #S_unit_Pixel)
;---------------------------- init test shader
SHwobble=S_ShaderCreate(-1, "#version 130 %%uniform sampler2D txt0;%uniform vec4 lightinfo;%uniform vec4 lightcolor;%uniform vec4 ambiantcolor;%uniform float time;%%in vec4 vcolor;%in vec2 vuv;%in vec3 vpos;%%out vec4 fcolor;%%void main( void ) {% float fq=8, amp=0.04, ti=time*4;% vec2 uv=vuv*(1+2*amp)-amp;% uv=uv+vec2(sin(vuv.y*fq+ti)*amp, sin(vuv.x*fq+ti)*amp);% if (uv.x<0 || uv.x>1 || uv.y<0 || uv.y>1) discard; % vec4 tcolor=texture(txt0, uv);% float lum=max(1-distance(lightinfo.xyz, vpos)/lightinfo.w, 0);% fcolor =tcolor*vcolor*(ambiantcolor+lum*lightcolor);%}", "", "wobble")
swobble=S_CreateSprite(-1, SHwobble, 10):S_SpriteOrigine(swobble, 0.5, 0.5):S_ZoomSprite(swobble, sheight, sheight, #S_unit_Pixel);:S_SpriteParameter(swobble, "amp", #PB_Shader_Float, 1)
Define.f sy, a, ai, py, dy, t, rot, zw=0.5*8, zc=0.25, example.b=0
Define rm
MouseLocate(swidth/2, sheight/2)
Repeat
t=ElapsedMilliseconds()/1000
a=t*2
sy=-t/10
ClearScreen(0)
S_BlendingMode(#S_BlendingMode_alphablend)
Select example
Case 0
S_Camera(Sin(sy*5)*200, Sin(sy*7)*200, 1, 0)
S_light(MouseX(), MouseY(), sheight/2, sheight*4, $ffffff, $0, 0)
S_DisplaySprite(sbump, swidth/2, sheight/2)
S_SpriteParameter(sblend, "blend", #PB_Shader_Float, 0.5+0.5*Cos(a)):S_DisplaySprite(sblend, swidth*0.25, sheight*0.25, $ff, $ffff00)
S_SpriteParameter(sblend, "blend", #PB_Shader_Float, 0.5+0.5*Sin(a)):S_DisplaySprite(sblend, swidth*0.25, sheight*0.75, $ff, $ff00ff)
S_BlendingMode(#S_BlendingMode_add)
S_DisplaySprite(sflame, swidth*0.75, sheight/2, 128, $88ff)
S_RotateSprite(sflare, 2, #PB_Relative):S_DisplaySprite(sflare, MouseX(), MouseY())
S_BlendingMode(#S_BlendingMode_alphablend)
Case 1
rot+MouseDeltaX()*0.05
S_Camera(0, 0, 1+Sin(sy*4)/3, rot)
S_light(10000, -10000, 10000, 0, $ffffff, $222222*4)
S_SpriteUV(swater, 0, sy, zw, sy, zw, zw+sy, 0, zw+sy):S_DisplaySprite(swater, swidth/2, sheight/2, 255, $443300)
S_SpriteUV(scloud, 0, sy, zc*2, sy, zc*2, zc*2+sy, 0, zc*2+sy)
S_DisplaySprite(scloud, swidth/2, sheight/2)
S_SpriteUV(scloud, 0, sy, zc, sy, zc, zc+sy, 0, zc+sy)
S_DisplaySprite(scloud, swidth/2, sheight/2)
Case 2
S_Camera(0, 0, 1, 0)
S_DisplaySprite(splasma, swidth/2, sheight/2)
Case 3
S_Camera(0, 0, 1, 0)
S_light(0, 0, 0, 0, 0, $ffffff, 0)
S_DisplaySprite(sbump, swidth/2, sheight/2, $ff, $888888)
S_DisplaySprite(swobble, swidth/2, sheight/2)
EndSelect
S_DrawText(8, 0, "[F1] Edit shader")
S_DrawText(8, 60, "[Space] Change example")
S_DrawText(8, 120, "[Esc] Quit")
S_DrawText(8, 180, "Use mouse", 40)
S_FlipBuffers()
; While WindowEvent():Wend
Repeat
Event = WindowEvent()
If Event = #PB_Event_CloseWindow:End:EndIf
Until event=0
ExamineKeyboard()
ExamineMouse()
If KeyboardReleased(#PB_Key_F1):S_ShaderEditor(#S_Shader_New) :EndIf
If KeyboardReleased(#PB_Key_Space):example=(example+1)%4:EndIf
If MouseButton(#PB_MouseButton_Right):ReleaseMouse(#True):EndIf
Until KeyboardReleased(#PB_Key_Escape) Or MouseButton(#PB_MouseButton_Middle)
CompilerEndIf
M.