PureBasic Forum
https://www.purebasic.fr/english/

DrawGLSprite
https://www.purebasic.fr/english/viewtopic.php?f=16&t=71920
Page 1 of 1

Author:  ultimzeus [ Thu Dec 13, 2018 10:40 pm ]
Post subject:  DrawGLSprite

This is my first post.
After searching the forum and tested many GL codes, i have discovered how Sprites are handled in purebasic in Opengl sub.
So i wrote my own LoadGLSprite and DrawGLSprite procedures to handle more efficiently sprites.
The trick is that sprites are just textures witch are stored in GL mode by handles. these hundles can be binded by calling SpriteID(Spritenumber) :wink:

Features :
-Now we can display sprites with tint , transparency , rotation , scale , all and parts = in one procedure
-Notice that the same handle returned by load procedure can be used in default DisplaySprite procedure
-Works fine with Engine3D initialized

Works fine in PB 5.30 Windows 8, OpenGL subsysem
Please test other versions if you have time, and feedback

Code:
Procedure.l LoadGLSprite(spname.s,mode.l)
  Protected sp1.l=LoadSprite(#PB_Any,spname,mode)
  glEnable_(#GL_TEXTURE_2D)
  StartDrawing(SpriteOutput(sp1))
  glBindTexture_(#GL_TEXTURE_2D, SpriteID(sp1))
If SpriteDepth(sp1)=32
  glTexImage2D_(#GL_TEXTURE_2D, 0, 4, SpriteWidth(sp1), SpriteHeight(sp1), 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, DrawingBuffer())
Else
  glTexImage2D_(#GL_TEXTURE_2D, 0, 3, SpriteWidth(sp1), SpriteHeight(sp1), 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, DrawingBuffer())
EndIf
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_NEAREST)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_NEAREST)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP)
  StopDrawing()
ProcedureReturn sp1
EndProcedure

; a procedure to test dimensions
Procedure.l Cadrer(x.l,min.l,max.l)
  If x>=max:ProcedureReturn max:EndIf
  If x=<min:ProcedureReturn min:EndIf
  ProcedureReturn x
EndProcedure

; x,y coordinates where to put sprite
; xp,yp coordinates where to begin sprite part ;
; wp,hp : width and height of sprite part ;
; if part coordinates are set to 0,0,0,0 then all the sprite will be drawn
; sc is the scale of the sprite or its part
; rot is the rotation of the sprite or its part
; col is the tint (you can have RGB values)
; alp is the transparency (0=invisible ; 255 is full opaque) , it is practicle for fading effect

Procedure DrawGlSprite(tex.l,x.l,y.l,xp.l=0,yp.l=0,wp.l=0,hp.l=0,sc.f=1,rot.f=0,col.l=#White,alp.l=255)
  ;here we bind the preloaded sprite texture by calling spriteid(tex)
  glEnable_(#GL_TEXTURE_2D) :  glBindTexture_(#GL_TEXTURE_2D,SpriteID(tex))
  ; we get the width and height
  glGetTexLevelParameteriv_(#GL_TEXTURE_2D, 0, #GL_TEXTURE_WIDTH, @w)
  glGetTexLevelParameteriv_(#GL_TEXTURE_2D, 0, #GL_TEXTURE_HEIGHT, @h)
 
  xp=Cadrer(xp,0,w)
  yp=Cadrer(yp,0,h)
  wp=Cadrer(wp,0,w)
  hp=Cadrer(hp,0,h)
   
  If xp=0 And wp=0:wp=w:EndIf
  If yp=0 And hp=0:hp=h:EndIf
   
  sh.l=WindowHeight(0)
  sw.l=WindowWidth(0)
  ;setting envirenment
  glEnable_(#GL_BLEND)
  glDepthFunc_(#GL_LEQUAL)                     
  glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)
 
  glPopMatrix_()
  glMatrixMode_(#GL_PROJECTION)
  glDisable_(#GL_DEPTH)
  glLoadIdentity_()
  gluPerspective_(58.1, WindowWidth(0)/WindowHeight(0)*0.75, 0, 60.0)
  glPushMatrix_()
 
  ; apply the rotation and scale
  glRotatef_(rot,0,0,1)
  glScalef_(sc,sc,1)
  glTranslatef_(CameraX(cam)-0.5,CameraY(cam)-0.5,CameraZ(cam)-0.9)
  Protected x1.f=x/sW
  Protected x2.f=(x+wp)/sW
  ;drawing the sprite or the part of it
  glBegin_(#GL_QUADS)
  glColor4f_(Red(col)/255,Green(col)/255,Blue(col)/255,alp/255)
  glTexCoord2f_(xp/w,(h-yp)/h) : glVertex2f_(x1, (sh-y)/sh)
  glTexCoord2f_((xp+wp)/w,(h-yp)/h) : glVertex2f_(x2,(sh-y)/sh)
  glTexCoord2f_((xp+wp)/w,(h-yp-hp)/h) : glVertex2f_(x2, (sh-y-hp)/sh)
  glTexCoord2f_(xp/w,(h-hp-yp)/h) : glVertex2f_(x1, (sh-y-hp)/sh)
  glEnd_()
  glPopMatrix_()
  glDisable_(#GL_TEXTURE_2D)
EndProcedure


exemple using it

Code:
InitEngine3D()
OpenWindow(0, 270, 100, 800, 600, "Sprite OpenGL demo")
Add3DArchive(#PB_Compiler_Home + "", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0) , WindowHeight(0))

UsePNGImageDecoder(); use PNG images to hundle alphachannel and avoid transparent color handling
Global sp.l
sp=LoadGLSprite("SomeFile.png",#PB_Sprite_AlphaBlending) ; replace SomeFile.png by your own png file
cam.l=CreateCamera(#PB_Any,0,0,100,100)

repeat
  CameraBackColor(Cam,RGB(0,255,55))
  RenderWorld()
  DrawGlSprite(sp,450,60,0,0,150,150,1.1,0,RGB(255,0,0),150);draws a part of a sprite scaled , red tinted and semi transparent
  FlipBuffers()
Until WaitWindowEvent() = #PB_Event_CloseWindow


Author:  Fig [ Fri Dec 14, 2018 6:39 pm ]
Post subject:  Re: DrawGLSprite

What are the advantages versus Purebasic native's sprites ? :?:

Author:  ultimzeus [ Fri Dec 14, 2018 10:25 pm ]
Post subject:  Re: DrawGLSprite

As i said the feastures:
- One procedure makes all
- The Tint feature now works better with opengl. native Purebasic procedure DisplayTransparentSprite does not work at all when mixing tinting and transparency.
- You can mix this procedure with my veryfast DrawRect procedure witch replaces the box procedure (wicth uses the very slow 2Ddrawing mode)

Try this
Code:
Procedure DrawRect(x.l,y.l,w.l,h.l,Col.l)
  glEnable_(#GL_BLEND)
  glDepthFunc_(#GL_LEQUAL)                     
  glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)
  glMatrixMode_(#GL_PROJECTION)
  glLoadIdentity_()
  gluPerspective_(58.1, WindowWidth(0)/WindowHeight(0)*0.75, 0, 60.0)
  ;glMatrixMode_(#GL_MODELVIEW)
  glPushMatrix_()
  glTranslatef_(CameraX(cam)-0.5,CameraY(cam)-0.5,CameraZ(cam)-0.9)
  ;glRotatef_(30.0, 0.0, 0.0, 1.0); uncomment if you want rotation
  glBegin_(#GL_POLYGON)
  glColor4f_(Red(col)/255,Green(col)/255,Blue(col)/255,Alpha(col)/255)
    Protected x1.f=x/WindowWidth(0)
    Protected x2.f=(x+w)/WindowWidth(0)
    glVertex2f_(x1, (WindowHeight(0)-y)/WindowHeight(0))
    glVertex2f_(x2,(WindowHeight(0)-y)/WindowHeight(0))
    glVertex2f_(x2, (WindowHeight(0)-y-h)/WindowHeight(0))
    glVertex2f_(x1, (WindowHeight(0)-y-h)/WindowHeight(0))
 glEnd_()
 glPopMatrix_()
 glDisable_(#GL_TEXTURE_2D)
 
EndProcedure

Author:  Env [ Thu Jan 10, 2019 2:09 pm ]
Post subject:  Re: DrawGLSprite

Tested as working on Linux...

I just want to extend a huge thanks for this as it allows us to finally tint sprites, which is a very underestimated feature, and it's beyond me why it hasn't been implemented natively yet.

Author:  Olliv [ Thu Jan 17, 2019 9:20 pm ]
Post subject:  Re: DrawGLSprite

@Env

Thank you for the feedback.

@UltimZeus

You are using native sprite functions to store texturing datas onto the graphic card. Could you compare executable file size if you use native image functions ?

Author:  Bitblazer [ Thu Jan 17, 2019 10:35 pm ]
Post subject:  Re: DrawGLSprite

Win7x64 - PureBasic 5.70 x86 LTS final - OpenGL subsystem

[ERROR] The specified #Camera is not initialised at

Code:
  glTranslatef_(CameraX(cam)-0.5,CameraY(cam)-0.5,CameraZ(cam)-0.9)


Though this line
Code:
cam.l=CreateCamera(#PB_Any,0,0,100,100)
returns a value.

Author:  Olliv [ Mon Jan 21, 2019 9:59 pm ]
Post subject:  Re: DrawGLSprite

Just insert Global on the start of the line cam.l = CreateCamera(...
Code:
Global Cam.L = CreateCamera(...

Author:  Bitblazer [ Tue Jan 22, 2019 3:17 am ]
Post subject:  Re: DrawGLSprite

Olliv wrote:
Just insert Global on the start of the line cam.l = CreateCamera(...
Code:
Global Cam.L = CreateCamera(...


Thanks. Thats why i always use "enableexplicit()" in my own software :?

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/