OpenGLGadget - drawing sprite (perfect pixel)
Posted: Thu Jun 04, 2015 11:32 pm
Just an OpenGL code to emulate sprite drawing
Code: Select all
;DOCS:
; http:;//www.gamedev.net/page/resources/_/technical/opengl/rendering-efficient-2d-sprites-in-opengl-using-r2429
; https://open.gl/textures
#GL_TEXTURE_RECTANGLE_NV=$84F5
#GL_CLAMP_TO_EDGE=$812F
Global Dim glTextureIDs.i(0)
Global screenGL, screenColor=RGBA(0, 0, 0, 0)
Global glSpriteTexture, w, h, tint=RGB(255, 255, 255)
Global scaleX.f=1.0, scaleY.f=1.0
Procedure SetupGL(screenW, screenH)
glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_()
glOrtho_(0, screenW, 0, screenH, -5.0, 5.0)
glMatrixMode_(#GL_MODELVIEW)
glLoadIdentity_()
glEnable_(#GL_CULL_FACE)
glPushAttrib_(#GL_DEPTH_BUFFER_BIT | #GL_LIGHTING_BIT);
glDisable_(#GL_DEPTH_TEST)
glDisable_(#GL_LIGHTING)
glDisable_(#GL_BLEND)
EndProcedure
Procedure.i LoadTextureGL(image)
;// Generate 100 texture IDs (only one time)
If ArraySize(glTextureIDs())=0
ReDim glTextureIDs(100)
glGenTextures_(ArraySize(glTextureIDs()), @glTextureIDs())
EndIf
Static glTextureID=0
;// Enable the texture rectangle extension
glEnable_(#GL_TEXTURE_RECTANGLE_NV)
;// Bind the texture using #GL_TEXTURE_RECTANGLE_NV
glTextureID + 1
glBindTexture_(#GL_TEXTURE_RECTANGLE_NV, glTextureIDs(glTextureID))
;// Enable NEAREST filtering on this texture (for old school style)
glTexParameteri_(#GL_TEXTURE_RECTANGLE_NV, #GL_TEXTURE_MIN_FILTER, #GL_NEAREST)
glTexParameteri_(#GL_TEXTURE_RECTANGLE_NV, #GL_TEXTURE_MAG_FILTER, #GL_NEAREST)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP_TO_EDGE);
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP_TO_EDGE);
;// Write the 32-bit RGBA texture buffer To video memory
StartDrawing(ImageOutput(image))
glTexImage2D_(#GL_TEXTURE_RECTANGLE_NV, 0, #GL_RGBA, ImageWidth(image), ImageHeight(image), 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, DrawingBuffer())
StopDrawing()
ProcedureReturn glTextureIDs(glTextureID)
EndProcedure
Procedure RenderGL()
;black background
glClearColor_(Red(screenColor) / 255.0, Green(screenColor) / 255.0, Blue(screenColor) / 255.0, Alpha(screenColor) / 255.0)
glClear_(#GL_COLOR_BUFFER_BIT)
;// Bind the texture To the polygons
glBindTexture_(#GL_TEXTURE_RECTANGLE_NV, glSpriteTexture)
;// Set the primitive color To white
glColor3f_(Red(tint) / 255.0, Green(tint) / 255.0, Blue(tint) / 255.0)
;// Rescale sprite _(optional)
glScalef_(scaleX, scaleY, 0.0)
;// Blend the color key into oblivion! _(optional)
glEnable_(#GL_BLEND)
glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA)
;// Move everything on the right
glTranslatef_(1, 0, 0)
;// Render a quad
;// Instead of the using _(s,t) coordinates, With the #GL_NV_texture_rectangle
;// extension, you need To use the actual dimensions of the texture.
;// This makes using 2D sprites For games And emulators much easier now
;// that you won't have to convert :)
glBegin_(#GL_QUADS)
glTexCoord2i_(0, 0) : glVertex2i_(0, 0)
glTexCoord2i_(w, 0) : glVertex2i_(w, 0)
glTexCoord2i_(w, h) : glVertex2i_(w, h)
glTexCoord2i_(0, h) : glVertex2i_(0, h)
glEnd_()
SetGadgetAttribute(screenGL, #PB_OpenGL_FlipBuffers, #True)
EndProcedure
win=OpenWindow(#PB_Any, 0, 0, 800, 512, "OpenGL 2D Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
screenGL=OpenGLGadget(#PB_Any, 0, 0, WindowWidth(win), WindowHeight(win))
screenW=GadgetWidth(screenGL)
screenH=GadgetHeight(screenGL)
SetupGL(screenW, screenH)
;Create Image Texture (caution, size must be a power of 2: 16, 32, 64, 128, 256, 512, 1024, 2048 ...)
w=512 : h=512
image=CreateImage(#PB_Any, w, h, 32, RGB(150, 0, 0)) ; red background
If StartDrawing(ImageOutput(image))
FrontColor(RGB(0, 255, 255)) ; cyan plots
Plot(0, 1)
Plot(1, 0)
Plot(OutputWidth()-1, OutputHeight()-1)
Plot(OutputWidth()-2, OutputHeight()-2)
Plot(OutputWidth()-3, OutputHeight()-3)
StopDrawing()
glSpriteTexture=LoadTextureGL(image)
EndIf
;Init and Start rendering (about 60 fps)
BindEvent(#PB_Event_Timer, @RenderGL())
AddWindowTimer(win, 1, 16)
Repeat: Until WaitWindowEvent()=#PB_Event_CloseWindow