Date: 02-16-2022
Return to Index
created by gbSnippets
'One of the more useful/popular features of OpenGL is the ability to
'map an image onto a surface - texture mapping. This snippets shows
'how it is done.
'Compiler Comments:
'This code was written to compilete in PBWin10. To compile with PBWin9, split pt
'into pt.x and pt.y as arguments wherever the ChildWindowFromPoint() API is used (1 place).
'Primary Code:
'There are 3 basic steps involved:
'1. Create a texture (load from a bitmap file, resource, or create from scratch)
'2. Initialize texture mapping
'3. Attach image to polygons
'Creating a texture in memory can be done in several ways. OpenGL requires
'a pointer to RGB color bytes for each pixel, so an array or string can
'be used. Here's the code to use an array of Longs to create the bytes
'needed by OpenGL.
Sub CreateTexture
Local i,j As Long, sFileName As String
sFileName = "cowgirl.bmp"
GetBitMapDimensions(sFileName, imgW, imgH)
Graphic Bitmap Load sFileName, imgW, imgH To hBMP
Graphic Attach hBMP, 0
Dim BMPData(imgW-1,imgH-1)
For i = 0 to imgW-1
For j = 0 to imgH-1
Graphic Get Pixel (i,j) To BMPData(i,imgH-1-j)
Next j
Next i
End Sub
'Starting with the OpenGL template that I've released, add this function to
'initialize texture mapping. Call it from the InitializeScene procedure.
Sub InitializeMapping
glEnable %gl_texture_2D
glTexEnvf %gl_texture_env, %gl_texture_env_mode, %gl_modulate
glBindTexture %gl_texture_2D, 1
glTexParameteri %gl_texture_2d, %gl_texture_wrap_s, %gl_repeat
glTexParameteri %gl_texture_2d, %gl_texture_wrap_t, %gl_repeat
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, %gl_rgb, 100, 100, 0, %gl_rgba, %gl_unsigned_byte, ByVal StrPTR(BMP$)
End Sub
'Finally, the corners of the image must be mapped to the corners of the
'face of each cube. Here's a partial code listing showing how it's done.
'Each vertex of a face is mapped to a corner of the image.
glBegin %gl_quads
' Front Face
glTexCoord2f 0.0, 0.0: glVertex3f -1.0, -1.0, 1.0 ' Bottom Left Of The Texture And Quad
glTexCoord2f 1.0, 0.0: glVertex3f 1.0, -1.0, 1.0 ' Bottom Right Of The Texture And Quad
glTexCoord2f 1.0, 1.0: glVertex3f 1.0, 1.0, 1.0 ' Top Right Of The Texture And Quad
glTexCoord2f 0.0, 1.0: glVertex3f -1.0, 1.0, 1.0 ' Top Left Of The Texture And Quad
glEnd
'Compilable Example: (Jose Includes)
#Compiler PBWin 10
#Compile EXE
#Dim All
%Unicode=1
#Include "win32api.inc"
#Include "gl.inc"
#Include "glu.inc"
%ID_Timer = 1000 : %ID_Label = 1002 : %ID_Graphic = 1003
Global hDlg, hDC, hRC, hLabel, hBMP As DWord
Global scalefactor As Single
Global BMPData(), imgW, imgH As Long
Function PBMain() As Long
CreateTexture
Dialog New Pixels, 0, "OpenGL Example",,, 400, 200,%WS_OverlappedWindow To hDlg
Control Add Graphic, hDlg, %ID_Graphic, "", 10,10,imgW,imgH
Graphic Attach hDlg, %ID_Graphic
Graphic Copy hBMP, 0
Control Add Label, hdlg, %ID_Label,"",120,10,imgW,imgH, %WS_Child Or %WS_Visible Or %SS_Sunken Or %SS_Notify
Dialog Show Modal hdlg Call dlgproc
End Function
CallBack Function dlgproc()
Local pt As Point
Local XDelta, YDelta As Single
Static SpinInWork,XLast,YLast As Long
Select Case CB.Msg
Case %WM_InitDialog : GetRenderContext
InitializeScene
SetTimer(hDlg, %ID_Timer, 50, %NULL)
ScaleFactor = 1
Case %WM_Timer : DrawScene 1,1,0 'redraw with rotation on all 3 axes
Case %WM_Paint : DrawScene 0,0,0 'redraw with no rotation
Case %WM_Size : Control Set Size hDlg, %ID_Label, Lo(Word, CB.lParam)-130, Hi(Word, CB.lParam)-20
ResizeScene Lo(Word, CB.lParam)-130, Hi(Word, CB.lParam)-20
DrawScene 0,0,0 'redraw with no rotation
Case %WM_Close : wglmakecurrent %null, %null 'unselect rendering context
wgldeletecontext hRC 'delete the rendering context
releasedc hDlg, hDC 'release device context
Case %WM_MouseWheel
Select Case Hi(Integer,CB.wParam)
Case > 0 : ScaleFactor = ScaleFactor + 0.1 : DrawScene 0,0,0
Case < 0 : ScaleFactor = ScaleFactor - 0.1 : DrawScene 0,0,0
End Select
Case %WM_SetCursor
GetCursorPos pt 'p.x and p.y are in screen coordinates
ScreenToClient hDlg, pt 'p.x and p.y are now dialog client coordinates
If GetDlgCtrlID(ChildWindowFromPoint( hDlg, pt )) <> %ID_Label Then Exit Function
Select Case Hi(Word, CB.lParam)
Case %WM_LButtonDown
GetCursorPos pt 'pt has xy screen coordinates
ScreenToClient hDlg, pt 'pt now has dialog client coordinates
If pt.y < 0 Then Exit Select
KillTimer CB.Hndl, %ID_Timer
SpinInWork = 1
XLast = Pt.x
YLast = Pt.y
Case %WM_MouseMove
If SpinInWork Then
GetCursorPos pt 'pt has xy screen coordinates
ScreenToClient hDlg, pt 'pt now has dialog client coordinates
If pt.y < 0 Then Exit Select
XDelta = XLast - Pt.x
YDelta = YLast - Pt.y
DrawScene -YDelta, -XDelta, 0
XLast = pt.x
YLast = pt.y
End If
Case %WM_LButtonUp
SetTimer(hDlg, %ID_Timer, 50, %NULL)
SpinInWork = 0
End Select
End Select
End Function
Sub GetRenderContext
Local pfd As PIXELFORMATDESCRIPTOR 'pixel format properties for device context
pfd.nSize = SizeOf(PIXELFORMATDESCRIPTOR)
pfd.nVersion = 1
pfd.dwFlags = %pfd_draw_to_window Or %pfd_support_opengl Or %pfd_doublebuffer
pfd.dwlayermask = %pfd_main_plane
pfd.iPixelType = %pfd_type_rgba
pfd.ccolorbits = 24
pfd.cdepthbits = 24
Control Handle hdlg, %ID_Label To hLabel
hDC = GetDC(hLabel)
SetPixelFormat(hDC, ChoosePixelFormat(hDC, pfd), pfd) 'set properties of device context
hRC = wglCreateContext (hDC) 'get rendering context
wglMakeCurrent hDC, hRC 'make the RC current
End Sub
Sub InitializeMapping
glEnable %gl_texture_2D
glTexEnvf %gl_texture_env, %gl_texture_env_mode, %gl_modulate
glBindTexture %gl_texture_2D, 1
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, %gl_rgb, 100, 100, 0, %gl_rgba, %gl_unsigned_byte, BMPData(0)
End Sub
Sub InitializeScene
InitializeMapping
glClearColor 0,0,0,0 'sets color to be used with glClear
glClearDepth 1 'sets zvalue to be used with glClear
glEnable %gl_depth_test 'enable depth testing
glHint %gl_perspective_correction_hint, %gl_nicest 'best quality rendering
BuildDisplayList 1
End Sub
Sub ResizeScene (w As Long, h As Long)
glViewport 0, 0, w, h 'resize viewport to match window size
glMatrixMode %gl_projection 'select the projection matrix
glLoadIdentity 'reset the projection matrix
gluPerspective 45, w/h, 0.1, 100 'set frustum using viewport aspect ratio
glMatrixMode %gl_modelview 'select the modelview matrix
End Sub
Sub DrawScene (dx As Single, dy As Single, dz As Single)
Static anglex, angley, anglez As Single
glClear %gl_color_buffer_bit Or %gl_depth_buffer_bit 'clear buffers
glLoadIdentity 'clear the modelview matrix
gluLookAt 0,0,6,0,0,0,0,1,0
glScalef scalefactor, scalefactor, scalefactor
anglex = anglex + dx : glRotatef anglex, 1,0,0
angley = angley + dy : glRotatef angley, 0,1,0
anglez = anglez + dz : glRotatef anglez, 0,0,1
glCallList 1
SwapBuffers hDC 'display the buffer (image)
End Sub
Sub BuildDisplayList(ListNumber As Long)
glNewList ListNumber, %gl_compile
glBegin %gl_quads
' Front Face
glTexCoord2f 0.0, 0.0: glVertex3f -1.0, -1.0, 1.0 ' Bottom Left Of The Texture And Quad
glTexCoord2f 1.0, 0.0: glVertex3f 1.0, -1.0, 1.0 ' Bottom Right Of The Texture And Quad
glTexCoord2f 1.0, 1.0: glVertex3f 1.0, 1.0, 1.0 ' Top Right Of The Texture And Quad
glTexCoord2f 0.0, 1.0: glVertex3f -1.0, 1.0, 1.0 ' Top Left Of The Texture And Quad
' Back Face
glTexCoord2f 1.0, 0.0: glVertex3f -1.0, -1.0, -1.0 ' Bottom Right Of The Texture And Quad
glTexCoord2f 1.0, 1.0: glVertex3f -1.0, 1.0, -1.0 ' Top Right Of The Texture And Quad
glTexCoord2f 0.0, 1.0: glVertex3f 1.0, 1.0, -1.0 ' Top Left Of The Texture And Quad
glTexCoord2f 0.0, 0.0: glVertex3f 1.0, -1.0, -1.0 ' Bottom Left Of The Texture And Quad
' Top Face
glTexCoord2f 0.0, 1.0: glVertex3f -1.0, 1.0, -1.0 ' Top Left Of The Texture And Quad
glTexCoord2f 0.0, 0.0: glVertex3f -1.0, 1.0, 1.0 ' Bottom Left Of The Texture And Quad
glTexCoord2f 1.0, 0.0: glVertex3f 1.0, 1.0, 1.0 ' Bottom Right Of The Texture And Quad
glTexCoord2f 1.0, 1.0: glVertex3f 1.0, 1.0, -1.0 ' Top Right Of The Texture And Quad
' Bottom Face
glTexCoord2f 1.0, 1.0: glVertex3f -1.0, -1.0, -1.0 ' Top Right Of The Texture And Quad
glTexCoord2f 0.0, 1.0: glVertex3f 1.0, -1.0, -1.0 ' Top Left Of The Texture And Quad
glTexCoord2f 0.0, 0.0: glVertex3f 1.0, -1.0, 1.0 ' Bottom Left Of The Texture And Quad
glTexCoord2f 1.0, 0.0: glVertex3f -1.0, -1.0, 1.0 ' Bottom Right Of The Texture And Quad
' Right face
glTexCoord2f 1.0, 0.0: glVertex3f 1.0, -1.0, -1.0 ' Bottom Right Of The Texture And Quad
glTexCoord2f 1.0, 1.0: glVertex3f 1.0, 1.0, -1.0 ' Top Right Of The Texture And Quad
glTexCoord2f 0.0, 1.0: glVertex3f 1.0, 1.0, 1.0 ' Top Left Of The Texture And Quad
glTexCoord2f 0.0, 0.0: glVertex3f 1.0, -1.0, 1.0 ' Bottom Left Of The Texture And Quad
' Left Face
glTexCoord2f 0.0, 0.0: glVertex3f -1.0, -1.0, -1.0 ' Bottom Left Of The Texture And Quad
glTexCoord2f 1.0, 0.0: glVertex3f -1.0, -1.0, 1.0 ' Bottom Right Of The Texture And Quad
glTexCoord2f 1.0, 1.0: glVertex3f -1.0, 1.0, 1.0 ' Top Right Of The Texture And Quad
glTexCoord2f 0.0, 1.0: glVertex3f -1.0, 1.0, -1.0 ' Top Left Of The Texture And Quad
glEnd
glEndList
End Sub
Sub GetBitMapDimensions(sFileName$, w As Long, h As Long)
Open sFileName$ For BINARY As #1
Get #1, 19, w
Get #1, 23, h
Close #1
End Sub
Sub CreateTexture
Local i,j As Long, sFileName As String
sFileName = "cowgirl.bmp"
GetBitMapDimensions(sFileName, imgW, imgH)
Graphic Bitmap Load sFileName, imgW, imgH To hBMP
Graphic Attach hBMP, 0
Dim BMPData(imgW-1,imgH-1)
For i = 0 to imgW-1
For j = 0 to imgH-1
Graphic Get Pixel (i,j) To BMPData(i,imgH-1-j)
Next j
Next i
End Sub
'gbs_00614
'Date: 03-10-2012
http://www.garybeene.com/sw/gbsnippets.htm