Multitexturing Example In NeHe's OpenGL Framework

Share your advanced PureBasic knowledge/code with the community.
hagibaba
Enthusiast
Enthusiast
Posts: 170
Joined: Fri Mar 05, 2004 2:55 am
Location: UK
Contact:

Multitexturing Example In NeHe's OpenGL Framework

Post by hagibaba »

This shows how to do multitexturing and 2-pass blending. It is based on "Multitex.c" by Michael I. Gold.
Press P key to pan textures, R key to rotate textures, L key for lighting, Arrows to rotate cubes and Pageup/Pagedown to zoom.

Last edited on 20 Feb 2007.

Code: Select all

;Multitexturing Example In NeHe's OpenGL Framework
;http://www.berkelium.com/OpenGL/ (Michael I. Gold)
;Credits: Nico Gruener, Dreglor, traumatic
;Author: hagibaba
;Date: 30 Jan 2007
;Note: you can get the "OpenGL.pbi" from "Sources - Advanced\OpenGL Cube"
;Note: up-to-date with PB v4.02 (Windows)
;Note: requires bitmaps in paths "Data/Font.bmp", "Data/Crate.bmp"
;"Data/Cube.bmp"

;Section for standard constants, structures, macros and declarations

XIncludeFile "OpenGL.pbi" ;include the gl.h constants

;wingdi.h constants
#ANTIALIASED_QUALITY=4 ;for CreateFont_()
#DM_BITSPERPEL=$40000
#DM_PELSWIDTH=$80000
#DM_PELSHEIGHT=$100000

;winuser.h constants
#CDS_FULLSCREEN=4
#DISP_CHANGE_SUCCESSFUL=0
#SC_MONITORPOWER=$F170

;glext.h constants
#GL_MAX_TEXTURE_UNITS_ARB=$84E2
#GL_COMBINE_EXT=$8570
#GL_COMBINE_RGB_EXT=$8571
#GL_TEXTURE0_ARB=$84C0
#GL_TEXTURE1_ARB=$84C1

Procedure.w LoWord(value.l) ;windef.h macro
 ProcedureReturn (value & $FFFF)
EndProcedure

Procedure.w HiWord(value.l) ;windef.h macro
 ProcedureReturn ((value >> 16) & $FFFF)
EndProcedure

Import "glu32.lib"
 gluPerspective(fovy.d,aspect.d,zNear.d,zFar.d) ;sets up a perspective projection matrix
EndImport

Import "opengl32.lib"
 glClearDepth(depth.d) ;specifies the clear value for the depth buffer
 glOrtho(left.d,right.d,bottom.d,top.d,near.d,far.d) ;multiplies the current matrix by an orthographic matrix
 glTranslated(x.d,y.d,z.d) ;moves the current matrix to the point specified
EndImport

;Start of Multitexturing Example

Global hDC.l ;Private GDI Device Context
Global hRC.l ;Permanent Rendering Context
Global hWnd.l ;Holds Our Window Handle
Global hInstance.l ;Holds The Instance Of The Application

Global Dim keys.b(256) ;Array Used For The Keyboard Routine
Global active.b=#True ;Window Active Flag Set To TRUE By Default
Global fullscreen.b=#True ;Fullscreen Flag Set To Fullscreen Mode By Default

Global base.l ;Base Display List For The Font Set
Global fonttex.l ;Storage For Font Texture
Global Dim texture.l(2) ;Storage For 2 Textures

Global xrot.f ;X Rotation
Global yrot.f ;Y Rotation
Global z.f=-6.0 ;Depth Into The Screen
Global angle.f=0 ;Texture Rotation and Panning

Global light.b ;Lighting Flag
Global panTextures.b=0 ;Pan Textures Flag
Global rotTextures.b=0 ;Rotate Textures Flag

Global glActiveTextureARB.l ;Function Pointers
Global glMultiTexCoord2fARB.l

Global Dim LightAmbient.f(3) ;Ambient Light is 20% white
 LightAmbient(0)=0.2 ;red
 LightAmbient(1)=0.2 ;green
 LightAmbient(2)=0.2 ;blue
 
Global Dim LightDiffuse.f(3) ;Diffuse Light is white
 LightDiffuse(0)=1.0 ;red
 LightDiffuse(1)=1.0 ;green
 LightDiffuse(2)=1.0 ;blue
 
Global Dim LightPosition.f(3) ;Position is somewhat in front of screen
 LightPosition(0)=0.0 ;x
 LightPosition(1)=0.0 ;y
 LightPosition(2)=2.0 ;z

;Data Contains The Faces For The Cube In Format 2xTexCoord, 3xVertex;
;Note That The Tesselation Of The Cube Is Only Absolute Minimum.
Global Dim dat.f(120)
 ;Front Face
 dat(  0)=0.0: dat(  1)=0.0: dat(  2)=-1.0: dat(  3)=-1.0: dat(  4)= 1.0
 dat(  5)=1.0: dat(  6)=0.0: dat(  7)= 1.0: dat(  8)=-1.0: dat(  9)= 1.0
 dat( 10)=1.0: dat( 11)=1.0: dat( 12)= 1.0: dat( 13)= 1.0: dat( 14)= 1.0
 dat( 15)=0.0: dat( 16)=1.0: dat( 17)=-1.0: dat( 18)= 1.0: dat( 19)= 1.0
 ;Back Face
 dat( 20)=1.0: dat( 21)=0.0: dat( 22)=-1.0: dat( 23)=-1.0: dat( 24)=-1.0
 dat( 25)=1.0: dat( 26)=1.0: dat( 27)=-1.0: dat( 28)= 1.0: dat( 29)=-1.0
 dat( 30)=0.0: dat( 31)=1.0: dat( 32)= 1.0: dat( 33)= 1.0: dat( 34)=-1.0
 dat( 35)=0.0: dat( 36)=0.0: dat( 37)= 1.0: dat( 38)=-1.0: dat( 39)=-1.0
 ;Top Face
 dat( 40)=0.0: dat( 41)=1.0: dat( 42)=-1.0: dat( 43)= 1.0: dat( 44)=-1.0
 dat( 45)=0.0: dat( 46)=0.0: dat( 47)=-1.0: dat( 48)= 1.0: dat( 49)= 1.0
 dat( 50)=1.0: dat( 51)=0.0: dat( 52)= 1.0: dat( 53)= 1.0: dat( 54)= 1.0
 dat( 55)=1.0: dat( 56)=1.0: dat( 57)= 1.0: dat( 58)= 1.0: dat( 59)=-1.0
 ;Bottom Face
 dat( 60)=1.0: dat( 61)=1.0: dat( 62)=-1.0: dat( 63)=-1.0: dat( 64)=-1.0
 dat( 65)=0.0: dat( 66)=1.0: dat( 67)= 1.0: dat( 68)=-1.0: dat( 69)=-1.0
 dat( 70)=0.0: dat( 71)=0.0: dat( 72)= 1.0: dat( 73)=-1.0: dat( 74)= 1.0
 dat( 75)=1.0: dat( 76)=0.0: dat( 77)=-1.0: dat( 78)=-1.0: dat( 79)= 1.0
 ;Right Face
 dat( 80)=1.0: dat( 81)=0.0: dat( 82)= 1.0: dat( 83)=-1.0: dat( 84)=-1.0
 dat( 85)=1.0: dat( 86)=1.0: dat( 87)= 1.0: dat( 88)= 1.0: dat( 89)=-1.0
 dat( 90)=0.0: dat( 91)=1.0: dat( 92)= 1.0: dat( 93)= 1.0: dat( 94)= 1.0
 dat( 95)=0.0: dat( 96)=0.0: dat( 97)= 1.0: dat( 98)=-1.0: dat( 99)= 1.0
 ;Left Face
 dat(100)=0.0: dat(101)=0.0: dat(102)=-1.0: dat(103)=-1.0: dat(104)=-1.0
 dat(105)=1.0: dat(106)=0.0: dat(107)=-1.0: dat(108)=-1.0: dat(109)= 1.0
 dat(110)=1.0: dat(111)=1.0: dat(112)=-1.0: dat(113)= 1.0: dat(114)= 1.0
 dat(115)=0.0: dat(116)=1.0: dat(117)=-1.0: dat(118)= 1.0: dat(119)=-1.0

Declare.l WndProc(hWnd.l,uMsg.l,wParam.l,lParam.l) ;Declaration For WndProc

Procedure.l LoadBMP(lpFileName.s) ;Loads a 24-bit DIB

 Protected hFile.l
 Protected hDIB.l
 Protected bfh.BITMAPFILEHEADER
 Protected bi.BITMAPINFOHEADER
 Protected lpbi.l ;pointer to BITMAPINFOHEADER
 Protected dwBitCount.l ;bits per pixel
 Protected dwNumColors.l ;number of colors in table
 Protected dwLen.l ;size of memory block
 Protected dwBytesPerLine.l ;number of bytes per scanline
 Protected ix.l,iy.l,ib.l ;loop variables
 Protected offset.l,byte.l,index.l ;temporary values
 Protected Dim col.b(256*SizeOf(RGBQUAD)) ;color table array
 
 hFile=ReadFile(#PB_Any,lpFileName) ;open the file to read
 
 If hFile=0 ;the file can't be opened
  ProcedureReturn #False
 EndIf
 
 ;Read the BITMAPFILEHEADER from our file
 ReadData(hFile,bfh,SizeOf(BITMAPFILEHEADER))
 
 If bfh\bfType<>$4d42 ;check header marker is "BM"
  CloseFile(hFile)
  ProcedureReturn #False
 EndIf
 
 ;Read the BITMAPINFOHEADER
 ReadData(hFile,bi,SizeOf(BITMAPINFOHEADER))
 
 ;Check to see that it's a Windows DIB, we'll not support the OS/2 DIB
 If bi\biSize=SizeOf(BITMAPCOREHEADER)
  CloseFile(hFile)
  ProcedureReturn #False
 EndIf
 
 dwBitCount=bi\biBitCount ;get bits per pixel, we need this later
 dwNumColors=bi\biClrUsed ;get number of colors in table
 
 ;Now determine the size of the color table
 If dwNumColors=0
  If dwBitCount<>24 ;no color table for 24-bit, default size otherwise
   dwNumColors=1 << dwBitCount ;standard size table (2, 16, 256 or 0)
  EndIf
 EndIf
 
 ;Read the color table to an array
 ReDim col.b(dwNumColors*SizeOf(RGBQUAD)) ;resize col()
 ReadData(hFile,col(),dwNumColors*SizeOf(RGBQUAD))
 
 ;Calculate size of memory block required to store the DIB
 dwBytesPerLine=((bi\biWidth*24)+31)/32*4 ;DWORD-aligned scanline (pitch)
 dwLen=bi\biSize+(dwBytesPerLine*bi\biHeight) ;info header + bits
 
 ;Reinitialize the BITMAPINFOHEADER as 24-bit
 bi\biSize=SizeOf(BITMAPINFOHEADER)
 bi\biWidth=bi\biWidth ;width is same
 bi\biHeight=bi\biHeight ;height is same
 bi\biPlanes=1 ;must be 1
 bi\biBitCount=24
 bi\biCompression=#BI_RGB ;none
 bi\biSizeImage=dwBytesPerLine*bi\biHeight ;0's here mean "default"
 bi\biXPelsPerMeter=0
 bi\biYPelsPerMeter=0
 bi\biClrUsed=0
 bi\biClrImportant=0
 
 ;Allocate memory block to store our bitmap
 hDIB=GlobalAlloc_(#GHND,dwLen)
 
 If hDIB=0 ;major bummer if we couldn't get memory block
  CloseFile(hFile)
  ProcedureReturn #False
 EndIf
 
 lpbi=GlobalLock_(hDIB) ;lock memory and get pointer to it
 
 ;Use our BITMAPINFOHEADER to fill in the first part of our DIB
 CopyMemory(bi,lpbi,bi\biSize)
 
 ;If the bfOffBits field is non-zero, then the bits might *not* be
 ;directly following the color table in the file
 If bfh\bfOffBits<>0
  FileSeek(hFile,bfh\bfOffBits) ;start of bits
 EndIf
 
 Select dwBitCount ;can be 1, 4, 8 or 24 bits per pixel
 
  Case 1 ;convert 1-bit data to 24-bit
   For iy=0 To bi\biHeight-1
    offset=dwBytesPerLine*iy ;start of scanline
    For ix=0 To bi\biWidth-1
     If ix % 8=0 ;every 8th pixel
      byte=ReadByte(hFile)
      If byte<0 : byte+256 : EndIf ;can't have a minus value for col()
      For ib=0 To 7 ;one byte is 8 pixels
       index=byte & (1 << (7-ib)) ;mask byte with bits (highest bit first)
       If index : index=1 : Else : index=0 : EndIf ;index to 0 or 1
       PokeB(lpbi+bi\biSize+offset+(ix*3)+(ib*3),col(index*4))
       PokeB(lpbi+bi\biSize+offset+(ix*3)+(ib*3)+1,col((index*4)+1))
       PokeB(lpbi+bi\biSize+offset+(ix*3)+(ib*3)+2,col((index*4)+2))
      Next
     EndIf
    Next
   Next
   
  Case 4 ;convert 4-bit data to 24-bit
   For iy=0 To bi\biHeight-1
    offset=dwBytesPerLine*iy ;start of scanline
    For ix=0 To bi\biWidth-1
     If ix % 2=0 ;every 2nd pixel
      byte=ReadByte(hFile)
      If byte<0 : byte+256 : EndIf ;can't have a minus value for col()
      For ib=0 To 1 ;one byte is 2 pixels
       If ib=0 : index=byte >> 4 : EndIf ;bits 4..7 (high nibble first)
       If ib=1 : index=byte & 15 : EndIf ;bits 0..3
       PokeB(lpbi+bi\biSize+offset+(ix*3)+(ib*3),col(index*4))
       PokeB(lpbi+bi\biSize+offset+(ix*3)+(ib*3)+1,col((index*4)+1))
       PokeB(lpbi+bi\biSize+offset+(ix*3)+(ib*3)+2,col((index*4)+2))
      Next
     EndIf
    Next
   Next
   
  Case 8 ;convert 8-bit data to 24-bit
   For iy=0 To bi\biHeight-1
    offset=dwBytesPerLine*iy ;start of scanline
    For ix=0 To bi\biWidth-1
     byte=ReadByte(hFile) ;one byte is one pixel
     If byte<0 : byte+256 : EndIf ;can't have a minus value for col()
     PokeB(lpbi+bi\biSize+offset+(ix*3),col(byte*4))
     PokeB(lpbi+bi\biSize+offset+(ix*3)+1,col((byte*4)+1))
     PokeB(lpbi+bi\biSize+offset+(ix*3)+2,col((byte*4)+2))
    Next
   Next
   
  Case 24 ;read the 24-bit data directly
   ReadData(hFile,lpbi+bi\biSize,bi\biSizeImage)
   
 EndSelect
 
 GlobalUnlock_(hDIB) ;unlock the DIB
 CloseFile(hFile) ;close the file
 Dim col.b(0) ;delete the array
 ProcedureReturn hDIB ;return handle to the DIB
 
EndProcedure

Procedure.l GetBMP(hDIB.l,*bmp.BITMAP) ;Gets BITMAP info about a DIB

 Protected lpbi.l ;pointer to BITMAPINFOHEADER
 
 lpbi=GlobalLock_(hDIB) ;lock memory and get pointer to it
 
 If lpbi=0 ;if we couldn't lock memory
  ProcedureReturn #False ;fails
 EndIf
 
 ;Get BITMAP info from BITMAPINFOHEADER
 *bmp\bmType=0 ;must be zero
 *bmp\bmWidth=PeekL(lpbi+4) ;biWidth
 *bmp\bmHeight=PeekL(lpbi+8) ;biHeight
 *bmp\bmWidthBytes=((PeekL(lpbi+4)*PeekW(lpbi+14))+31)/32*4 ;DWORD-aligned Width
 *bmp\bmPlanes=PeekW(lpbi+12) ;biPlanes
 *bmp\bmBitsPixel=PeekW(lpbi+14) ;biBitCount
 *bmp\bmBits=lpbi+PeekL(lpbi)+(PeekL(lpbi+32)*SizeOf(RGBQUAD)) ;biSize+(biClrUsed*4)
 
 GlobalUnlock_(hDIB) ;unlock the DIB
 ProcedureReturn #True ;succeeds
 
EndProcedure

Procedure.l FreeBMP(hDIB.l) ;Frees a DIB from memory

 ProcedureReturn GlobalFree_(hDIB)
 
EndProcedure

Procedure.l LoadGLTextures() ;Load Bitmaps And Convert To Textures

 Protected Dim hBMP.l(3) ;Handle Of The Bitmaps
 Protected Dim BMP.BITMAP(3) ;Bitmap Structures
 Protected loop.l
 
 hBMP(0)=LoadBMP("Data/Font.bmp")
 GetBMP(hBMP(0),BMP(0)) ;Get the BITMAP info
 
 hBMP(1)=LoadBMP("Data/Crate.bmp")
 GetBMP(hBMP(1),BMP(1)) ;Get the BITMAP info
 
 hBMP(2)=LoadBMP("Data/Cube.bmp")
 GetBMP(hBMP(2),BMP(2)) ;Get the BITMAP info
 
 For loop=0 To 3-1
  If hBMP(loop)=0 ;Do The Bitmaps Exist?
   ProcedureReturn #False ;If Not Return False
  EndIf
 Next
 
 glGenTextures_(1,@fonttex) ;Create One Texture
 glGenTextures_(2,@texture(0)) ;Create Two Textures
 
 For loop=0 To 3-1
  If loop=0
   glBindTexture_(#GL_TEXTURE_2D,fonttex)
  Else
   glBindTexture_(#GL_TEXTURE_2D,texture(loop-1))
  EndIf
  ;Create Linear Filtered Textures
  glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MIN_FILTER,#GL_LINEAR)
  glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MAG_FILTER,#GL_LINEAR)
  glTexImage2D_(#GL_TEXTURE_2D,0,3,BMP(loop)\bmWidth,BMP(loop)\bmHeight,0,#GL_BGR_EXT,#GL_UNSIGNED_BYTE,BMP(loop)\bmBits)
 Next
 
 For loop=0 To 3-1
  FreeBMP(hBMP(loop)) ;Delete The Bitmaps
 Next
 
 ProcedureReturn #True ;Loading Was Successful
 
EndProcedure

Procedure ReSizeGLScene(width.l,height.l) ;Resize And Initialize The GL Window

 Protected aspect.f
 
 If height=0 : height=1 : EndIf ;Prevent A Divide By Zero Error
 aspect=width/height ;make sure aspect is a float
 
 glViewport_(0,0,width,height) ;Reset The Current Viewport
 
 glMatrixMode_(#GL_PROJECTION) ;Select The Projection Matrix
 glLoadIdentity_() ;Reset The Projection Matrix
 
 gluPerspective(45.0,aspect,0.1,100.0) ;Calculate The Aspect Ratio Of The Window
 
 glMatrixMode_(#GL_MODELVIEW) ;Select The Modelview Matrix
 glLoadIdentity_() ;Reset The Modelview Matrix
 
EndProcedure

Procedure.b GetGLProcs()

 Protected strExtensions.s
 
 strExtensions=PeekS(glGetString_(#GL_EXTENSIONS)) ;Get Extensions String
 If FindString(strExtensions,"GL_ARB_multitexture",1)=0
  MessageBox_(#Null,"GL_ARB_multitexture not found.","Error",#MB_OK | #MB_ICONINFORMATION)
  ProcedureReturn #False
 EndIf
 
 glActiveTextureARB=wglGetProcAddress_("glActiveTextureARB")
 glMultiTexCoord2fARB=wglGetProcAddress_("glMultiTexCoord2fARB")
 ProcedureReturn #True
 
EndProcedure

Procedure BuildFont() ;Build Our Font Display List

 Protected cx.f ;Holds Our X Character Coord
 Protected cy.f ;Holds Our Y Character Coord
 Protected modx.l ;modulus for x coord
 
 base=glGenLists_(256) ;Creating 256 Display Lists
 
 glBindTexture_(#GL_TEXTURE_2D,fonttex) ;Select Our Font Texture
 
 For loop=0 To 256-1 ;Loop Through All 256 Lists
  modx=loop % 16 ;Note: can't use % with floats
  cx=modx/16.0 ;X Position Of Current Character
  cy=Int(loop/16)/16.0 ;Y Position Of Current Character
  
  glNewList_(base+loop,#GL_COMPILE) ;Start Building A List
   glBegin_(#GL_QUADS) ;Use A Quad For Each Character
    glTexCoord2f_(cx,1-cy-0.0625) ;Texture Coord (Bottom Left)
    glVertex2i_(0,0) ;Vertex Coord (Bottom Left)
    glTexCoord2f_(cx+0.0625,1-cy-0.0625) ;Texture Coord (Bottom Right)
    glVertex2i_(16,0) ;Vertex Coord (Bottom Right)
    glTexCoord2f_(cx+0.0625,1-cy) ;Texture Coord (Top Right)
    glVertex2i_(16,16) ;Vertex Coord (Top Right)
    glTexCoord2f_(cx,1-cy) ;Texture Coord (Top Left)
    glVertex2i_(0,16) ;Vertex Coord (Top Left)
   glEnd_() ;Done Building Our Quad (Character)
   glTranslated(10,0,0) ;Move To The Right Of The Character
  glEndList_() ;Done Building The Display List
 Next ;Loop Until All 256 Are Built
 
EndProcedure

Procedure KillFont() ;Delete The Font From Memory

 glDeleteLists_(base,256) ;Delete All 256 Display Lists
 
EndProcedure

Procedure glPrint(x.l,y.l,string.s,set.l) ;Where The Printing Happens

 If set : set=1 : EndIf ;Is set True? If So, Make set Equal One
 
 glBindTexture_(#GL_TEXTURE_2D,fonttex) ;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_(base-32+(128*set)) ;Choose The Font Set (0 or 1)
   glCallLists_(Len(string),#GL_BYTE,string) ;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
 
EndProcedure

Procedure.l InitGL() ;All Setup For OpenGL Goes Here

 GetGLProcs() ;Initialize Multitexturing
 
 If LoadGLTextures()=0 ;Jump To Texture Loading Routine
  ProcedureReturn #False ;If Textures Didn't Load Return FALSE
 EndIf
 
 BuildFont() ;Build The Font
 
 glShadeModel_(#GL_SMOOTH) ;Enable Smooth Shading
 glClearColor_(0.0,0.0,0.0,0.5) ;Black Background
 glClearDepth(1.0) ;Depth Buffer Setup
 glEnable_(#GL_DEPTH_TEST) ;Enables Depth Testing
 glDepthFunc_(#GL_LEQUAL) ;The Type Of Depth Testing To Do
 glHint_(#GL_PERSPECTIVE_CORRECTION_HINT,#GL_NICEST) ;Really Nice Perspective Calculations  
 
 glLightfv_(#GL_LIGHT1,#GL_AMBIENT,LightAmbient()) ;Ambient Light
 glLightfv_(#GL_LIGHT1,#GL_DIFFUSE,LightDiffuse()) ;Diffuse Light
 glLightfv_(#GL_LIGHT1,#GL_POSITION,LightPosition()) ;Position Light
 glEnable_(#GL_LIGHT1) ;Enable Light One
 
 ProcedureReturn #True ;Initialization Went OK
 
EndProcedure

Procedure doCube()

 Protected i.l
 
 glBegin_(#GL_QUADS)
  ;Front Face
  glNormal3f_( 0.0, 0.0, 1.0)
  For i=0 To 4-1
   glTexCoord2f_(dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Back Face
  glNormal3f_( 0.0, 0.0,-1.0)
  For i=4 To 8-1
   glTexCoord2f_(dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Top Face
  glNormal3f_( 0.0, 1.0, 0.0)
  For i=8 To 12-1
   glTexCoord2f_(dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Bottom Face
  glNormal3f_( 0.0,-1.0, 0.0)
  For i=12 To 16-1
   glTexCoord2f_(dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Right face
  glNormal3f_( 1.0, 0.0, 0.0)
  For i=16 To 20-1
   glTexCoord2f_(dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Left Face
  glNormal3f_(-1.0, 0.0, 0.0)
  For i=20 To 24-1
   glTexCoord2f_(dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
 glEnd_()
 
EndProcedure

Procedure doCubeMulti()

 Protected i.l
 
 glBegin_(#GL_QUADS)
  ;Front Face
  glNormal3f_( 0.0, 0.0, 1.0)
  For i=0 To 4-1
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE0_ARB,dat(5*i),dat((5*i)+1))
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE1_ARB,dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Back Face
  glNormal3f_( 0.0, 0.0,-1.0)
  For i=4 To 8-1
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE0_ARB,dat(5*i),dat((5*i)+1))
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE1_ARB,dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Top Face
  glNormal3f_( 0.0, 1.0, 0.0)
  For i=8 To 12-1
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE0_ARB,dat(5*i),dat((5*i)+1))
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE1_ARB,dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Bottom Face
  glNormal3f_( 0.0,-1.0, 0.0)
  For i=12 To 16-1
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE0_ARB,dat(5*i),dat((5*i)+1))
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE1_ARB,dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Right face
  glNormal3f_( 1.0, 0.0, 0.0)
  For i=16 To 20-1
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE0_ARB,dat(5*i),dat((5*i)+1))
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE1_ARB,dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
  ;Left Face
  glNormal3f_(-1.0, 0.0, 0.0)
  For i=20 To 24-1
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE0_ARB,dat(5*i),dat((5*i)+1))
   CallFunctionFast(glMultiTexCoord2fARB,#GL_TEXTURE1_ARB,dat(5*i),dat((5*i)+1))
   glVertex3f_(dat((5*i)+2),dat((5*i)+3),dat((5*i)+4))
  Next
 glEnd_()
 
EndProcedure

Procedure.l DrawGLScene() ;Here's Where We Do All The Drawing

 Protected i.l,status.s
 
 glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT) ;Clear Screen And Depth Buffer
 
 ;Multitextured Cube
 glMatrixMode_(#GL_MODELVIEW) ;Select The Modelview Matrix
 glLoadIdentity_() ;Reset The Modelview Matrix
 glTranslatef_(-1.5,0.0,z) ;Move Left 1.5 Units And Away z
 glRotatef_(xrot,1.0,0.0,0.0) ;Rotate On The X Axis By xrot
 glRotatef_(yrot,0.0,1.0,0.0) ;Rotate On The Y Axis By yrot
 
 CallFunctionFast(glActiveTextureARB,#GL_TEXTURE0_ARB) ;Texture-Unit 0
 glEnable_(#GL_TEXTURE_2D) ;Enable 2D Texture Mapping
 glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select 1st Texture
 glTexEnvi_(#GL_TEXTURE_ENV,#GL_TEXTURE_ENV_MODE,#GL_MODULATE) ;Normal Lighting
 
 glMatrixMode_(#GL_TEXTURE) ;Select The Texture Matrix
 glLoadIdentity_() ;Reset The Texture Matrix
 If panTextures
  glTranslatef_(-2.0*angle*0.002,-angle*0.002,0) ;Move Right And Up
 EndIf
 If rotTextures
  glTranslatef_(0.5,0.5,0.0) ;Move To Center
  glRotatef_(-angle,0.0,0.0,1.0) ;Rotate Counter-Clockwise
  glTranslatef_(-0.5,-0.5,0.0) ;Move Back
 EndIf
 
 CallFunctionFast(glActiveTextureARB,#GL_TEXTURE1_ARB) ;Texture-Unit 1
 glEnable_(#GL_TEXTURE_2D) ;Enable 2D Texture Mapping
 glBindTexture_(#GL_TEXTURE_2D,texture(1)) ;Select 2nd Texture
 glTexEnvi_(#GL_TEXTURE_ENV,#GL_TEXTURE_ENV_MODE,#GL_MODULATE) ;Normal Lighting
 
 glMatrixMode_(#GL_TEXTURE) ;Select The Texture Matrix
 glLoadIdentity_() ;Reset The Texture Matrix
 If panTextures
  glTranslatef_(2.0*angle*0.002,angle*0.002,0) ;Move Left And Down
 EndIf
 If rotTextures
  glTranslatef_(0.5,0.5,0.0) ;Move To Center
  glRotatef_(angle,0.0,0.0,1.0) ;Rotate Clockwise
  glTranslatef_(-0.5,-0.5,0.0) ;Move Back
 EndIf
 
 glColor4f_(1.0,1.0,1.0,1.0) ;Full Brightness. 100% Alpha
 glBlendFunc_(#GL_SRC_ALPHA,#GL_ONE_MINUS_SRC_ALPHA) ;Blending For Translucency Based On Source Alpha
 glEnable_(#GL_BLEND) ;Enable Blending
 
 doCubeMulti() ;Multitextured Cube
 
 CallFunctionFast(glActiveTextureARB,#GL_TEXTURE1_ARB) ;Texture-Unit 1
 glDisable_(#GL_TEXTURE_2D) ;Disable 2D Texture Mapping
 CallFunctionFast(glActiveTextureARB,#GL_TEXTURE0_ARB) ;Texture-Unit 0
 glDisable_(#GL_TEXTURE_2D) ;Disable 2D Texture Mapping
 
 ;2-Pass Blended Cube
 glMatrixMode_(#GL_MODELVIEW) ;Select The Modelview Matrix
 glLoadIdentity_() ;Reset The Modelview Matrix
 glTranslatef_(1.5,0.0,z) ;Move Right 1.5 Units And Away z
 glRotatef_(xrot,1.0,0.0,0.0) ;Rotate On The X Axis By xrot
 glRotatef_(yrot,0.0,1.0,0.0) ;Rotate On The Y Axis By yrot
 
 glEnable_(#GL_TEXTURE_2D) ;Enable 2D Texture Mapping
 glDisable_(#GL_BLEND) ;Disable Blending
 
 glBindTexture_(#GL_TEXTURE_2D,texture(0)) ;Select 1st Texture
 glTexEnvi_(#GL_TEXTURE_ENV,#GL_TEXTURE_ENV_MODE,#GL_MODULATE) ;Normal Lighting
 
 glMatrixMode_(#GL_TEXTURE) ;Select The Texture Matrix
 glLoadIdentity_() ;Reset The Texture Matrix
 If panTextures
  glTranslatef_(-2.0*angle*0.002,-angle*0.002,0) ;Move Right And Up
 EndIf
 If rotTextures
  glTranslatef_(0.5,0.5,0.0) ;Move To Center
  glRotatef_(-angle,0.0,0.0,1.0) ;Rotate Counter-Clockwise
  glTranslatef_(-0.5,-0.5,0.0) ;Move Back
 EndIf
 
 doCube() ;Unblended Cube
 
 glColor4f_(0.5,0.5,0.5,0.5) ;Half Brightness. 50% Alpha
 glBlendFunc_(#GL_SRC_ALPHA,#GL_ONE_MINUS_SRC_ALPHA) ;Blending For Translucency Based On Source Alpha
 glEnable_(#GL_BLEND) ;Enable Blending
 If light : glDisable_(#GL_LIGHTING) : EndIf ;Disable Lighting
 
 glBindTexture_(#GL_TEXTURE_2D,texture(1)) ;Select 2nd Texture
 glTexEnvi_(#GL_TEXTURE_ENV,#GL_TEXTURE_ENV_MODE,#GL_MODULATE) ;Normal Lighting
 
 glMatrixMode_(#GL_TEXTURE) ;Select The Texture Matrix
 glLoadIdentity_() ;Reset The Texture Matrix
 If panTextures
  glTranslatef_(2.0*angle*0.002,angle*0.002,0) ;Move Left And Down
 EndIf
 If rotTextures
  glTranslatef_(0.5,0.5,0.0) ;Move To Center
  glRotatef_(angle,0.0,0.0,1.0) ;Rotate Clockwise
  glTranslatef_(-0.5,-0.5,0.0) ;Move Back
 EndIf
 
 doCube() ;Blended Cube
 
 glDisable_(#GL_TEXTURE_2D) ;Disable 2D Texture Mapping
 glDisable_(#GL_BLEND) ;Disable Blending
 If light : glEnable_(#GL_LIGHTING) : EndIf ;Enable Lighting
 
 ;Blended Texture Text
 glMatrixMode_(#GL_TEXTURE) ;Select The Texture Matrix
 glLoadIdentity_() ;Reset The Texture Matrix
 
 glBlendFunc_(#GL_SRC_ALPHA,#GL_ONE) ;Select The Type Of Blending
 glEnable_(#GL_TEXTURE_2D) ;Enable 2D Texture Mapping
 glEnable_(#GL_BLEND) ;Enable Blending
 If light : glDisable_(#GL_LIGHTING) : EndIf ;Disable Lighting
 
 glColor3f_(1.0,1.0,1.0) ;Set Color To White
 glPrint(80,400,"Multitexturing",0)
 glPrint(420,400,"2-Pass Blending",0)
 glPrint(200,140,"Keys:",0)
 If panTextures : status="(ON)" : Else : status="(OFF)" : EndIf
 glPrint(200,120,"P to pan textures "+status,0)
 If rotTextures : status="(ON)" : Else : status="(OFF)" : EndIf
 glPrint(200,100,"R to rotate textures "+status,0)
 If light : status="(ON)" : Else : status="(OFF)" : EndIf
 glPrint(200,80,"L for lighting "+status,0)
 glPrint(200,60,"Arrows to rotate cubes",0)
 glPrint(200,40,"Pageup/Pagedown to zoom",0)
 If glActiveTextureARB=0
  glPrint(200,20,"No GL_ARB_multitexture",0)
 EndIf
 
 glDisable_(#GL_TEXTURE_2D) ;Disable 2D Texture Mapping
 glDisable_(#GL_BLEND) ;Disable Blending
 If light : glEnable_(#GL_LIGHTING) : EndIf ;Enable Lighting
 
 If panTextures Or rotTextures
  angle+0.1 ;Increase angle
 EndIf
 
 ProcedureReturn #True ;Everything Went OK
 
EndProcedure

Procedure KillGLWindow() ;Properly Kill The Window

 If fullscreen ;Are We In Fullscreen Mode?
  ChangeDisplaySettings_(#Null,0) ;If So Switch Back To The Desktop
  ShowCursor_(#True) ;Show Mouse Pointer
 EndIf
 
 If hRC ;Do We Have A Rendering Context?
  If wglMakeCurrent_(#Null,#Null)=0 ;Are We Able To Release The DC And RC Contexts?
   MessageBox_(#Null,"Release Of DC And RC Failed.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  EndIf
  If wglDeleteContext_(hRC)=0 ;Are We Able To Delete The RC?
   MessageBox_(#Null,"Release Rendering Context Failed.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  EndIf
  hRC=#Null ;Set RC To NULL
 EndIf
 
 If hDC And ReleaseDC_(hWnd,hDC)=0 ;Are We Able To Release The DC
  MessageBox_(#Null,"Release Device Context Failed.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  hDC=#Null ;Set DC To NULL
 EndIf
 
 If hWnd And DestroyWindow_(hWnd)=0 ;Are We Able To Destroy The Window?
   MessageBox_(#Null,"Could Not Release hWnd.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
   hWnd=#Null ;Set hWnd To NULL
 EndIf
 
 If UnregisterClass_("OpenGL",hInstance)=0 ;Are We Able To Unregister Class
  MessageBox_(#Null,"Could Not Unregister Class.","SHUTDOWN ERROR",#MB_OK | #MB_ICONINFORMATION)
  hInstance=#Null ;Set hInstance To NULL
 EndIf
 
 KillFont() ;Destroy The Font
 
EndProcedure

;This Code Creates Our OpenGL Window. Parameters Are:
;title - Title To Appear At The Top Of The Window
;width - Width Of The GL Window Or Fullscreen Mode
;height - Height Of The GL Window Or Fullscreen Mode
;bits - Number Of Bits To Use For Color (8/16/24/32)
;fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE)

Procedure.b CreateGLWindow(title.s,width.l,height.l,bits.l,fullscreenflag.b)

 Protected PixelFormat.l ;Holds The Results After Searching For A Match
 Protected wc.WNDCLASS ;Windows Class Structure
 Protected dwExStyle.l ;Window Extended Style
 Protected dwStyle.l ;Window Style
 Protected WindowRect.RECT ;Grabs Rectangle Upper Left / Lower Right Values
 Protected wpos.POINT ;Window position
 
 WindowRect\left=0 ;Set Left Value To 0
 WindowRect\right=width ;Set Right Value To Requested Width
 WindowRect\top=0 ;Set Top Value To 0
 WindowRect\bottom=height ;Set Bottom Value To Requested Height
 
 fullscreen=fullscreenflag ;Set The Global Fullscreen Flag
 
 hInstance=GetModuleHandle_(#Null) ;Grab An Instance For Our Window
 
 wc\style=#CS_HREDRAW | #CS_VREDRAW | #CS_OWNDC ;Redraw On Size, And Own DC For Window
 wc\lpfnWndProc=@WndProc() ;WndProc Handles Messages
 wc\cbClsExtra=0 ;No Extra Window Data
 wc\cbWndExtra=0 ;No Extra Window Data
 wc\hInstance=hInstance ;Set The Instance
 wc\hIcon=LoadIcon_(#Null,#IDI_WINLOGO) ;Load The Default Icon
 wc\hCursor=LoadCursor_(#Null,#IDC_ARROW) ;Load The Arrow Pointer
 wc\hbrBackground=#Null ;No Background Required For GL
 wc\lpszMenuName=#Null ;We Don't Want A Menu
 wc\lpszClassName=@"OpenGL" ;Set The Class Name  
 
 If RegisterClass_(wc)=0 ;Attempt To Register The Window Class
  MessageBox_(#Null,"Failed To Register The Window Class.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If fullscreen ;Attempt Fullscreen Mode?
 
  Protected dmScreenSettings.DEVMODE ;Device Mode
  dmScreenSettings\dmSize=SizeOf(DEVMODE) ;Size Of The Devmode Structure
  dmScreenSettings\dmFields=#DM_BITSPERPEL | #DM_PELSWIDTH | #DM_PELSHEIGHT ;bit flags to specify the members of DEVMODE that were initialized
  dmScreenSettings\dmBitsPerPel=bits ;Selected Bits Per Pixel
  dmScreenSettings\dmPelsWidth=width ;Selected Screen Width in pixels
  dmScreenSettings\dmPelsHeight=height ;Selected Screen Height in pixels
  
  ;Try To Set Selected Mode And Get Results. Note: CDS_FULLSCREEN Gets Rid Of Start Bar
  If ChangeDisplaySettings_(dmScreenSettings,#CDS_FULLSCREEN)<>#DISP_CHANGE_SUCCESSFUL
   ;If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode
   If MessageBox_(#Null,"The Requested Fullscreen Mode Is Not Supported By"+Chr(10)+"Your Video Card. Use Windowed Mode Instead?","NeHe GL",#MB_YESNO | #MB_ICONEXCLAMATION)=#IDYES
    fullscreen=#False ;Windowed Mode Selected.  Fullscreen = FALSE
   Else
    ;Pop Up A Message Box Letting User Know The Program Is Closing
    MessageBox_(#Null,"Program Will Now Close.","ERROR",#MB_OK | #MB_ICONSTOP)
    ProcedureReturn #False
   EndIf
  EndIf
  
 EndIf
 
 If fullscreen ;Are We Still In Fullscreen Mode?
  dwExStyle=#WS_EX_APPWINDOW ;Window Extended Style
  dwStyle=#WS_POPUP ;Windows Style
  ShowCursor_(#False) ;Hide Mouse Pointer
 Else
  dwExStyle=#WS_EX_APPWINDOW | #WS_EX_WINDOWEDGE ;Window Extended Style
  dwStyle=#WS_OVERLAPPEDWINDOW ;Windows Style
 EndIf
 
 AdjustWindowRectEx_(WindowRect,dwStyle,#False,dwExStyle) ;Adjust Window To True Requested Size
 
 If fullscreen=0 ;if not fullscreen mode calculate screen centered window
  wpos\x=(GetSystemMetrics_(#SM_CXSCREEN)/2)-((WindowRect\right-WindowRect\left)/2)
  wpos\y=(GetSystemMetrics_(#SM_CYSCREEN)/2)-((WindowRect\bottom-WindowRect\top)/2)
 EndIf
 
 ;CreateWindowEx_(Extended Window Style, Class Name, Window Title, Window Style, Window X Position, Window Y Position, Width, Height, No Parent Window, No Menu, Instance, No Creation Data)
 hWnd=CreateWindowEx_(dwExStyle,"OpenGL",title,dwStyle | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN,wpos\x,wpos\y,WindowRect\right-WindowRect\left,WindowRect\bottom-WindowRect\top,#Null,#Null,hInstance,#Null)
 If hWnd=0
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Window Creation Error.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 Protected pfd.PIXELFORMATDESCRIPTOR ;pfd Tells Windows How We Want Things To Be
 pfd\nSize=SizeOf(PIXELFORMATDESCRIPTOR) ;Size Of This Structure
 pfd\nVersion=1 ;Version Number
 pfd\dwFlags=#PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW ;Format Must Support Window, OpenGL, Double Buffering
 pfd\iPixelType=#PFD_TYPE_RGBA ;Request An RGBA Format
 pfd\cColorBits=bits ;Select Our Color Depth
 pfd\cRedBits=0 ;Color Bits Ignored
 pfd\cRedShift=0
 pfd\cGreenBits=0
 pfd\cGreenShift=0
 pfd\cBlueBits=0
 pfd\cBlueShift=0
 pfd\cAlphaBits=0 ;No Alpha Buffer
 pfd\cAlphaShift=0 ;Shift Bit Ignored
 pfd\cAccumBits=0 ;No Accumulation Buffer
 pfd\cAccumRedBits=0 ;Accumulation Bits Ignored
 pfd\cAccumGreenBits=0
 pfd\cAccumBlueBits=0
 pfd\cAccumAlphaBits=0
 pfd\cDepthBits=16 ;16Bit Z-Buffer (Depth Buffer)
 pfd\cStencilBits=0 ;No Stencil Buffer
 pfd\cAuxBuffers=0 ;No Auxiliary Buffer
 pfd\iLayerType=#PFD_MAIN_PLANE ;Main Drawing Layer
 pfd\bReserved=0 ;Reserved
 pfd\dwLayerMask=0 ;Layer Masks Ignored
 pfd\dwVisibleMask=0
 pfd\dwDamageMask=0
 
 hDC=GetDC_(hWnd)
 If hDC=0 ;Did We Get A Device Context?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Create A GL Device Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 PixelFormat=ChoosePixelFormat_(hDC,pfd)
 If PixelFormat=0 ;Did Windows Find A Matching Pixel Format?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Find A Suitable PixelFormat.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If SetPixelFormat_(hDC,PixelFormat,pfd)=0 ;Are We Able To Set The Pixel Format?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Set The PixelFormat.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 hRC=wglCreateContext_(hDC)
 If hRC=0 ;Are We Able To Get A Rendering Context?
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Create A GL Rendering Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 If wglMakeCurrent_(hDC,hRC)=0 ;Try To Activate The Rendering Context
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Can't Activate The GL Rendering Context.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 ShowWindow_(hWnd,#SW_SHOW) ;Show The Window
 SetForegroundWindow_(hWnd) ;Slightly Higher Priority
 SetFocus_(hWnd) ;Sets Keyboard Focus To The Window
 ReSizeGLScene(width,height) ;Set Up Our Perspective GL Screen
 
 If InitGL()=0 ;Initialize Our Newly Created GL Window
  KillGLWindow() ;Reset The Display
  MessageBox_(#Null,"Initialization Failed.","ERROR",#MB_OK | #MB_ICONEXCLAMATION)
  ProcedureReturn #False
 EndIf
 
 ProcedureReturn #True ;Success
 
EndProcedure

Procedure.l WndProc(hWnd.l,uMsg.l,wParam.l,lParam.l)

 Select uMsg ;Check For Windows Messages
 
  Case #WM_ACTIVATE ;Watch For Window Activate Message
   If HiWord(wParam)=0 ;Check Minimization State
    active=#True ;Program Is Active
   Else
    active=#False ;Program Is No Longer Active
   EndIf
   ProcedureReturn 0 ;Return To The Message Loop
   
  Case #WM_SYSCOMMAND ;Intercept System Commands
   Select wParam ;Check System Calls
    Case #SC_SCREENSAVE ;Screensaver Trying To Start?
     ProcedureReturn 0 ;Prevent From Happening
    Case #SC_MONITORPOWER ;Monitor Trying To Enter Powersave?
     ProcedureReturn 0 ;Prevent From Happening
   EndSelect
   
  Case #WM_CLOSE ;Did We Receive A Close Message?
   PostQuitMessage_(0) ;Send A Quit Message 
   ProcedureReturn 0 ;Jump Back
   
  Case #WM_KEYDOWN ;Is A Key Being Held Down?
   keys(wParam)=#True ;If So, Mark It As TRUE
   ProcedureReturn 0 ;Jump Back
   
  Case #WM_KEYUP ;Has A Key Been Released?
   keys(wParam)=#False ;If So, Mark It As FALSE
   ProcedureReturn 0 ;Jump Back
   
  Case #WM_SIZE ;Resize The OpenGL Window
   ReSizeGLScene(LoWord(lParam),HiWord(lParam)) ;LoWord=Width, HiWord=Height
   ProcedureReturn 0 ;Jump Back
   
 EndSelect
 
 ;Pass All Unhandled Messages To DefWindowProc
 ProcedureReturn DefWindowProc_(hWnd,uMsg,wParam,lParam)
 
EndProcedure

Procedure.l WinMain() ;Main Program

 Protected msg.MSG ;Windows Message Structure
 Protected done.b ;Bool Variable To Exit Loop
 
 ;Ask The User Which Screen Mode They Prefer
 If MessageBox_(#Null,"Would You Like To Run In Fullscreen Mode?","Start FullScreen?",#MB_YESNO | #MB_ICONQUESTION)=#IDNO
  fullscreen=#False ;Windowed Mode
 EndIf
 
 If CreateGLWindow("Multitexturing Example In NeHe's OpenGL Framework",640,480,16,fullscreen)=0 ;Create The Window
  done=#True
  ProcedureReturn 0 ;Quit If Window Was Not Created
 EndIf
 
 While done=#False ;Loop That Runs While done=FALSE
 
  If PeekMessage_(msg,#Null,0,0,#PM_REMOVE) ;Is There A Message Waiting?
  
   If msg\message=#WM_QUIT ;Have We Received A Quit Message?
    done=#True ;If So done=TRUE
   Else ;If Not, Deal With Window Messages
    TranslateMessage_(msg) ;Translate The Message
    DispatchMessage_(msg) ;Dispatch The Message
   EndIf
   
  Else ;If There Are No Messages
  
   ;Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
   If (active And DrawGLScene()=0) Or keys(#VK_ESCAPE) ;Active? Was There A Quit Received?
   
    done=#True ;ESC or DrawGLScene Signalled A Quit
    
   Else ;Not Time To Quit, Update Screen
   
    SwapBuffers_(hDC) ;Swap Buffers (Double Buffering)
    
    If keys(#VK_P) ;Is P Key Being Pressed?
     keys(#VK_P)=#False
     panTextures=(panTextures=0 And 1) ;Toggle Pan Textures
     angle=0 ;Set the angle to Zero
    EndIf
    
    If keys(#VK_R) ;Is R Key Being Pressed?
     keys(#VK_R)=#False
     rotTextures=(rotTextures=0 And 1) ;Toggle Rotate Textures
     angle=0 ;Set the angle to Zero
    EndIf
    
    If keys(#VK_L) ;Is L Key Being Pressed?
     keys(#VK_L)=#False
     light=(light=0 And 1) ;Toggle Lighting
     If light=0 ;If Not Light
      glDisable_(#GL_LIGHTING) ;Disable Lighting
     Else ;Otherwise
      glEnable_(#GL_LIGHTING) ;Enable Lighting
     EndIf
    EndIf
    
    If keys(#VK_PRIOR) ;Is Page Up Being Pressed?
     z-0.02 ;Move Into The Screen
    EndIf
    If keys(#VK_NEXT) ;Is Page Down Being Pressed?
     z+0.02 ;Move Towards The Viewer
    EndIf
    
    If keys(#VK_LEFT) ;Is Left Arrow Being Pressed?
     yrot-0.2 ;Spin Cubes Left
    EndIf
    If keys(#VK_RIGHT) ;Is Right Arrow Being Pressed?
     yrot+0.2 ;Spin Cubes Right
    EndIf
    If keys(#VK_UP) ;Is Up Arrow Being Pressed?
     xrot-0.2 ;Tilt Cubes Up
    EndIf
    If keys(#VK_DOWN) ;Is Down Arrow Being Pressed?
     xrot+0.2 ;Tilt Cubes Down
    EndIf
    
   EndIf
   
   If keys(#VK_F1) ;Is F1 Being Pressed?
    keys(#VK_F1)=#False ;If So Make Key FALSE
    KillGLWindow() ;Kill Our Current Window
    If fullscreen : fullscreen=#False : Else : fullscreen=#True : EndIf ;Toggle Fullscreen / Windowed Mode
    ;Recreate Our OpenGL Window
    If CreateGLWindow("Multitexturing Example In NeHe's OpenGL Framework",640,480,16,fullscreen)=0
     done=#True
     ProcedureReturn 0 ;Quit If Window Was Not Created
    EndIf
   EndIf
   
  EndIf
  
 Wend
 
 ;Shutdown
 KillGLWindow() ;Kill The Window
 End ;Exit The Program
 
EndProcedure

WinMain() ;run the main program

Wladek
User
User
Posts: 98
Joined: Mon Feb 23, 2009 4:01 pm
Location: Poland
Contact:

Thanks

Post by Wladek »

Thanks
User avatar
IceSoft
Addict
Addict
Posts: 1695
Joined: Thu Jun 24, 2004 8:51 am
Location: Germany

Re: Thanks

Post by IceSoft »

Wladek wrote:Thanks
Better late as never ;-)
Belive! C++ version of Puzzle of Mystralia
Bug Planet
<Wrapper>4PB, PB<game>, =QONK=, PetriDish, Movie2Image, PictureManager,...
User avatar
idle
Always Here
Always Here
Posts: 5905
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

True, well it should be thanks, I expect he spent a couple of years porting it!
Post Reply