Page 2 sur 3

Re: Lib screen (Sprite)

Publié : ven. 17/mai/2024 19:37
par G-Rom
je suis en 6.10, j'utilise toujours pb pour prototyper mes idées, et je ne changerais pas.
en l'état c'est compliquer de gerer ça
Pas spécialement , en amont d'une passe de rendu , un simple tableau structuré avec un champ adéquat fait l'affaire.

pseudo code :
struct sSprite
texture.sTexture
shader.sShader
spatial2D.sSpatial
zorder.i
endstruct

list arendre.sSprite()
....
SortList( arendre(), sSprite, offset(\zorder), ... );


comme je t'ai dis plusieurs fois je connais pas le c (et j'aime pas le c)
Le C ressemble a PB pourtant , c'est juste que c'est plus casse couille a mettre en place , et en C couplé au c++ , tu peu plus facilement faire des libs de qualité , PB a des soucis d'autres nature , macro peu utile , module limité... le C ou le c++ a des lib qui facilite les choses, je pense notamment a glm pour les besoins de calcul matriciel , port audio pour le son ( je me suis pété le cul a essayé de faire fonctionné cela sous pb y a 2 ou 3 ans , je crois que c'est plus facile maintenant (j'avais besoin de capturé le micro) ). j'ai appris avec le temps à utilisé des outils en fonction de mes besoins , que j'aime ou pas l'outils , cela importe peu en réalité. j'ai codé récemment pour mon fils une connerie en VR , j'allais pas le faire en PB , ni en C ou C++ , je suis parti sur godot , même si je n'aime pas le gdscript , je m'y suis collé pour avoir le résultat attendu, et cela a marché. a quoi bon refaire la roue , alors qu'un portage de libs existante a la sauce pb ( comme ogre ) existe ?

(il m'avais promis ça pour dans 3/4 mois, y'a deja 8 mois !)
Il doit avoir le même soucis que moi , le temps. il ne doit pas vivre de PB a plein temps malheureusement. mais cela peu changé , j'ai bossé avec notre futur président de la république , Edouard Philippe ( je suis du Havre ) , faut qu'il mette son langage en avant dans les écoles , qu'il prenne un rdv dans un ministère et cocorico :) , les profs ne jure que par python ou javascript , même dans les filières scientifique.
cela s'appelle faire du lobbying, et le made in France est à mort en avant , bon c'est un métier le lobbying... je n'ai malheureusement plus contact avec la municipalité, j'en avais quand j'étais vice président d'un syndicat de la ville. ce n'est plus le cas aujourd'hui. j'ai complètement changé de métier , ouvert une autre boite avec des employés , et j'ai une petite dimension nationale , donc comme Fred , problème de temps.

D'ailleurs, il faut s'estimé heureux que PB existe encore , et qu'il évolue dans le bon sens.

Re: Lib screen (Sprite)

Publié : sam. 18/mai/2024 14:41
par Guillot
ma parole, mais t'es un vrai évangéliste du c !!

ouai je pense que je passerai par vbo/vao, je lu kek part que c'est plus optimisé

sur le forum anglais ça à l'air de marcher
je pense que t'as bien un probleme de chargement d'image, peut etre que tu utilise une beta 6.10
(regard si t'as pas un "!" dans la marge vers la ligne 750)

Re: Lib screen (Sprite)

Publié : sam. 18/mai/2024 18:01
par G-Rom

Code : Tout sélectionner

ma parole, mais t'es un vrai évangéliste du c !!
pas du tout , mais quand j'ai une vis ph2, je n'utilise pas un plat.

Code : Tout sélectionner

ouai je pense que je passerai par vbo/vao, je lu kek part que c'est plus optimisé
exactement. et pas qu'un peu.
peut etre que tu utilise une beta 6.10
yes, j'ai corrigé cela, cela fonctionne.


Avant que tu partes trop loin dans ton code, quelques remarques.

tu dois pouvoir faire plusieurs passe sur un même sprite avec plusieurs shaders , exemple , le blur , tu as une passe horizontale , verticale.
tu dois pouvoir appliqué un shader ou plusieurs sur l'écran , en dehors d'un sprite donc, cela implique ( comme le multipasse des sprites ) des rendus offscreen, donc sur texture.

Re: Lib screen (Sprite)

Publié : lun. 20/mai/2024 15:52
par threedslider
Guillot a écrit : ven. 17/mai/2024 18:15 comme je t'ai dis plusieurs fois je connais pas le c (et j'aime pas le c)
Bah si tu aimes Purebasic forcement tu vas aimer le C !!! xD

T'as pas essayé et en plus c'est LE langage qui a inspiré par la suite des nombreux langages de programmation 8)
C tout comme Purebasic c'est de la procédural comme programmation, mais C est plus puissant car faut tout gérer par soi même. Et dire que C avait construit un OS comme UNIX grâce à ce langage et de plus il a que 32 mots clé pour construire comme tu veux, il a la qualité d'être simple, puissant, efficace dans la performance 8O

Le tester cela vaut le coup je te rassure !

Je suis d'accord avec G-Rom, Purebasic est malgré puissant mais limité quand même, j'aime bien mais je suis plutôt axé sur C++ qu'en C, encore LE Langage de programmation pour une supplémentaire dimension comme orienté objet, la puissance est là

C comme C++ on peut créer un autre langage de programmation du type BASIC comme Purebasic ou autre langage si tu veux

C'est qui est plutôt bien en C++, c'est de faire avec Vulkan API pour faire la 3D temps réel donc ya pas sa en Purebasic :D

Et enfin je suis pas un évangéliste du C++ mais j'étais bien avant pour programmeur C++ que Purebasic, voilà ;)

En espérant que Purebasic deviendra plus puissant genre comme C ou C++ et là pas de commentaire dessus

Happy coding !

Re: Lib screen (Sprite)

Publié : lun. 20/mai/2024 16:17
par G-Rom
Bah si tu aimes Purebasic forcement tu vas aimer le C !!!
Bah non, rien a voir, PB est fourni prêt a l'emploi, le C n'est qu'une norme , pas PB , PB est fourni avec le compilateur, l'environnement prêt avec les lib , l'ide , en C , y a une chiée de compilateur , d'ide , de config différente , milles manière de compilé un programme , en ligne de com, via make , cmake , etc... c'est tout de suite plus complexe, je ne parle même pas de debbuger ( je ne parle pas de printn() ou std::cout , hein... comme la plupart des programmeurs c/c++ l'utilise ), l'écosystème est 1000x plus compliqué, ici les gens n'ont pas envie de se prendre le choux, juste programmé.

Y a pas de "puissance" dans un langage , mais des fonctionnalités , PB est aussi PERFORMANT que le C , puisqu'il transforme le code C , après avant de voir PB souffrir sur les perfs... va falloir se levé de bonheur. c'est souvent un problème d'interface chaise/clavier dans 99.999% des cas.
Pour vulkan sour PB , y a pas vraiment d'intérêt, pourquoi ?

As tu vu des jeux sortir sur des plateformes style steam qui demande de la ressource graphique next gen ? non.
As tu vu des jeux 2D sortir ou OpenGL ( moderne ) souffre dans les perfs ? non.

Je ne sais pas si tu connais un peu l'api vulkan, ce n'est pas à la porté d'un hobbyste du dimanche quand il pleut , mettre une tel énergie et du temps sur une tel feature , c'est n'importe quoi.
En espérant que Purebasic deviendra plus puissant genre comme C ou C++ et là pas de commentaire dessus
J'ai créer un compilateur asm avec PureBasic pour des chipsets PIC , un petit moteur 3D , et autre appli jamais terminée ou divulguée.
PB fait le café dans 99% des cas, le % restant est pour la 3D ( engine obsolète ) et la 2D qui est à la ramasse aujourd'hui.

Re: Lib screen (Sprite)

Publié : lun. 20/mai/2024 19:05
par threedslider
G-Rom a écrit : lun. 20/mai/2024 16:17 Bah non, rien a voir, PB est fourni prêt a l'emploi, le C n'est qu'une norme , pas PB , PB est fourni avec le compilateur, l'environnement prêt avec les lib , l'ide , en C , y a une chiée de compilateur , d'ide , de config différente , milles manière de compilé un programme , en ligne de com, via make , cmake , etc... c'est tout de suite plus complexe, je ne parle même pas de debbuger ( je ne parle pas de printn() ou std::cout , hein... comme la plupart des programmeurs c/c++ l'utilise ), l'écosystème est 1000x plus compliqué, ici les gens n'ont pas envie de se prendre le choux, juste programmé.
Ah bon lol je suis surpris, bah ya la MINGW de MSYS2 prêt à l'emploi pas besoin de chercher ailleurs si tu veux, pleins de libs prêt à télécharger en ligne de commande et avec Visual Studio tu programmes direct :) Pas besoin de recompilé les libs en soi même et tout et tout ! Et Cmake facilite beaucoup des choses aussi
G-Rom a écrit : lun. 20/mai/2024 16:17 Y a pas de "puissance" dans un langage , mais des fonctionnalités , PB est aussi PERFORMANT que le C , puisqu'il transforme le code C , après avant de voir PB souffrir sur les perfs... va falloir se levé de bonheur. c'est souvent un problème d'interface chaise/clavier dans 99.999% des cas.
Pour vulkan sour PB , y a pas vraiment d'intérêt, pourquoi ?
C/C++ est très puissant j'insiste car très performant en termes de vitesse pour poids lourds de calculs... PB est certes performant aussi mais faudrait comparer en performance pour poids lourds en calcul ... De plus Vulkan va remplacer dans le futur l'OpenGL...
G-Rom a écrit : lun. 20/mai/2024 16:17 As tu vu des jeux sortir sur des plateformes style steam qui demande de la ressource graphique next gen ? non.
Si c'est le CyberPunk 2077
G-Rom a écrit : lun. 20/mai/2024 16:17 Je ne sais pas si tu connais un peu l'api vulkan, ce n'est pas à la porté d'un hobbyste du dimanche quand il pleut , mettre une tel énergie et du temps sur une tel feature , c'est n'importe quoi.
Vulkan c'est comme OpenGL mais donne énormément plus de possibilité c'est un api moderne
G-Rom a écrit : lun. 20/mai/2024 16:17 J'ai créer un compilateur asm avec PureBasic pour des chipsets PIC , un petit moteur 3D , et autre appli jamais terminée ou divulguée.
PB fait le café dans 99% des cas, le % restant est pour la 3D ( engine obsolète ) et la 2D qui est à la ramasse aujourd'hui.
T'es sûr que PB fait 99% le café ? :? Certes PB fait plein des trucs sympas mais cela m’étonnerait ... Peut on construire un petit OS par exemple ? ou un petit compilateur genre à la C ? ... :roll:

OK on va pas faire la guerre sur les langages de programmation, qui pour et qui est meilleur, et désolé pour avoir poster un message pareil je pensais que tout le monde savait ça, un dernière je ne critique pas PB ou qu'il est moins bien c'est pas ça, c'est juste un constat et crois moi j'aime beaucoup PB telle qu'il est, il est plutôt rare un langage Basic aussi performant que C ou C++ après ça dépend sur quel domaine cela va plus vite... Même moi j'ai programmé des nombreux petits programmes fait en PB aussi :mrgreen:

Re: Lib screen (Sprite)

Publié : mar. 21/mai/2024 1:38
par G-Rom
Si c'est le CyberPunk 2077
Je parle avec PB.
Vulkan c'est comme OpenGL mais donne énormément plus de possibilité c'est un api moderne
Non, rien a voir avec opengl , c'est une api graphique , mais la comparaison s'arrête la.
Beaucoup plus difficile a mettre en place. c'est pour cela que mettre en place vulkan sur PB n'a aucun interêt pour le moment,
meme les AAA n'utilise pas ou très peu vulkan , ou l'implémente a peine. vulkan apporte avant tout des performance supplémentaire.
Faudrais déjà qu'il y ai une plétore de jeu PB en 2D qui utilise OpenGL ( moderne ) et même a genoux le hardware, ce qui est loin d'être le cas.
Peut on construire un petit OS par exemple ? ou un petit compilateur genre à la C ? ... :roll:
Petit OS, non , mais compilateur, oui.

Happy coding
@++ ;)

Re: Lib screen (Sprite)

Publié : mar. 21/mai/2024 19:07
par Guillot
@ threedslider
je connais quand même suffisamment le c pour dire que je l'aime pas
faut avouer que c'est beaucoup plus chiant que du basic pour la gestion des string, la gestion de la mémoire
c'est sûr que c'est beaucoup plus puissant, faut de dire que PB est particulièrement archaïque comme basic

@ G-rom
pas l'intention d'aller bcp + loin dans cette lib, je verrai si ça intéresse du monde...
j'aurai bien tenté d'y integrer les commandes de la lib vectordrawing, mais pas trouvé moyen de faire du vrai antialiasing

en somme j'ai 2 cador du c, mais c'est bibi qui se tape l'integration d'ogre3D...

Re: Lib screen (Sprite)

Publié : mar. 21/mai/2024 22:08
par G-Rom
en somme j'ai 2 cador du c, mais c'est bibi qui se tape l'integration d'ogre3D...
Heuuu, je ne suis un cador dans aucun domaine particulier. et j'ai une boite a gérer qui grossi , pas vraiment le temps de m'en occupé , et si cela ne tenais qu'a moi, ogre -> recycle bin :)

Re: Lib screen (Sprite)

Publié : mar. 21/mai/2024 23:23
par Guillot
mais tu t'y connais dans les domaines techniques, là où je suis une bille
si j'avais tes connaissance y'a longtemps que j'aurai fais un outil de création de lib
j'ai plein de fonctions a proposer (surtout en 3d)

je pense pas que ogre soit une daube (même si j'ai pas d'élément de comparaison)
je pense qu'il est tres complet (permet tout), mais en conséquence est trop complexe, reservé au passionné qui veulent comprendre dans le détail le fonctionnement de la 3d

Re: Lib screen (Sprite)

Publié : mer. 22/mai/2024 9:47
par Mesa
Gros travail, merci. :D

Avec l'exemple ci dessous, la rotation, le cas 1, a un drôle de comportement, ça tourne sans s'arrêter. Comment faire une simple rotation ?

Et le cas 3, déplacer une lumière, ne fonctionne pas.

Remarque, je n'y connais absolument rien en shader, je découvre.

Code : Tout sélectionner

;=======================================================
;            Lib screen (Sprite) - pf Shadoko -2024
;=======================================================

EnableExplicit

InitSprite():OpenWindow(0,0,0,10,10,""):OpenWindowedScreen(WindowID(0),0,0,10,10):CloseWindow(0);init opengl to add functions

#PB_Shader_Vector2=2
#PB_Shader_color=10
#GL_TEXTURE0=$84c0
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30
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 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

;============================================================================================ Sprite internal

Structure f2
	x.f
	y.f
EndStructure

Structure sShaderinfo
	num.i          ;shader num
	name.s
	pg.i           ;shader program
	vcode.s
	fcode.s
	Map uloc.i()  ;uniform location
	List sampler.s();uniform sampler name
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

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()

Procedure ImageToGLTextures(image,free=0)
	Protected TextureID,w,h
	
	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, #GL_BGR_EXT, #GL_UNSIGNED_BYTE, DrawingBuffer());  
		Case 32:glTexImage2D_(#GL_TEXTURE_2D, 0,  #GL_RGBA, W, H, 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, DrawingBuffer());  
	EndSelect
	StopDrawing()
	If free:FreeImage(image):EndIf
	ProcedureReturn TextureID  
EndProcedure

Procedure Spriteverif(num)
	If FindMapElement(SpriteInfo(),""+num)=0:MessageRequester("S_ Erreur","Sprite "+num+" does not exist"):CallDebugger:EndIf
EndProcedure

Procedure spritecoord(num)
	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)
	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)
	If FindMapElement(*sh\uloc(),nom)
		;   Debug *sh\name+#TAB$+nom+#TAB$+Hex(v0,#PB_Long)
		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


;============================================================================================ Sprite public
Enumeration S_unit
	#s_unit_Pixel=0
	#s_unit_UV=1
EndEnumeration

Enumeration s_BlendingMode
	#s_BlendingMode_alphablend
	#s_BlendingMode_add
	#s_BlendingMode_custom
EndEnumeration

Enumeration shader2D
	#SHoverlay=1000
	#SHdefault
	#SHblend
	#SHlight
	#SHbump
	#SHflame
	#SHwater
	#SHplasma
	#SHnew
EndEnumeration

Procedure.s supspace(l.s)
	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)
	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:Debug "error shader "+shader+#CRLF$+Shadermessage:EndIf
		ProcedureReturn
	EndIf
	ProcedureReturn shader
EndProcedure

Procedure shaderCreate(num,fshadercode.s,vshadercode.s="",name.s="",dbg=1)
	Static numauto=1000000
	Protected vshader,fshader,Program,vfcode.s,u.s
	If num=-1:num=numauto:numauto+1:EndIf
	
	If fshadercode="":fshader=#SHdefault: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)
	
	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," "):\uloc(n)=glGetUniformLocation(Program,n)
				t=StringField(l,2," "):If FindString(t,"sampler"):AddElement(\sampler()):\sampler()=n:EndIf 
			EndIf
		Until p=0  
	EndWith
	ProcedureReturn num
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_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_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_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)
	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)
			SelectElement(SpriteInfo()\sh\sampler(),txu)
			S_SpriteParameter(num,SpriteInfo()\sh\sampler(),#PB_Shader_Integer,txu):txu+1
		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<>#SHoverlay: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_FreeSprite(num)
	Spriteverif(num)
	glDeleteProgram(SpriteInfo(""+num)\sh\pg)
	DeleteMapElement(SpriteInfo(),""+num)
EndProcedure 

Procedure S_IsSprite(num)
	If FindMapElement(SpriteInfo(),""+num):ProcedureReturn 1:EndIf  
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_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_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_Spritecollision(num1, X1, Y1, num2, X2, Y2); !!! todo
	Spriteverif(num1)
	Spriteverif(num2)
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

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_FlipBuffers() 
	S_globalparameter()
	FlipBuffers()
	glEnable_(#GL_BLEND)
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 tan;% void main() {% tan = 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;vuv.y=1-vuv.y;% vpos=gl_Vertex.xyz;%}"
	SHvertex=ShaderCompile(codevertex,#PB_Shader_Vertex)
	;Debug ReplaceString(codevertex,"%",#LF$)
	shaderCreate(#SHoverlay,"#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")
	shaderCreate(#SHdefault,"#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")
	shaderCreate(#SHblend,"#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")
	shaderCreate(#SHlight,"#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")
	shaderCreate(#SHbump,"#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 tan;%%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(tan.x*tnor.x+tan.y*-tnor.y,  -tan.y*tnor.x+tan.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")
	shaderCreate(#SHflame,"#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")
	shaderCreate(#SHwater,"#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 tan;%%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(tan.x*tnor.x+tan.y*-tnor.y,  -tan.y*tnor.x+tan.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")
	shaderCreate(#SHplasma,"#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")
	shaderCreate(#SHnew,"#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

;========================================================================== shader editor
Global GSE_editor,GSE_message,GSE_list,GSE_run,GSE_savecb,  SE_window, shaderedit

Procedure shaderEditorcallback()
	Protected event,code.s
	
	Macro updateshader
		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=shaderCreate(-1,\""+code+~"\",\"\",\""+ShaderInfo(""+shaderedit)\name+~"\")\n")
			EndSelect
	EndSelect
EndProcedure

Procedure shaderEditor(shader)  
	Protected  wdx=700,xdy=600,nf,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)
	nf=LoadFont(-1,"consolas",10)
	SetGadgetFont(GSE_editor,FontID(nf))
	SetGadgetFont(GSE_message,FontID(nf))
	
	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

;============================================================================================ 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

;============================================================================================ fastfont
Procedure S_InitFont(num,name.s, height.f,style=0,brush=-1,chars.s="")
	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
	
	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,#SHoverlay,im)
	ScrennFont\height=h
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

;-
; CatchSprite
; *ClipSprite
; CopySprite
; *CreateSprite
; *DisplaySprite
; DisplayTransparentSprite
; *FreeSprite
; GrabSprite
; *InitSprite
; *IsSprite
; LoadSprite
; *RotateSprite
; SaveSprite
; SpriteBlendingMode
; SpriteCollision
; SpriteDepth
; SpriteHeight
; SpriteID
; SpriteOutput
; SpritePixelCollision
; SpriteQuality
; SpriteWidth
; *TransformSprite
; TransparentSpriteColor
; *ZoomSprite

; :Alphabetical
; S_BlendingMode(mode, modesource=#PB_Sprite_BlendSourceAlpha, modedestination=#PB_Sprite_BlendInvertSourceAlpha); mode:Enumeration S_BlendingMode,  mosesource/modedestination: cf:SpriteBlendingMode
; S_Camera(x.f,y.f,zoom.f=0,rotation.f=1e10)
; S_ClipSprite(num, x.f, y.f, dx.f, dy.f,mode=0)
; S_CreateSprite(num,shaderNum,image1,image2=-1,image3=-1,image4=-1)
; S_DisplaySprite(num,x.f,y.f,Alpha=$ff,color.l=$ffffff,z.f=0)
; S_DrawText(x,y,t.s,size=-1,color=$ffffffff)
; S_FlipBuffers() 
; S_FreeSprite(num)
; S_Globalparameter()
; S_InitFont(num,name.s, height.f,style=0,brush=-1,chars.s="")
; S_IsSprite(num)
; S_Light(x.f,y.f,z.f,dist.f,color.l,ambiantcolor.l,world=1)
; S_RotateSprite(num,angle.f,mode=0)
; S_Spritecollision(num1, X1, Y1, num2, X2, Y2); !!! todo
; S_SpriteOrigine(num,x.f,y.f,unit=#s_unit_UV) ; unit:Enumeration S_unit
; 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
; S_SpriteUV(num, u1.f, v1.f, u2.f, v2.f, u3.f, v3.f, u4.f, v4.f)
; S_TransformSprite(num, X1.f, Y1.f, X2.f, Y2.f, X3.f, Y3.f, X4.f, Y4.f)
;====================================================================================================================================================
;====================================================================================================================================================
;====================================================================================================================================================

DisableExplicit

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

;----------------------------- 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()


bubbles=S_CreateSprite(-1,#SHdefault,10):S_SpriteOrigine(bubbles,0.5,0.5)

; Define.f sy,a,ai,py,dy,t,   rot,zw=0.5*8,zc=0.25

MouseLocate(swidth/2,sheight/2)

example=0
tiks=1

Repeat
	
	
	ClearScreen(0)
	
	S_BlendingMode(#s_BlendingMode_alphablend)
	
	Select example
		Case 0
			;- zoom
			S_ZoomSprite(bubbles,tiks,tiks)
			S_DisplaySprite(bubbles,swidth/2,sheight/2)
			
			
		Case 1
			;- rotation
			S_RotateSprite(bubbles,tiks,#PB_Relative)
			S_DisplaySprite(bubbles,swidth/2,sheight/2)
			
		Case 2
			;Camera
			S_Camera(MouseX(),MouseY(),tiks,0)
			S_DisplaySprite(bubbles,swidth/2,sheight/2)
			
		Case 3
			;light
			S_light(MouseX(),MouseY(),sheight/2,sheight*4,$ffffff,$0,0)
			;       S_DisplaySprite(bubbles,swidth/2,sheight/2,$ff,$888888)
			S_DisplaySprite(bubbles,swidth/2,sheight/2)
			
	EndSelect
	S_DrawText(8,0,"X="+Str(MX)+":"+"Y="+Str(MY)+":"+Str(tiks),30)
	S_DrawText(8,60,"[Space] Change example",30)
	S_DrawText(8,120,"[Esc] Quit",30)
	S_DrawText(8,180,"Use mouse wheel",30)
	s_FlipBuffers()
	
	While WindowEvent():Wend
	ExamineKeyboard()
	ExamineMouse()  
	tiks +MouseWheel()
	MX=MouseX()
	MY=MouseY()
	
	If KeyboardReleased(#PB_Key_Space):example=(example+1)%4:tiks=0:EndIf
Until KeyboardReleased(#PB_Key_Escape) Or MouseButton(3)

M.

Re: Lib screen (Sprite)

Publié : mer. 22/mai/2024 11:05
par Guillot
- rotation:
normal, t'as mis #PB_relative !

- lumiere:
la gestion de la lumiere n'est pas prise en compte avec touts les shaders, seulement avec #SHlight, #SHbump et #SHblend (et shwoble de mon exemple je crois)
pas utile de la mettre de partout
dans ton cas, remplace #SHdefault par #SHlight

Re: Lib screen (Sprite)

Publié : mer. 22/mai/2024 13:25
par Mesa
Nickel !

C'est vrai qu'il manque les collisions qui permetrait de faire des jeux, et une petite aide (.chm ou html mais gros travail aussi...)

M.

Re: Lib screen (Sprite)

Publié : mer. 22/mai/2024 15:25
par threedslider
G-Rom a écrit : mar. 21/mai/2024 1:38 Je parle avec PB.
Ah ok, j'ai même testé un truc de fou un Vulkan pour wrapper dans Purebasic, pour l'instant c'est loin d’être bien marcher :D
G-Rom a écrit : mar. 21/mai/2024 1:38 Non, rien a voir avec opengl , c'est une api graphique , mais la comparaison s'arrête la.
Beaucoup plus difficile a mettre en place. c'est pour cela que mettre en place vulkan sur PB n'a aucun interêt pour le moment,
meme les AAA n'utilise pas ou très peu vulkan , ou l'implémente a peine. vulkan apporte avant tout des performance supplémentaire.
Au contraire, actuellement le C++ est utilisé beaucoup avec Vulkan, juste regarde sur Github tu verras ils sont nombreux
G-Rom a écrit : mar. 21/mai/2024 1:38 Petit OS, non , mais compilateur, oui.
Pas en ASM mais bien pure en PB ? Non ?
G-Rom a écrit : mar. 21/mai/2024 1:38 Happy coding
@++ ;)
Merci et à toi même également ^^

Re: Lib screen (Sprite)

Publié : mer. 22/mai/2024 15:29
par Mesa
J'ai fait un module.

[Edition1 le 23 05 2024]

Code : Tout sélectionner

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