The following example illustrates how to write any character or phrase you want to the screen using texture mapped quads.
It is an adaptation of NeHe Lesson 17: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=17
' SED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "GLU.INC"
#INCLUDE "GDIPLUS.INC"
#INCLUDE "GDIPUTILS.INC"
$WindowCaption = "NeHe Lesson 17"
%GL_WINDOWWIDTH = 640 ' Window width
%GL_WINDOWHEIGHT = 480 ' Window height
%GL_BITSPERPEL = 16 ' Color resolution in bits per pixel
%GL_DEPTHBITS = 16 ' Depth of the depth (z-axis) buffer
GLOBAL hDC AS LONG ' Device context handle
GLOBAL TextureHandles() AS DWORD
GLOBAL FontBase AS DWORD
GLOBAL cnt1 AS SINGLE
GLOBAL cnt2 AS SINGLE
SUB glPrint (BYVAL x AS LONG, BYVAL y AS LONG, BYREF szText AS ASCIIZ, BYVAL nSet AS LONG, BYVAL FontBase AS DWORD, BYREF TextureHandle AS DWORD)
IF nSet > 1 THEN nSet = 1
glBindTexture %GL_TEXTURE_2D, TextureHandle ' Select our font texture
glDisable %GL_DEPTH_TEST ' Disables depth testing
glMatrixMode %GL_PROJECTION ' Select the projection matrix
glPushMatrix ' Store the projection matrix
glLoadIdentity ' Reset the projection matrix
glOrtho 0, 640, 0, 480, -1, 1 ' Set up an ortho screen
glMatrixMode %GL_MODELVIEW ' Select the modelview matrix
glPushMatrix ' Store the modelview matrix
glLoadIdentity ' Reset the modelview matrix
glTranslated x, y, 0 ' Position the text (0,0 - bottom left)
glListBase FontBase - 32 + (128 * nSet) ' Choose the font set (0 or 1)
glCallLists LEN(szText), %GL_UNSIGNED_BYTE, szText ' Write the text to the screen
glMatrixMode %GL_PROJECTION ' Select the projection matrix
glPopMatrix ' Restore the old projection matrix
glMatrixMode %GL_MODELVIEW ' Select the modelview matrix
glPopMatrix ' Restore the old projection matrix
glEnable %GL_DEPTH_TEST ' Enables depth testing
END SUB
' =======================================================================================
' All the setup goes here
' =======================================================================================
SUB SetupScene (BYVAL hwnd AS DWORD, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG)
LOCAL hr AS LONG
LOCAL i AS LONG
LOCAL cx, cy AS SINGLE
DIM TextureHandles(1) AS DWORD
DIM TextureWidth(1) AS LONG
DIM TextureHeight(1) AS LONG
DIM strTextureData(1) AS STRING
' Load textures from disk
hr = GdiPlusLoadTexture("Font.bmp", TextureWidth(0), TextureHeight(0), strTextureData(0), %TRUE)
hr = GdiPlusLoadTexture("Bumps.bmp", TextureWidth(1), TextureHeight(1), strTextureData(1), %TRUE)
' Create two textures
glGenTextures 2, TextureHandles(0)
FOR i = 0 TO 1
glBindTexture %GL_TEXTURE_2D, TextureHandles(i)
glTexParameteri %GL_TEXTURE_2D, %GL_TEXTURE_MAG_FILTER, %GL_LINEAR
glTexParameteri %GL_TEXTURE_2D, %GL_TEXTURE_MIN_FILTER, %GL_LINEAR
glTexImage2D %GL_TEXTURE_2D, 0, 3, TextureWidth(i), TextureHeight(i), 0, _
%GL_RGBA, %GL_UNSIGNED_BYTE, BYVAL STRPTR(strTextureData(i))
NEXT
' Create 256 display lists
FontBase = glGenLists(256)
' Select our font texture
glBindTexture %GL_TEXTURE_2D, TextureHandles(0)
FOR i = 0 TO 255
' x position of current character
cx = (i MOD 16) / 16.0!
' y position of current character
cy = (i \ 16) / 16.0!
' Start building a list
glNewList FontBase + i, %GL_COMPILE
' Use a quad for each character
glBegin %GL_QUADS
' Texture coordinate (bottom left)
glTexCoord2f cx, 1 - cy - 0.0625!
' Vertex coordinate (bottom left)
glVertex2i 0,0
' Texture coordinate (bottom right)
glTexCoord2f cx + 0.0625!, 1 - cy - 0.0625!
' Vertex coordinate (bottom right)
glVertex2i 16, 0
' Texture coordinate (top right)
glTexCoord2f cx + 0.0625!, 1 - cy
' Vertex coordinate (top right)
glVertex2i 16,16
' Texture coordinate (top left)
glTexCoord2f cx, 1 - cy
' Vertex coordinate (top left)
glVertex2i 0, 16
' Done building our quad character
glEnd
' Move to the right of the character
glTranslated 10,0,0
' Done building the display list
glEndList
NEXT
' Specify clear values for the color buffers
glClearColor 0.0!, 0.0!, 0.0!, 0.0!
' Enables clearing of the depth buffer
glClearDepth 1.0!
' Type of depth test to do
glDepthFunc %GL_LEQUAL
' Select the type of blending
glBlendFunc %GL_SRC_ALPHA, %GL_ONE
' Enables smooth color shading
glShadeModel %GL_SMOOTH
' Enable 2D texture mapping
glEnable %GL_TEXTURE_2D
END SUB
' =======================================================================================
' =======================================================================================
' Resize the scene
' =======================================================================================
SUB ResizeScene (BYVAL hwnd AS DWORD, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG)
' Prevent divide by zero making height equal one
IF nHeight = 0 THEN nHeight = 1
' Reset the current viewport
glViewport 0, 0, nWidth, nHeight
' Select the projection matrix
glMatrixMode %GL_PROJECTION
' Reset the projection matrix
glLoadIdentity
' Calculate the aspect ratio of the window
gluPerspective 45.0!, nWidth / nHeight, 0.1!, 100.0!
' Select the model view matrix
glMatrixMode %GL_MODELVIEW
' Reset the model view matrix
glLoadIdentity
END SUB
' =======================================================================================
' =======================================================================================
' Draw the scene
' =======================================================================================
SUB DrawScene (BYVAL hwnd AS DWORD, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG)
' Clear the screen buffer
glClear %GL_COLOR_BUFFER_BIT OR %GL_DEPTH_BUFFER_BIT
' Reset the view
glLoadIdentity
glBindTexture %GL_TEXTURE_2D, TextureHandles(1) ' Select our second texture
glTranslatef 0.0!, 0.0!, -5.0! ' Move into the screen 5 units
glRotatef 45.0!, 0.0!, 0.0!, 1.0! ' Rotate on the Z axis 45 degrees (clockwise)
glRotatef cnt1 * 30.0!, 1.0!, 1.0!, 0.0! ' Rotate on the X & Y axis by cnt1 (left to right)
glDisable %GL_BLEND ' Disable blending before we draw in 3d
glColor3f 1.0!, 1.0!, 1.0! ' Bright white
glBegin %GL_QUADS ' Draw our first texture mapped quad
glTexCoord2d 0.0!, 0.0! ' First texture coordinate
glVertex2f -1.0!, 1.0! ' First vertex
glTexCoord2d 1.0!, 0.0! ' Second texture coordinate
glVertex2f 1.0!, 1.0! ' Second vertex
glTexCoord2d 1.0!, 1.0! ' Third texture coordinate
glVertex2f 1.0!, -1.0! ' Third vertex
glTexCoord2d 0.0!, 1.0! ' Fourth texture coordinate
glVertex2f -1.0!, -1.0! ' Fourth vertex
glEnd ' Done drawing the first quad
glRotatef 90.0!, 1.0!, 1.0!, 0.0! ' Rotate on the x & y axis by 90 degrees (left to right)
glBegin %GL_QUADS ' Draw our second texture mapped quad
glTexCoord2d 0.0!, 0.0! ' First texture coordinate
glVertex2f -1.0!, 1.0! ' First vertex
glTexCoord2d 1.0!, 0.0! ' Second texture coordinate
glVertex2f 1.0!, 1.0! ' Second vertex
glTexCoord2d 1.0!, 1.0! ' Third texture coordinate
glVertex2f 1.0!, -1.0! ' Third vertex
glTexCoord2d 0.0!, 1.0! ' Fourth texture coordinate
glVertex2f -1.0!, -1.0! ' Fourth vertex
glEnd ' Done drawing our second quad
glEnable %GL_BLEND ' Enable blending
' Reset the view
glLoadIdentity
' Pulsing colors based on text position
glColor3f 1.0! * COS(cnt1),1.0! * SIN(cnt2), 1.0! - 0.5! * COS(cnt1 + cnt2)
' Print GL text to the screen
glPrint 280 + 250 * COS(cnt1), 235 + 200 * SIN(cnt2), "NeHe", 0, FontBase, TextureHandles(0)
' Pulsing colors based on text position
glColor3f 1.0! * SIN(cnt2), 1.0! - 0.5! * COS(cnt1 + cnt2), 1.0! * COS(cnt1)
' Print GL text to the screen
glPrint 280 + 230 * COS(cnt2), 235 + 200 * SIN(cnt1), "OpenGL", 1, FontBase, TextureHandles(0)
' Set color to blue
glColor3f 0.0!, 0.0!, 1.0!
' Print GL text to the screen
glPrint 240 + 200 * COS((cnt2 + cnt1) / 5), 2, "Giuseppe D'Agata",0, FontBase, TextureHandles(0)
' Set color to white
glColor3f 1.0!, 1.0!, 1.0!
' Print GL text to the screen
glPrint 242 + 200 * COS((cnt2 + cnt1) / 5), 2, "Giuseppe D'Agata",0, FontBase, TextureHandles(0)
cnt1 = cnt1 + 0.01! ' Increase the first counter
cnt2 = cnt2 + 0.0081! ' Increase the second counter
END SUB
' =======================================================================================
' =======================================================================================
' Cleanup
' =======================================================================================
SUB Cleanup (BYVAL hwnd AS DWORD)
' Deletes the lists
glDeleteLists FontBase, 256
' Delete the textures
glDeleteTextures(2, TextureHandles(0))
END SUB
' =======================================================================================
' =======================================================================================
' Processes keystrokes
' Parameters:
' * hwnd = Window hande
' * vKeyCode = Virtual key code
' * bKeyDown = %TRUE if key is pressed; %FALSE if it is released
' =======================================================================================
SUB ProcessKeystrokes (BYVAL hwnd AS DWORD, BYVAL vKeyCode AS LONG, BYVAL bKeyDown AS LONG)
SELECT CASE AS LONG vKeyCode
CASE %VK_ESCAPE
' Quit if Esc key pressed
SendMessage hwnd, %WM_CLOSE, 0, 0
END SELECT
END SUB
' =======================================================================================
' =======================================================================================
' Main
' =======================================================================================
FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG
LOCAL hwnd AS DWORD
LOCAL wcex AS WNDCLASSEX
LOCAL szClassName AS ASCIIZ * 256
LOCAL szCaption AS ASCIIZ * 256
LOCAL msg AS tagMSG
LOCAL rc AS RECT
LOCAL bDone AS LONG
LOCAL nLeft AS LONG
LOCAL nTop AS LONG
LOCAL nWidth AS LONG
LOCAL nHeight AS LONG
LOCAL dwStyle AS DWORD
LOCAL dwStyleEx AS DWORD
STATIC vKeyCode AS LONG
STATIC bKeyDown AS LONG
LOCAL t AS DOUBLE
LOCAL t0 AS DOUBLE
LOCAL fps AS DOUBLE
LOCAL nFrames AS LONG
LOCAL dm AS DEVMODE
LOCAL bFullScreen AS LONG
LOCAL lResult AS LONG
' Register the window class
szClassName = "PBOPENGL"
wcex.cbSize = SIZEOF(wcex)
wcex.style = %CS_HREDRAW OR %CS_VREDRAW OR %CS_OWNDC
wcex.lpfnWndProc = CODEPTR(WndProc)
wcex.cbClsExtra = 0
wcex.cbWndExtra = 0
wcex.hInstance = hInstance
wcex.hCursor = LoadCursor (%NULL, BYVAL %IDC_ARROW)
wcex.hbrBackground = %NULL
wcex.lpszMenuName = %NULL
wcex.lpszClassName = VARPTR(szClassName)
wcex.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Sample, if resource icon: LoadIcon(hInst, "APPICON")
wcex.hIconSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Remember to set small icon too..
RegisterClassEx wcex
' Ask the user which screen mode he prefers
lResult = MessageBox(%NULL, "Would you like to run in fullscreen mode?", _
"Start fullScreen?", %MB_YESNOCANCEL OR %MB_ICONQUESTION)
SELECT CASE lResult
CASE %IDCANCEL : EXIT FUNCTION
CASE %IDYES : bFullScreen = %TRUE
CASE %IDNO : bFullScreen = %FALSE
END SELECT
' Window size
nWidth = %GL_WINDOWWIDTH
nHeight = %GL_WINDOWHEIGHT
IF bFullScreen THEN
' Change display settings
dm.dmSize = SIZEOF(dm)
dm.dmPelsWidth = nWidth
dm.dmPelsHeight = nHeight
dm.dmBitsPerPel = %GL_BITSPERPEL
dm.dmFields = %DM_BITSPERPEL OR %DM_PELSWIDTH OR %DM_PELSHEIGHT
IF ChangeDisplaySettings(dm, %CDS_FULLSCREEN) = 0 THEN ShowCursor %FALSE
END IF
' Window caption
szCaption = $WindowCaption
' Window styles
IF ISFALSE bFullScreen THEN
dwStyle = %WS_OVERLAPPEDWINDOW
dwStyleEx = %WS_EX_APPWINDOW OR %WS_EX_WINDOWEDGE
ELSE
dwStyle = %WS_POPUP
dwStyleEx = %WS_EX_APPWINDOW
END IF
' Create the window
hwnd = CreateWindowEx( _
dwStyleEx, _ ' extended styles
szClassName, _ ' window class name
szCaption, _ ' window caption
dwStyle, _ ' window style
nLeft, _ ' initial x position
nTop, _ ' initial y position
nWidth, _ ' initial x size
nHeight, _ ' initial y size
%NULL, _ ' parent window handle
0, _ ' window menu handle
hInstance, _ ' program instance handle
BYVAL %NULL) ' creation parameters
' Retrieve the coordinates of the window's client area
GetClientRect hwnd, rc
' Initialize the new OpenGl window
SetupScene hwnd, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop
' Show the window
ShowWindow hwnd, nCmdShow
UpdateWindow hwnd
DO UNTIL bDone
' Windows message pump
DO WHILE PeekMessage(msg, %NULL, 0, 0, %PM_REMOVE)
IF msg.message = %WM_QUIT THEN
bDone = %TRUE
ELSE
IF msg.message = %WM_KEYDOWN THEN
vKeyCode = msg.wParam
bKeyDown = %TRUE
ELSEIF msg.message = %WM_KEYUP THEN
vKeyCode = msg.wParam
bKeyDown = %FALSE
END IF
TranslateMessage msg
DispatchMessage msg
END IF
LOOP
IF ISFALSE bFullScreen THEN
' Get time and mouse position
t = INT(TIMER)
' Calculate and display FPS (frames per second)
IF t > t0 OR nFrames = 0 THEN
fps = nFrames \ (t - t0)
wsprintf szCaption, $WindowCaption & " (%i FPS)", BYVAL fps
SetWindowText hwnd, szCaption
t0 = t
nFrames = 0
END IF
nFrames = nFrames + 1
END IF
' Draw the scene
DrawScene hwnd, nWidth, nHeight
' Exchange the front and back buffers
SwapBuffers hDC
' Process the keystrokes
IF vKeyCode THEN
ProcessKeystrokes hwnd, vKeyCode, bKeyDown
vKeyCode = 0
END IF
LOOP
' Retore defaults
IF bFullScreen THEN
ChangeDisplaySettings BYVAL %NULL, 0
ShowCursor %TRUE
END IF
FUNCTION = msg.wParam
END FUNCTION
' =======================================================================================
' =======================================================================================
' Main window procedure
' =======================================================================================
FUNCTION WndProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
LOCAL pf AS LONG
LOCAL pfd AS PIXELFORMATDESCRIPTOR
STATIC hRC AS LONG
SELECT CASE wMsg
CASE %WM_SYSCOMMAND
' Disable the Windows screensaver
IF (wParam AND &HFFF0) = %SC_SCREENSAVE THEN EXIT FUNCTION
' Close the window
IF (wParam AND &HFFF0) = %SC_CLOSE THEN
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
CASE %WM_CREATE
' Retrieve the device context handle
hDC = GetDC(hwnd)
' Fill the PIXELFORMATDESCRIPTOR structure
pfd.nSize = SIZEOF(PIXELFORMATDESCRIPTOR) ' Size of the structure
pfd.nVersion = 1 ' Version number
pfd.dwFlags = %PFD_DRAW_TO_WINDOW _ ' Format must support window
OR %PFD_SUPPORT_OPENGL _ ' Format must support OpenGL
OR %PFD_DOUBLEBUFFER ' Format must support double buffering
pfd.iPixelType = %PFD_TYPE_RGBA ' Request an RGBA format
pfd.cColorBits = %GL_BITSPERPEL ' Number of color bitplanes in each color buffer
pfd.cRedBits = 0 ' Number of red bitplanes in each RGBA color buffer.
pfd.cRedShift = 0 ' Shift count for red bitplanes in each RGBA color buffer.
pfd.cGreenBits = 0 ' Number of green bitplanes in each RGBA color buffer.
pfd.cGreenShift = 0 ' Shift count for green bitplanes in each RGBA color buffer.
pfd.cBlueBits = 0 ' Number of blue bitplanes in each RGBA color buffer.
pfd.cBlueShift = 0 ' Shift count for blue bitplanes in each RGBA color buffer.
pfd.cAlphaBits = 0 ' Number of alpha bitplanes in each RGBA color buffer
pfd.cAlphaShift = 0 ' Shift count for alpha bitplanes in each RGBA color buffer.
pfd.cAccumBits = 0 ' Total number of bitplanes in the accumulation buffer.
pfd.cAccumRedBits = 0 ' Number of red bitplanes in the accumulation buffer.
pfd.cAccumGreenBits = 0 ' Number of gree bitplanes in the accumulation buffer.
pfd.cAccumBlueBits = 0 ' Number of blue bitplanes in the accumulation buffer.
pfd.cAccumAlphaBits = 0 ' Number of alpha bitplanes in the accumulation buffer.
pfd.cDepthBits = %GL_DEPTHBITS ' Depth of the depth (z-axis) buffer.
pfd.cStencilBits = 0 ' Depth of the stencil buffer.
pfd.cAuxBuffers = 0 ' Number of auxiliary buffers.
pfd.iLayerType = %PFD_MAIN_PLANE ' Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
pfd.bReserved = 0 ' Number of overlay and underlay planes.
pfd.dwLayerMask = 0 ' Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
pfd.dwVisibleMask = 0 ' Transparent color or index of an underlay plane.
pfd.dwDamageMask = 0 ' Ignored. Earlier implementations of OpenGL used this member, but it is no longer used.
' Find a matching pixel format
pf = ChoosePixelFormat(hDC, pfd)
IF ISFALSE pf THEN
MessageBox hwnd, "Can't find a suitable pixel format", _
"Error", %MB_OK OR %MB_ICONEXCLAMATION
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
' Set the pixel format
IF ISFALSE SetPixelFormat(hDC, pf, pfd) THEN
MessageBox hwnd, "Can't set the pixel format", _
"Error", %MB_OK OR %MB_ICONEXCLAMATION
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
' Create a new OpenGL rendering context
hRC = wglCreateContext(hDC)
IF ISFALSE hRC THEN
MessageBox hwnd, "Can't create an OpenGL rendering context", _
"Error", %MB_OK OR %MB_ICONEXCLAMATION
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
' Make it current
IF ISFALSE wglMakeCurrent(hDC,hRC) THEN
MessageBox hwnd, "Can't activate the OpenGL rendering context", _
"Error", %MB_OK OR %MB_ICONEXCLAMATION
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
EXIT FUNCTION
CASE %WM_DESTROY
' Clear resources
Cleanup hwnd
' Release the device and rendering contexts
wglMakeCurrent hDC, 0
' Make the rendering context no longer current
wglDeleteContext hRC
' Release the device context
ReleaseDC hwnd, hDC
' Post an WM_QUIT message
PostQuitMessage 0
EXIT FUNCTION
CASE %WM_SIZE
ResizeScene hwnd, LO(WORD, lParam), HI(WORD, lParam)
EXIT FUNCTION
END SELECT
' Call the default window procedure to process unhandled messages
FUNCTION = DefWindowProc(hwnd, wMsg, wParam, lParam)
END FUNCTION
' =======================================================================================
(http://www.jose.it-berater.org/captures/EX_NeHe_Lesson_17.png)
The following example illustrates how to write any character or phrase you want to the screen using texture mapped quads.
It is an adaptation of NeHe Lesson 17: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=17
' SED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "SDL.INC"
#INCLUDE "GLU.INC"
#INCLUDE "GDIPUTILS.INC"
$WindowCaption = "NeHe Lesson 17"
GLOBAL TextureHandles() AS DWORD
GLOBAL FontBase AS DWORD
GLOBAL cnt1 AS SINGLE
GLOBAL cnt2 AS SINGLE
SUB glPrint (BYVAL x AS LONG, BYVAL y AS LONG, BYREF szText AS ASCIIZ, BYVAL nSet AS LONG, BYVAL FontBase AS DWORD, BYREF TextureHandle AS DWORD)
IF nSet > 1 THEN nSet = 1
glBindTexture %GL_TEXTURE_2D, TextureHandle ' Select our font texture
glDisable %GL_DEPTH_TEST ' Disables depth testing
glMatrixMode %GL_PROJECTION ' Select the projection matrix
glPushMatrix ' Store the projection matrix
glLoadIdentity ' Reset the projection matrix
glOrtho 0, 640, 0, 480, -1, 1 ' Set up an ortho screen
glMatrixMode %GL_MODELVIEW ' Select the modelview matrix
glPushMatrix ' Store the modelview matrix
glLoadIdentity ' Reset the modelview matrix
glTranslated x, y, 0 ' Position the text (0,0 - bottom left)
glListBase FontBase - 32 + (128 * nSet) ' Choose the font set (0 or 1)
glCallLists LEN(szText), %GL_UNSIGNED_BYTE, szText ' Write the text to the screen
glMatrixMode %GL_PROJECTION ' Select the projection matrix
glPopMatrix ' Restore the old projection matrix
glMatrixMode %GL_MODELVIEW ' Select the modelview matrix
glPopMatrix ' Restore the old projection matrix
glEnable %GL_DEPTH_TEST ' Enables depth testing
END SUB
' =======================================================================================
' All the setup goes here
' =======================================================================================
SUB SetupScene ()
LOCAL hr AS LONG
LOCAL i AS LONG
LOCAL cx, cy AS SINGLE
DIM TextureHandles(1) AS DWORD
DIM TextureWidth(1) AS LONG
DIM TextureHeight(1) AS LONG
DIM strTextureData(1) AS STRING
' Load textures from disk
hr = GdiPlusLoadTexture("Font.bmp", TextureWidth(0), TextureHeight(0), strTextureData(0), %TRUE)
hr = GdiPlusLoadTexture("Bumps.bmp", TextureWidth(1), TextureHeight(1), strTextureData(1), %TRUE)
' Create two textures
glGenTextures 2, TextureHandles(0)
FOR i = 0 TO 1
glBindTexture %GL_TEXTURE_2D, TextureHandles(i)
glTexParameteri %GL_TEXTURE_2D, %GL_TEXTURE_MAG_FILTER, %GL_LINEAR
glTexParameteri %GL_TEXTURE_2D, %GL_TEXTURE_MIN_FILTER, %GL_LINEAR
glTexImage2D %GL_TEXTURE_2D, 0, 3, TextureWidth(i), TextureHeight(i), 0, _
%GL_RGBA, %GL_UNSIGNED_BYTE, BYVAL STRPTR(strTextureData(i))
NEXT
' Create 256 display lists
FontBase = glGenLists(256)
' Select our font texture
glBindTexture %GL_TEXTURE_2D, TextureHandles(0)
FOR i = 0 TO 255
' x position of current character
cx = (i MOD 16) / 16.0!
' y position of current character
cy = (i \ 16) / 16.0!
' Start building a list
glNewList FontBase + i, %GL_COMPILE
' Use a quad for each character
glBegin %GL_QUADS
' Texture coordinate (bottom left)
glTexCoord2f cx, 1 - cy - 0.0625!
' Vertex coordinate (bottom left)
glVertex2i 0,0
' Texture coordinate (bottom right)
glTexCoord2f cx + 0.0625!, 1 - cy - 0.0625!
' Vertex coordinate (bottom right)
glVertex2i 16, 0
' Texture coordinate (top right)
glTexCoord2f cx + 0.0625!, 1 - cy
' Vertex coordinate (top right)
glVertex2i 16,16
' Texture coordinate (top left)
glTexCoord2f cx, 1 - cy
' Vertex coordinate (top left)
glVertex2i 0, 16
' Done building our quad character
glEnd
' Move to the right of the character
glTranslated 10,0,0
' Done building the display list
glEndList
NEXT
' Specify clear values for the color buffers
glClearColor 0.0!, 0.0!, 0.0!, 0.0!
' Enables clearing of the depth buffer
glClearDepth 1.0!
' Type of depth test to do
glDepthFunc %GL_LEQUAL
' Select the type of blending
glBlendFunc %GL_SRC_ALPHA, %GL_ONE
' Enables smooth color shading
glShadeModel %GL_SMOOTH
' Enable 2D texture mapping
glEnable %GL_TEXTURE_2D
END SUB
' =======================================================================================
' =======================================================================================
' Draw the scene
' =======================================================================================
SUB DrawScene (BYVAL nWidth AS LONG, BYVAL nHeight AS LONG)
LOCAL x_m, y_m, z_m, u_m, v_m AS SINGLE
LOCAL loop_m AS LONG
LOCAL xtrans, ztrans, ytrans AS SINGLE
LOCAL sceneroty AS SINGLE
' Clear the screen buffer
glClear %GL_COLOR_BUFFER_BIT OR %GL_DEPTH_BUFFER_BIT
' Select and setup the projection matrix
glMatrixMode %GL_PROJECTION
glLoadIdentity
' Prevent divide by zero making height equal one
IF nHeight = 0 THEN nHeight = 1
' Calculate the aspect ratio of the window
gluPerspective 45.0!, nWidth/nHeight, 1.0!, 100.0!
' Select and setup the modelview matrix
glMatrixMode %GL_MODELVIEW
glLoadIdentity
glBindTexture %GL_TEXTURE_2D, TextureHandles(1) ' Select our second texture
glTranslatef 0.0!, 0.0!, -5.0! ' Move into the screen 5 units
glRotatef 45.0!, 0.0!, 0.0!, 1.0! ' Rotate on the Z axis 45 degrees (clockwise)
glRotatef cnt1 * 30.0!, 1.0!, 1.0!, 0.0! ' Rotate on the X & Y axis by cnt1 (left to right)
glDisable %GL_BLEND ' Disable blending before we draw in 3d
glColor3f 1.0!, 1.0!, 1.0! ' Bright white
glBegin %GL_QUADS ' Draw our first texture mapped quad
glTexCoord2d 0.0!, 0.0! ' First texture coordinate
glVertex2f -1.0!, 1.0! ' First vertex
glTexCoord2d 1.0!, 0.0! ' Second texture coordinate
glVertex2f 1.0!, 1.0! ' Second vertex
glTexCoord2d 1.0!, 1.0! ' Third texture coordinate
glVertex2f 1.0!, -1.0! ' Third vertex
glTexCoord2d 0.0!, 1.0! ' Fourth texture coordinate
glVertex2f -1.0!, -1.0! ' Fourth vertex
glEnd ' Done drawing the first quad
glRotatef 90.0!, 1.0!, 1.0!, 0.0! ' Rotate on the x & y axis by 90 degrees (left to right)
glBegin %GL_QUADS ' Draw our second texture mapped quad
glTexCoord2d 0.0!, 0.0! ' First texture coordinate
glVertex2f -1.0!, 1.0! ' First vertex
glTexCoord2d 1.0!, 0.0! ' Second texture coordinate
glVertex2f 1.0!, 1.0! ' Second vertex
glTexCoord2d 1.0!, 1.0! ' Third texture coordinate
glVertex2f 1.0!, -1.0! ' Third vertex
glTexCoord2d 0.0!, 1.0! ' Fourth texture coordinate
glVertex2f -1.0!, -1.0! ' Fourth vertex
glEnd ' Done drawing our second quad
glEnable %GL_BLEND ' Enable blending
' Reset the view
glLoadIdentity
' Pulsing colors based on text position
glColor3f 1.0! * COS(cnt1),1.0! * SIN(cnt2), 1.0! - 0.5! * COS(cnt1 + cnt2)
' Print GL text to the screen
glPrint 280 + 250 * COS(cnt1), 235 + 200 * SIN(cnt2), "NeHe", 0, FontBase, TextureHandles(0)
' Pulsing colors based on text position
glColor3f 1.0! * SIN(cnt2), 1.0! - 0.5! * COS(cnt1 + cnt2), 1.0! * COS(cnt1)
' Print GL text to the screen
glPrint 280 + 230 * COS(cnt2), 235 + 200 * SIN(cnt1), "OpenGL", 1, FontBase, TextureHandles(0)
' Set color to blue
glColor3f 0.0!, 0.0!, 1.0!
' Print GL text to the screen
glPrint 240 + 200 * COS((cnt2 + cnt1) / 5), 2, "Giuseppe D'Agata",0, FontBase, TextureHandles(0)
' Set color to white
glColor3f 1.0!, 1.0!, 1.0!
' Print GL text to the screen
glPrint 242 + 200 * COS((cnt2 + cnt1) / 5), 2, "Giuseppe D'Agata",0, FontBase, TextureHandles(0)
cnt1 = cnt1 + 0.01! ' Increase the first counter
cnt2 = cnt2 + 0.0081! ' Increase the second counter
' // Swap buffers
SDL_GL_SwapBuffers
END SUB
' =======================================================================================
' =======================================================================================
' Main
' =======================================================================================
FUNCTION PBMAIN () AS LONG
LOCAL pscreen AS SDL_Surface PTR
LOCAL nWidth, nHeight, bpp AS LONG
LOCAL lResult, bFullScreen AS LONG
LOCAL szCaption AS ASCIIZ * 256
LOCAL dwFlags AS DWORD
LOCAL t, t0, fps AS DOUBLE
LOCAL nFrames AS LONG
szCaption = $WindowCaption ' Window caption
' Ask the user which screen mode he prefers
lResult = MessageBox(%NULL, "Would you like to run in fullscreen mode?", _
"Start fullScreen?", %MB_YESNOCANCEL OR %MB_ICONQUESTION)
SELECT CASE lResult
CASE %IDCANCEL : EXIT FUNCTION
CASE %IDYES : bFullScreen = %TRUE
CASE %IDNO : bFullScreen = %FALSE
END SELECT
' // Initialize SDL's subsystems - in this case, only video.
IF SDL_Init(%SDL_INIT_VIDEO) < 0 THEN
MSGBOX "Unable to init SDL: " & SDL_GetError()
EXIT FUNCTION
END IF
' // Attempt to create a 640x480 window
nWidth = 640 : nHeight = 480 : bpp = 16
IF bFullScreen THEN
dwFlags = %SDL_OPENGL OR %SDL_FULLSCREEN
ELSE
dwFlags = %SDL_OPENGL
END IF
pscreen = SDL_SetVideoMode(nWidth, nHeight, bpp, dwFlags)
SDL_WM_SetCaption szCaption, ""
' // If we fail, return error.
IF pscreen = %NULL THEN
SDL_Quit
MSGBOX "Unable to set the video mode: " & SDL_GetError()
EXIT FUNCTION
END IF
' // Set up the scene
SetupScene
' // Main loop
LOCAL done AS LONG
LOCAL uevent AS SDL_Event
WHILE done = %FALSE
' // Poll for events, and handle the ones we care about.
WHILE SDL_PollEvent(VARPTR(uevent))
SELECT CASE uevent.type
CASE %SDL_KEYUP
' // Quit if escape is pressed
IF uevent.key.keysym.sym = %SDLK_ESCAPE THEN
done = %TRUE
EXIT LOOP
END IF
CASE %SDL_QUIT
done = %TRUE
EXIT LOOP
END SELECT
WEND
IF ISFALSE bFullScreen THEN
' Get time and mouse position
t = INT(TIMER)
' Calculate and display FPS (frames per second)
IF t > t0 OR nFrames = 0 THEN
fps = nFrames \ (t - t0)
wsprintf szCaption, $WindowCaption & " (%i FPS)", BYVAL fps
SDL_WM_SetCaption szCaption, szCaption
t0 = t
nFrames = 0
END IF
nFrames = nFrames + 1
END IF
' // Draw the scene
DrawScene nWidth, nHeight
WEND
' Deletes the lists
glDeleteLists FontBase, 256
' Delete the textures
glDeleteTextures(2, TextureHandles(0))
' Shut down SDL
SDL_Quit
END FUNCTION
' =======================================================================================
The following example illustrates how to write any character or phrase you want to the screen using texture mapped quads.
It is an adaptation of NeHe Lesson 17: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=17
' SED_PBWIN - Use the PBWIN compiler
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "GLFW.INC"
#INCLUDE ONCE "GDIPUTILS.INC"
SUB glPrint (BYVAL x AS LONG, BYVAL y AS LONG, BYREF szText AS ASCIIZ, BYVAL nSet AS LONG, BYVAL FontBase AS DWORD, BYREF TextureHandle AS DWORD)
IF nSet > 1 THEN nSet = 1
glBindTexture %GL_TEXTURE_2D, TextureHandle ' Select our font texture
glDisable %GL_DEPTH_TEST ' Disables depth testing
glMatrixMode %GL_PROJECTION ' Select the projection matrix
glPushMatrix ' Store the projection matrix
glLoadIdentity ' Reset the projection matrix
glOrtho 0, 640, 0, 480, -1, 1 ' Set up an ortho screen
glMatrixMode %GL_MODELVIEW ' Select the modelview matrix
glPushMatrix ' Store the modelview matrix
glLoadIdentity ' Reset the modelview matrix
glTranslated x, y, 0 ' Position the text (0,0 - bottom left)
glListBase FontBase - 32 + (128 * nSet) ' Choose the font set (0 or 1)
glCallLists LEN(szText), %GL_UNSIGNED_BYTE, szText ' Write the text to the screen
glMatrixMode %GL_PROJECTION ' Select the projection matrix
glPopMatrix ' Restore the old projection matrix
glMatrixMode %GL_MODELVIEW ' Select the modelview matrix
glPopMatrix ' Restore the old projection matrix
glEnable %GL_DEPTH_TEST ' Enables depth testing
END SUB
FUNCTION PBMAIN () AS LONG
LOCAL nWidth, nHeight, running, frames, x, y AS LONG
LOCAL t, t0, fps AS DOUBLE
LOCAL szTitlestr AS ASCIIZ * 200
LOCAL hr, i AS LONG
LOCAL cx, cy, cnt1, cnt2 AS SINGLE
LOCAL FontBase AS DWORD
DIM TextureHandles(1) AS DWORD
DIM TextureWidth(1) AS LONG
DIM TextureHeight(1) AS LONG
DIM strTextureData(1) AS STRING
' Initialize GLFW
glfwInit
' Open OpenGL window
IF ISFALSE glfwOpenWindow(640, 480, 0, 0, 0, 0, 16, 0, %GLFW_WINDOW) THEN
glfwTerminate
EXIT FUNCTION
END IF
' Load textures from disk
hr = GdiPlusLoadTexture("Font.bmp", TextureWidth(0), TextureHeight(0), strTextureData(0), %TRUE)
hr = GdiPlusLoadTexture("Bumps.bmp", TextureWidth(1), TextureHeight(1), strTextureData(1), %TRUE)
' Create two textures
glGenTextures 2, TextureHandles(0)
FOR i = 0 TO 1
glBindTexture %GL_TEXTURE_2D, TextureHandles(i)
glTexParameteri %GL_TEXTURE_2D, %GL_TEXTURE_MAG_FILTER, %GL_LINEAR
glTexParameteri %GL_TEXTURE_2D, %GL_TEXTURE_MIN_FILTER, %GL_LINEAR
glTexImage2D %GL_TEXTURE_2D, 0, 3, TextureWidth(i), TextureHeight(i), 0, _
%GL_RGBA, %GL_UNSIGNED_BYTE, BYVAL STRPTR(strTextureData(i))
NEXT
' Create 256 display lists
FontBase = glGenLists(256)
' Select our font texture
glBindTexture %GL_TEXTURE_2D, TextureHandles(0)
FOR i = 0 TO 255
' x position of current character
cx = (i MOD 16) / 16.0!
' y position of current character
cy = (i \ 16) / 16.0!
' Start building a list
glNewList FontBase + i, %GL_COMPILE
' Use a quad for each character
glBegin %GL_QUADS
' Texture coordinate (bottom left)
glTexCoord2f cx, 1 - cy - 0.0625!
' Vertex coordinate (bottom left)
glVertex2i 0,0
' Texture coordinate (bottom right)
glTexCoord2f cx + 0.0625!, 1 - cy - 0.0625!
' Vertex coordinate (bottom right)
glVertex2i 16, 0
' Texture coordinate (top right)
glTexCoord2f cx + 0.0625!, 1 - cy
' Vertex coordinate (top right)
glVertex2i 16,16
' Texture coordinate (top left)
glTexCoord2f cx, 1 - cy
' Vertex coordinate (top left)
glVertex2i 0, 16
' Done building our quad character
glEnd
' Move to the right of the character
glTranslated 10,0,0
' Done building the display list
glEndList
NEXT
' Specify clear values for the color buffers
glClearColor 0.0!, 0.0!, 0.0!, 0.0!
' Enables clearing of the depth buffer
glClearDepth 1.0!
' Type of depth test to do
glDepthFunc %GL_LEQUAL
' Select the type of blending
glBlendFunc %GL_SRC_ALPHA, %GL_ONE
' Enables smooth color shading
glShadeModel %GL_SMOOTH
' Enable 2D texture mapping
glEnable %GL_TEXTURE_2D
' Main loop
running = %TRUE
frames = 0
t0 = glfwGetTime
DO WHILE running
' Get time and mouse position
t = glfwGetTime
glfwGetMousePos x, y
' Calculate and display FPS (frames per second)
IF t - t0 > 1.0! OR frames = 0 THEN
fps = frames / (t-t0)
wsprintf szTitlestr, "NEHE Lesson 17 (%i FPS)", BYVAL fps
glfwSetWindowTitle szTitlestr
t0 = t
frames = 0
END IF
frames = frames + 1
' Get window size (may be different than the requested size)
glfwGetWindowSize nWidth, nHeight
IF nHeight <= 0 THEN nHeight = 1
' Set viewport
glViewport 0, 0, nWidth, nHeight
' Clear the screen and depth buffers
glClear %GL_COLOR_BUFFER_BIT OR %GL_DEPTH_BUFFER_BIT
' Select and setup the projection matrix
glMatrixMode %GL_PROJECTION
glLoadIdentity
' Calculate the aspect ratio of the window
gluPerspective 45.0!, nWidth/nHeight, 1.0!, 100.0!
' Select and setup the modelview matrix
glMatrixMode %GL_MODELVIEW
glLoadIdentity
glBindTexture %GL_TEXTURE_2D, TextureHandles(1) ' Select our second texture
glTranslatef 0.0!, 0.0!, -5.0! ' Move into the screen 5 units
glRotatef 45.0!, 0.0!, 0.0!, 1.0! ' Rotate on the Z axis 45 degrees (clockwise)
glRotatef cnt1 * 30.0!, 1.0!, 1.0!, 0.0! ' Rotate on the X & Y axis by cnt1 (left to right)
glDisable %GL_BLEND ' Disable blending before we draw in 3d
glColor3f 1.0!, 1.0!, 1.0! ' Bright white
glBegin %GL_QUADS ' Draw our first texture mapped quad
glTexCoord2d 0.0!, 0.0! ' First texture coordinate
glVertex2f -1.0!, 1.0! ' First vertex
glTexCoord2d 1.0!, 0.0! ' Second texture coordinate
glVertex2f 1.0!, 1.0! ' Second vertex
glTexCoord2d 1.0!, 1.0! ' Third texture coordinate
glVertex2f 1.0!, -1.0! ' Third vertex
glTexCoord2d 0.0!, 1.0! ' Fourth texture coordinate
glVertex2f -1.0!, -1.0! ' Fourth vertex
glEnd ' Done drawing the first quad
glRotatef 90.0!, 1.0!, 1.0!, 0.0! ' Rotate on the x & y axis by 90 degrees (left to right)
glBegin %GL_QUADS ' Draw our second texture mapped quad
glTexCoord2d 0.0!, 0.0! ' First texture coordinate
glVertex2f -1.0!, 1.0! ' First vertex
glTexCoord2d 1.0!, 0.0! ' Second texture coordinate
glVertex2f 1.0!, 1.0! ' Second vertex
glTexCoord2d 1.0!, 1.0! ' Third texture coordinate
glVertex2f 1.0!, -1.0! ' Third vertex
glTexCoord2d 0.0!, 1.0! ' Fourth texture coordinate
glVertex2f -1.0!, -1.0! ' Fourth vertex
glEnd ' Done drawing our second quad
glEnable %GL_BLEND ' Enable blending
' Reset the view
glLoadIdentity
' Pulsing colors based on text position
glColor3f 1.0! * COS(cnt1),1.0! * SIN(cnt2), 1.0! - 0.5! * COS(cnt1 + cnt2)
' Print GL text to the screen
glPrint 280 + 250 * COS(cnt1), 235 + 200 * SIN(cnt2), "NeHe", 0, FontBase, TextureHandles(0)
' Pulsing colors based on text position
glColor3f 1.0! * SIN(cnt2), 1.0! - 0.5! * COS(cnt1 + cnt2), 1.0! * COS(cnt1)
' Print GL text to the screen
glPrint 280 + 230 * COS(cnt2), 235 + 200 * SIN(cnt1), "OpenGL", 1, FontBase, TextureHandles(0)
' Set color to blue
glColor3f 0.0!, 0.0!, 1.0!
' Print GL text to the screen
glPrint 240 + 200 * COS((cnt2 + cnt1) / 5), 2, "Giuseppe D'Agata",0, FontBase, TextureHandles(0)
' Set color to white
glColor3f 1.0!, 1.0!, 1.0!
' Print GL text to the screen
glPrint 242 + 200 * COS((cnt2 + cnt1) / 5), 2, "Giuseppe D'Agata",0, FontBase, TextureHandles(0)
cnt1 = cnt1 + 0.01! ' Increase the first counter
cnt2 = cnt2 + 0.0081! ' Increase the second counter
' Swap buffers
glfwSwapBuffers
' Check if the ESC key was pressed or the window was closed
running = NOT glfwGetKey(%GLFW_KEY_ESC) AND glfwGetWindowParam(%GLFW_OPENED)
LOOP
' Deletes the lists
glDeleteLists FontBase, 256
' Delete the textures
glDeleteTextures(2, TextureHandles(0))
' Close OpenGL window and terminate GLFW
glfwTerminate
END FUNCTION