DrawGLSprite

Advanced game related topics
ultimzeus
New User
New User
Posts: 6
Joined: Thu Sep 20, 2018 12:27 pm

DrawGLSprite

Post by ultimzeus »

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: Select all

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: Select all

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

User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: DrawGLSprite

Post by Fig »

What are the advantages versus Purebasic native's sprites ? :?:
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
ultimzeus
New User
New User
Posts: 6
Joined: Thu Sep 20, 2018 12:27 pm

Re: DrawGLSprite

Post by ultimzeus »

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: Select all

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
Env
Enthusiast
Enthusiast
Posts: 151
Joined: Tue Apr 27, 2010 3:20 pm
Location: Wales, United Kingdom

Re: DrawGLSprite

Post by Env »

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.
Thanks!
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: DrawGLSprite

Post by Olliv »

@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 ?
Bitblazer
Enthusiast
Enthusiast
Posts: 733
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: DrawGLSprite

Post by Bitblazer »

Win7x64 - PureBasic 5.70 x86 LTS final - OpenGL subsystem

[ERROR] The specified #Camera is not initialised at

Code: Select all

  glTranslatef_(CameraX(cam)-0.5,CameraY(cam)-0.5,CameraZ(cam)-0.9)
Though this line

Code: Select all

cam.l=CreateCamera(#PB_Any,0,0,100,100)
returns a value.
webpage - discord chat links -> purebasic GPT4All
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: DrawGLSprite

Post by Olliv »

Just insert Global on the start of the line cam.l = CreateCamera(...

Code: Select all

Global Cam.L = CreateCamera(... 
Bitblazer
Enthusiast
Enthusiast
Posts: 733
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: DrawGLSprite

Post by Bitblazer »

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

Code: Select all

Global Cam.L = CreateCamera(... 
Thanks. Thats why i always use "enableexplicit()" in my own software :?
webpage - discord chat links -> purebasic GPT4All
Post Reply