Page 1 of 2

OpenGL Useful Integrated 2D Functions

Posted: Sat Jun 08, 2019 12:06 am
by ultimzeus
Hi
It is my second post in this forum.
After long nights of testing and coding, i made some discoverings in purebasic langage (hidden concepts) that i just wanted to share with community

The post is about how to deal in OpenGL env with new 2D functions and just keep using the native purebasic 2D functions.

1- A new Drawsprite and DrawSpriteRect : with Rotation,tinting, alpha, and scaling all in one function. GREAT! but the very exciting thing is that we no more deal with purebasic sprites, but rather than that messy purebasic concept we will draw directily purebasic loaded TEXTURES!!
Why textures?
because we use them for 3D functions : imagine that rather than having 3 different concepts : images, sprites, textures, we just can have one thing, no convertions, no confusing variables anymore. just one only concept for 2D an 3D functions in the same loop.!

2- A new runtime super fast Render to texture function with no shaders use, at all, simple as SartRTT(Texture) then StopRTT()...an between them all the 2D drawings (ie Drawsprite, drawspriterect, DrawRect...)

First lets start by setting Env

Code: Select all

  InitEngine3D()
  Add3DArchive(GetTemporaryDirectory(),#PB_3DArchive_FileSystem)
  Add3DArchive(GetCurrentDirectory(),#PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home, #PB_3DArchive_FileSystem)
  
  Parse3DScripts()
  InitSprite()
  InitMouse()
  InitKeyboard()
  OpenWindow(0, 0, 0, 800, 600, "New OpenGL",#PB_Window_Tool)
  res.l=OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0,0,0,#PB_Screen_NoSynchronization)   
  
  Global sh.l=WindowHeight(0)
  Global sw.l=WindowWidth(0)
  Global Fbo.l  ; this is a framebuffer to use later with textures (dont bother about him)
  
  UsePNGImageDecoder()

; now the GL setting

  glViewport_(0, 0,WindowWidth(0),WindowHeight(0))
  ; Set current Mode to projection(ie: 3d) 
    glMatrixMode(#GL_PROJECTION) 
  ;'Load identity matrix to projection matrix 
    glLoadIdentity() 
  ;'Set gluPerspective params 
    Aspect.f = WindowWidth(0)/WindowHeight(0);
   ;'use glu Perspective to set our 3d frustum dimension up 
    gluPerspective_(45.0, aspect, 1.0, 60.0) 
   ;'Modelview mode ie. Matrix that does things to anything we draw as in lines, points, tris, etc. 
    glMatrixMode(#GL_MODELVIEW) 
   ;'load identity(clean) matrix to modelview 
    glLoadIdentity() 
    glShadeModel(#GL_SMOOTH)        ;         'set shading to smooth(try GL_FLAT) 
	glClearColor(0.0, 0.0, 0.0, 1.0);        'set Clear color to BLACK 
	glClearDepth(1.0)               ;        'Set Depth buffer to 1(z-Buffer) 
	glDisable(#GL_DEPTH_TEST)       ;         'Disable Depth Testing so that our z-buffer works 
	;'compare each incoming pixel z value with the z value present in the depth buffer 
	;'LEQUAL means than pixel is drawn if the incoming z value is less than 
	;'or equal to the stored z value 
	glDepthFunc(#GL_LEQUAL) 
	;'have one or more material parameters track the current color 
	;'Material is your 3d model 
	glEnable(#GL_COLOR_MATERIAL) 
       ; 'Enable Texturing 
    glEnable(#GL_TEXTURE_2D) 
   ;'Tell openGL that we want the best possible perspective transform 
    glHint(#GL_PERSPECTIVE_CORRECTION_HINT, #GL_NICEST) 
    ;'Disable Backface culling
     glDisable (#GL_CULL_FACE)
     glPolygonMode(#GL_FRONT,#GL_FILL) 
    ;enable blending For transparency 
    glEnable(#GL_BLEND)    	    
    glBlendFunc(#GL_SRC_ALPHA,#GL_ONE_MINUS_SRC_ALPHA)
    glDisable(#GL_DEPTH_TEST )
    glEnable(#GL_ALPHA_TEST )
    glAlphaFunc(#GL_GREATER, 0)
    glDisable(#GL_STENCIL_TEST)
    glDisable(#GL_TEXTURE_1D)
    glDisable(#GL_LOGIC_OP)
    glDisable(#GL_DITHER)
    glDisable(#GL_FOG)
    glHint(#GL_POINT_SMOOTH_HINT, #GL_FASTEST)
    glHint(#GL_LINE_SMOOTH_HINT , #GL_FASTEST)
    glPointSize( 1 )
    glLineWidth( 1 )
setting camera and light that we can draw 3D things

Code: Select all

cam=CreateCamera(-1, 0, 0, 100, 100)
light=CreateLight(-1,RGB(255, 255, 255),13*32,320,32*12,#PB_Light_Directional)
SetLightColor(light, #PB_Light_SpecularColor, RGB(255,255,255))
LightLookAt(light, 0, 10, 0)
AmbientColor(RGB(150, 150, 150))
  
  MoveCamera(cam,0,180,180);
  CameraLookAt(cam,0,0,0)
Now the function that loads the textures : notice that it is as simple as the native loadtexture, but the trick is that we just want to detect
where the purebasic compiler will store the data. in another word : lets hack the system and get the internal Opengl ID of the loaded texture in order to use it for all the drawing functions and at hte same time , keep ist use also for native 3D functions. we will have a unique ID for the texture.

Code: Select all


Procedure.l LoadTextur(texN.s)
  Protected glsp.l
  glEnable_(#GL_TEXTURE_2D)
  ME.l=Loadimage(-1,TexN)  ;load the image the normal way
  If ME=0:Debug(TexN +" not found"):ProcedureReturn -1:EndIf 
  w=ImageWidth(ME):h=ImageHeight(ME)
  ttx.l=CreateTexture(-1,w,h)
  glGetIntegerv_(#GL_TEXTURE_BINDING_2D, @glsp)  ; => here is the trick = we just get the internal ID of the last created texture (this 
                                                                                ;       ID is  set by the OpenGl driver itself by using the 
                                                                                ;       glgentextures function  
  FreeTexture(ttx); we release the created texture because we dont need a different ID (whitch is given by purebasic not OpenGL driver)
  CreateTexture(glsp,w,h); now that we know whitch ID is internal we create a pb texture with the same ID just to have the same ID
                                    ; for all the functions (3D native, and new ones)                        
 ; here we tell the GL driver about the  internal format, clipping, filtering , width, height.. of the texture
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP_TO_BORDER)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP_TO_BORDER)
  glTexImage2D(#GL_TEXTURE_2D, 0, 4, w,h, 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, #Null) 
  ; here we will store the image into the texture
  StartDrawing(TextureOutput(glsp))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  DrawAlphaImage(ImageID(ME),0,0)
  StopDrawing()
  ; dont forget to free the image
  freeimage(ME)
  ProcedureReturn glsp
EndProcedure

;We are done. Now we can use our texture for every thing : u just have to load any image
Global Tx1.l=Loadtextur("someimage.png")

The drawing functions :

Code: Select all

Procedure DrawSprite(tex.l,x.f,y.f,col.l=$FFFFFFFF,rot.f=0,sc.f=1)
  If sc=<0:ProcedureReturn :EndIf
  glEnable_(#GL_TEXTURE_2D) :  glBindTexture_(#GL_TEXTURE_2D,tex)
  Protected w.l,h.l
  glGetTexLevelParameteriv(#GL_TEXTURE_2D,0,#GL_TEXTURE_WIDTH, @w)
  glGetTexLevelParameteriv(#GL_TEXTURE_2D,0,#GL_TEXTURE_HEIGHT, @h)
  glRotatef_(rot,0,0,1)
  If sc>0:glScalef_(sc,sc,1):x/sc:y/sc:EndIf
  cx1.f=0
  cx2.f=1
  cy1.f=1 
  cy2.f=0 
  x1.f=x
  x2.f=x+w
  y2.f=y+h  
  y1.f=y 
     
  glColor4ub(Red(col),Green(col),Blue(col),Alpha(col))
  glBegin_(#GL_QUADS)
  glTexCoord2f(cx1,cy2);
  glVertex2i(x1,y1);
  glTexCoord2f(cx1,cy1);
     glVertex2i(x1,y2);
     glTexCoord2f(cx2,cy1);
     glVertex2i(x2,y2);
     glTexCoord2f(cx2,cy2);
     glVertex2i(x2,y1);  ;
  glEnd_()
  glPopMatrix()
  glDisable_(#GL_TEXTURE_2D)
EndProcedure
The Begin2D & End2D procedures : it sets up the envirnment before we can render 2D stuff in the loop , that we can
mix 2D and 3D stuff

Code: Select all

Procedure Begin2D()
glDisable(#GL_DEPTH_TEST)
glDisable (#GL_CULL_FACE)
	
	glEnable(#GL_BLEND)    	    
	glBlendFunc(#GL_SRC_ALPHA,#GL_ONE_MINUS_SRC_ALPHA)
	
	glDisable(#GL_DEPTH_TEST )
	
	glEnable(#GL_ALPHA_TEST )
	glAlphaFunc(#GL_GREATER, 0)

	glDisable(#GL_STENCIL_TEST)
	glDisable(#GL_TEXTURE_1D)
	glDisable(#GL_LIGHTING)
	glDisable(#GL_LOGIC_OP)
	glDisable(#GL_DITHER)
	glDisable(#GL_FOG)

	glHint(#GL_POINT_SMOOTH_HINT, #GL_FASTEST)
	glHint(#GL_LINE_SMOOTH_HINT , #GL_FASTEST)

	glPointSize( 1 )
	glLineWidth( 1 )
	
	Dim ViewPort.i(3)

    glGetIntegerv_(#GL_VIEWPORT, @ViewPort(0))

    glMatrixMode_(#GL_PROJECTION)    
    glPushMatrix_()
    glLoadIdentity_()
    glOrtho_(0, ViewPort(2),ViewPort(3),0,0, -1)
    glMatrixMode_(#GL_MODELVIEW)
    glPushMatrix_()
    glLoadIdentity_()
EndProcedure

Procedure End2D()  
    glMatrixMode(#GL_PROJECTION)
    glPopMatrix()
    glMatrixMode(#GL_MODELVIEW)
    glPopMatrix()
EndProcedure

The Main loop

Code: Select all

Repeat
  ExamineKeyboard()
 ;  3D Stuff comes HERE  
  
  RenderWorld()    
;2D Stuff comes HERE  
  Begin2D()
  DrawSprite(tx1,200,0,RGBA($ff,$ff,$ff,200))
  End2D()
      
  Flipbuffers()
  	
Until KeyboardPushed(#PB_Key_Escape)


Just try it and tell me your feedback
The DrawSpriteRect, DrawRect, StartRTT function will come in next posts.

Tested on Purebasic 5.3 Windows 8 64bit
Dont know about other versions

Re: OpenGL Useful Integrated 2D Functions

Posted: Thu Aug 15, 2019 8:00 am
by dige
Hi ultimzeus,

unfortunately, I can't test your example. Aren't the underscores behind the OpenGl commands missing?

Ciao Dige

Re: OpenGL Useful Integrated 2D Functions

Posted: Thu Aug 15, 2019 12:56 pm
by djes
I just think for a very long time that Fred should reinforce the 2D/3D engine with OpenGl the only real industry standard as first choice. But MS was badly lobbying there. Opening some structures could help, and to overload some functions too.

Re: OpenGL Useful Integrated 2D Functions

Posted: Tue Aug 27, 2019 5:43 pm
by infratec
To make it work:

Code: Select all

#GL_CLAMP_TO_BORDER = $812D


UsePNGImageDecoder()
InitEngine3D()

Procedure.l LoadTextur(texN.s)
  Protected glsp.l
  glEnable_(#GL_TEXTURE_2D)
  ME.l=LoadImage(-1,TexN)  ;load the image the normal way
  If ME=0:Debug(TexN +" not found"):ProcedureReturn -1:EndIf
  w=ImageWidth(ME):h=ImageHeight(ME)
  ttx.l=CreateTexture(-1,w,h)
  glGetIntegerv_(#GL_TEXTURE_BINDING_2D, @glsp)  ; => here is the trick = we just get the internal ID of the last created texture (this
                                                 ; ID is  set by the OpenGl driver itself by using the
                                                 ; glgentextures function 
  FreeTexture(ttx)                               ; we release the created texture because we dont need a different ID (whitch is given by purebasic not OpenGL driver)
  CreateTexture(glsp,w,h)                        ; now that we know whitch ID is internal we create a pb texture with the same ID just to have the same ID
                                                 ; for all the functions (3D native, and new ones)                       
                                                 ; here we tell the GL driver about the  internal format, clipping, filtering , width, height.. of the texture
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP_TO_BORDER)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP_TO_BORDER)
  glTexImage2D_(#GL_TEXTURE_2D, 0, 4, w,h, 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, #Null)
  ; here we will store the image into the texture
  StartDrawing(TextureOutput(glsp))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  DrawAlphaImage(ImageID(ME),0,0)
  StopDrawing()
  ; dont forget to free the image
  FreeImage(ME)
  ProcedureReturn glsp
EndProcedure






Procedure DrawSprite(tex.l,x.f,y.f,col.l=$FFFFFFFF,rot.f=0,sc.f=1)
  If sc=<0:ProcedureReturn :EndIf
  glEnable_(#GL_TEXTURE_2D) :  glBindTexture_(#GL_TEXTURE_2D,tex)
  Protected w.l,h.l
  glGetTexLevelParameteriv_(#GL_TEXTURE_2D,0,#GL_TEXTURE_WIDTH, @w)
  glGetTexLevelParameteriv_(#GL_TEXTURE_2D,0,#GL_TEXTURE_HEIGHT, @h)
  glRotatef_(rot,0,0,1)
  If sc>0:glScalef_(sc,sc,1):x/sc:y/sc:EndIf
  cx1.f=0
  cx2.f=1
  cy1.f=1
  cy2.f=0
  x1.f=x
  x2.f=x+w
  y2.f=y+h 
  y1.f=y
  
  glColor4ub_(Red(col),Green(col),Blue(col),Alpha(col))
  glBegin_(#GL_QUADS)
  glTexCoord2f_(cx1,cy2);
  glVertex2i_(x1,y1)    ;
  glTexCoord2f_(cx1,cy1);
  glVertex2i_(x1,y2)    ;
  glTexCoord2f_(cx2,cy1);
  glVertex2i_(x2,y2)    ;
  glTexCoord2f_(cx2,cy2);
  glVertex2i_(x2,y1)    ;  ;
  glEnd_()
  glPopMatrix_()
  glDisable_(#GL_TEXTURE_2D)
EndProcedure




Procedure Begin2D()
  glDisable_(#GL_DEPTH_TEST)
  glDisable_(#GL_CULL_FACE)
  
  glEnable_(#GL_BLEND)          
  glBlendFunc_(#GL_SRC_ALPHA,#GL_ONE_MINUS_SRC_ALPHA)
  
  glDisable_(#GL_DEPTH_TEST )
  
  glEnable_(#GL_ALPHA_TEST )
  glAlphaFunc_(#GL_GREATER, 0)
  
  glDisable_(#GL_STENCIL_TEST)
  glDisable_(#GL_TEXTURE_1D)
  glDisable_(#GL_LIGHTING)
  glDisable_(#GL_LOGIC_OP)
  glDisable_(#GL_DITHER)
  glDisable_(#GL_FOG)
  
  glHint_(#GL_POINT_SMOOTH_HINT, #GL_FASTEST)
  glHint_(#GL_LINE_SMOOTH_HINT , #GL_FASTEST)
  
  glPointSize_( 1 )
  glLineWidth_( 1 )
  
  Dim ViewPort.i(3)
  
  glGetIntegerv_(#GL_VIEWPORT, @ViewPort(0))
  
  glMatrixMode_(#GL_PROJECTION)   
  glPushMatrix_()
  glLoadIdentity_()
  glOrtho_(0, ViewPort(2),ViewPort(3),0,0, -1)
  glMatrixMode_(#GL_MODELVIEW)
  glPushMatrix_()
  glLoadIdentity_()
EndProcedure

Procedure End2D() 
  glMatrixMode_(#GL_PROJECTION)
  glPopMatrix_()
  glMatrixMode_(#GL_MODELVIEW)
  glPopMatrix_()
EndProcedure






Add3DArchive(GetTemporaryDirectory(),#PB_3DArchive_FileSystem)
Add3DArchive(GetCurrentDirectory(),#PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home, #PB_3DArchive_FileSystem)

Parse3DScripts()
InitSprite()
InitMouse()
InitKeyboard()
OpenWindow(0, 0, 0, 800, 600, "New OpenGL",#PB_Window_Tool)
res.l=OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0,0,0,#PB_Screen_NoSynchronization)   

Global sh.l=WindowHeight(0)
Global sw.l=WindowWidth(0)
Global Fbo.l  ; this is a framebuffer to use later with textures (dont bother about him)

;We are done. Now we can use our texture for every thing : u just have to load any image
Global Tx1.l=Loadtextur(#PB_Compiler_Home + "Examples\3D\Data\OPE\textures\bigflame.png")

; now the GL setting

glViewport_(0, 0,WindowWidth(0),WindowHeight(0))
; Set current Mode to projection(ie: 3d)
glMatrixMode_(#GL_PROJECTION)
;'Load identity matrix to projection matrix
glLoadIdentity_()
;'Set gluPerspective params
Aspect.f = WindowWidth(0)/WindowHeight(0);
                                         ;'use glu Perspective to set our 3d frustum dimension up
gluPerspective_(45.0, aspect, 1.0, 60.0)
;'Modelview mode ie. Matrix that does things to anything we draw as in lines, points, tris, etc.
glMatrixMode_(#GL_MODELVIEW)
;'load identity(clean) matrix to modelview
glLoadIdentity_()
glShadeModel_(#GL_SMOOTH)        ;         'set shading to smooth(try GL_FLAT)
glClearColor_(0.0, 0.0, 0.0, 1.0);        'set Clear color to BLACK
glClearDepth_(1.0)               ;        'Set Depth buffer to 1(z-Buffer)
glDisable_(#GL_DEPTH_TEST)       ;         'Disable Depth Testing so that our z-buffer works
                                ;'compare each incoming pixel z value with the z value present in the depth buffer
                                ;'LEQUAL means than pixel is drawn if the incoming z value is less than
                                ;'or equal to the stored z value
glDepthFunc_(#GL_LEQUAL)
;'have one or more material parameters track the current color
;'Material is your 3d model
glEnable_(#GL_COLOR_MATERIAL)
; 'Enable Texturing
glEnable_(#GL_TEXTURE_2D)
;'Tell openGL that we want the best possible perspective transform
glHint_(#GL_PERSPECTIVE_CORRECTION_HINT, #GL_NICEST)
;'Disable Backface culling
glDisable_(#GL_CULL_FACE)
glPolygonMode_(#GL_FRONT,#GL_FILL)
;enable blending For transparency
glEnable_(#GL_BLEND)          
glBlendFunc_(#GL_SRC_ALPHA,#GL_ONE_MINUS_SRC_ALPHA)
glDisable_(#GL_DEPTH_TEST )
glEnable_(#GL_ALPHA_TEST )
glAlphaFunc_(#GL_GREATER, 0)
glDisable_(#GL_STENCIL_TEST)
glDisable_(#GL_TEXTURE_1D)
glDisable_(#GL_LOGIC_OP)
glDisable_(#GL_DITHER)
glDisable_(#GL_FOG)
glHint_(#GL_POINT_SMOOTH_HINT, #GL_FASTEST)
glHint_(#GL_LINE_SMOOTH_HINT , #GL_FASTEST)
glPointSize_( 1 )
glLineWidth_( 1 )

cam=CreateCamera(-1, 0, 0, 100, 100)
light=CreateLight(-1,RGB(255, 255, 255),13*32,320,32*12,#PB_Light_Directional)
SetLightColor(light, #PB_Light_SpecularColor, RGB(255,255,255))
LightLookAt(light, 0, 10, 0)
AmbientColor(RGB(150, 150, 150))

MoveCamera(cam,0,180,180);
CameraLookAt(cam,0,0,0)



Repeat
  WindowEvent()
  
  ExamineKeyboard()
  ;  3D Stuff comes HERE 
  
  RenderWorld()   
  ;2D Stuff comes HERE 
  Begin2D()
  DrawSprite(tx1,200,0,RGBA($ff,$ff,$ff,200))
  End2D()
  
  FlipBuffers()
  
Until KeyboardPushed(#PB_Key_Escape)

Re: OpenGL Useful Integrated 2D Functions

Posted: Tue Aug 27, 2019 6:03 pm
by Mijikai
Ogre should be able to produce textured quads?

Re: OpenGL Useful Integrated 2D Functions

Posted: Sun Mar 20, 2022 12:26 pm
by ShadowStorm
Hi, it doesn't work with PB 86 and 64 bits.
The screen stays black.

Re: OpenGL Useful Integrated 2D Functions

Posted: Sun Mar 20, 2022 4:55 pm
by infratec
ShadowStorm wrote: Sun Mar 20, 2022 12:26 pm Hi, it doesn't work with PB 86 and 64 bits.
Sorry, but I still not know with which version it is not working.

If I interprete your sentence I think youi mean it doesn't work in PB x86 and x64.
Ok, so it doesn't work at all.

But From which version of PB are you talking? (5.73 ... 6.00B5 ...)
Which OS are you using? (Windows, linux, macOS, raspian)

Re: OpenGL Useful Integrated 2D Functions

Posted: Sun Mar 20, 2022 5:46 pm
by ShadowStorm
Hello:

Windows 10 * 64 bits.

PureBasic 5.72 LTS Beta 3 86 Bits.
PureBasic 6.00 Beta 1 64 Bits.

Thanks :)

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 8:00 am
by infratec
I just tested the code with PB 5.73 x86 on Win 10 x64: it works.

But .... you have to write opengl in the field Library Subsystem in compiler options.

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 11:54 am
by ShadowStorm
Hi, yes with write "opengl" with PureBasic 5.72 LTS Beta 3 86 Bits, I can see something
but it's just a kind of grey spot, on a black font and nothing more.

And on PureBasic 6.00 Beta 1 64 Bits, nothing.

Moreover I understand why sometimes you have to indicate "opengl" and other times not :?

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 11:58 am
by infratec
If you use opengl, then you need to write this in the compiler option field. Always.
Because default is directx.

And the program does exactly what is written in the code.

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 1:11 pm
by ShadowStorm
No, it doesn't work!
Even with opengl writing, in 64 bits.

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 1:30 pm
by infratec
As I told you it works with 5.73 x86.

You are using a beta version which is not finished and not fully working.
What does you expect from a beta version? If it works 100% then it is not a beta.

So you can place a bug report for the beta versin in the bug section.

Does it work with 5.73 x64 ?
I don't have this version installed.

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 1:33 pm
by ShadowStorm
I don't know.

Re: OpenGL Useful Integrated 2D Functions

Posted: Mon Mar 21, 2022 4:19 pm
by Mindphazer
ShadowStorm wrote: Mon Mar 21, 2022 1:33 pm I don't know.
Use your hands and brain, download PB 5.73 x64 and try.