It is currently Wed Dec 11, 2019 5:49 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: DrawGLSprite
PostPosted: Thu Dec 13, 2018 10:40 pm 
Offline
New User
New User

Joined: Thu Sep 20, 2018 12:27 pm
Posts: 6
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



Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Fri Dec 14, 2018 6:39 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Apr 30, 2009 5:23 pm
Posts: 307
Location: Côtes d'Azur, France
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.70 LTS


Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Fri Dec 14, 2018 10:25 pm 
Offline
New User
New User

Joined: Thu Sep 20, 2018 12:27 pm
Posts: 6
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


Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Thu Jan 10, 2019 2:09 pm 
Offline
Enthusiast
Enthusiast
User avatar

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


Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Thu Jan 17, 2019 9:20 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Sep 22, 2009 10:41 pm
Posts: 456
@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 ?


Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Thu Jan 17, 2019 10:35 pm 
Offline
Enthusiast
Enthusiast

Joined: Mon Apr 10, 2017 6:17 pm
Posts: 302
Location: Germany
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.

_________________
webpage


Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Mon Jan 21, 2019 9:59 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Sep 22, 2009 10:41 pm
Posts: 456
Just insert Global on the start of the line cam.l = CreateCamera(...
Code:
Global Cam.L = CreateCamera(...


Top
 Profile  
Reply with quote  
 Post subject: Re: DrawGLSprite
PostPosted: Tue Jan 22, 2019 3:17 am 
Offline
Enthusiast
Enthusiast

Joined: Mon Apr 10, 2017 6:17 pm
Posts: 302
Location: Germany
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 :?

_________________
webpage


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye