This shows how to apply sphere environment mapping to quadric objects and a cube.
Press Spacebar to change object, L key for lighting, F key for filters, Arrows to rotate object, Pageup/Pagedown to zoom.
You can get the "BG.bmp", "Reflect.bmp" from the "lesson23.zip" here:
http://nehe.gamedev.net/data/lessons/vc/lesson23.zip
Last edited on 20 Feb 2007.
Code: Select all
;NeHe & TipTup's Environment Mapping Tutorial (Lesson 23)
;http://nehe.gamedev.net and http://www.tiptup.com
;Credits: Nico Gruener, Dreglor, traumatic
;Author: hagibaba
;Date: 27 Jan 2007
;Note: up-to-date with PB v4.02 (Windows)
;Note: requires bitmaps in paths "Data/BG.bmp", "Data/Reflect.bmp"
;Section for standard constants, structures, macros and declarations
XIncludeFile #PB_Compiler_Home+"Examples\Sources - Advanced\OpenGL Cube\OpenGL.pbi" ;include the gl.h constants
;wingdi.h constants
#DM_BITSPERPEL=$40000
#DM_PELSWIDTH=$80000
#DM_PELSHEIGHT=$100000
;winuser.h constants
#CDS_FULLSCREEN=4
#DISP_CHANGE_SUCCESSFUL=0
#SC_MONITORPOWER=$F170
;glu.h constants
#GLU_SMOOTH=100000
#GLU_FLAT=100001
#GLU_NONE=100002
Structure AUX_RGBImageRec ;glaux.h structure
sizeX.l : sizeY.l
Data.l
EndStructure
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
;glaux.lib symbols
!public ___ftoll
!___ftoll dw 0
!public __imp__wsprintfA
!__imp__wsprintfA dw 0
Import "glaux.lib"
CompilerIf #PB_Compiler_Unicode
auxDIBImageLoad.l(filename.s) As "_auxDIBImageLoadW@4" ;loads a 24-bit Windows DIB
CompilerElse
auxDIBImageLoad.l(filename.s) As "_auxDIBImageLoadA@4" ;loads a 24-bit Windows DIB
CompilerEndIf
EndImport
Import "glu32.lib"
gluCylinder(*qobj,baseRadius.d,topRadius.d,height.d,slices.l,stacks.l) ;draws a cylinder
gluDisk(*qobj,innerRadius.d,outerRadius.d,slices.l,loops.l) ;draws a disk
gluPartialDisk(*qobj,innerRadius.d,outerRadius.d,slices.l,loops.l,startAngle.d,sweepAngle.d) ;draws an arc of a disk
gluPerspective(fovy.d,aspect.d,zNear.d,zFar.d) ;sets up a perspective projection matrix
gluSphere(*qobj,radius.d,slices.l,stacks.l) ;draws a sphere
EndImport
Import "opengl32.lib"
glClearDepth(depth.d) ;specifies the clear value for the depth buffer
EndImport
;Start of Lesson 23
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 light.b ;Lighting ON/OFF
Global lp.b ;L Pressed?
Global fp.b ;F Pressed?
Global sp.b ;Spacebar Pressed?
Global part1.l ;Start Of Disc
Global part2.l ;End Of Disc
Global p1.l=0 ;Increase 1
Global p2.l=1 ;Increase 2
Global xrot.f ;X Rotation
Global yrot.f ;Y Rotation
Global xspeed.f ;X Rotation Speed
Global yspeed.f ;Y Rotation Speed
Global z.f=-10.0 ;Depth Into The Screen
Global quadratic.l ;Storage For Our Quadratic Objects
Global Dim LightAmbient.f(4) ;Ambient Light Values
LightAmbient(0)=0.5 ;red
LightAmbient(1)=0.5 ;green
LightAmbient(2)=0.5 ;blue
LightAmbient(3)=1.0 ;alpha
Global Dim LightDiffuse.f(4) ;Diffuse Light Values
LightDiffuse(0)=1.0 ;red
LightDiffuse(1)=1.0 ;green
LightDiffuse(2)=1.0 ;blue
LightDiffuse(3)=1.0 ;alpha
Global Dim LightPosition.f(4) ;Light Position
LightPosition(0)=0.0 ;x
LightPosition(1)=0.0 ;y
LightPosition(2)=2.0 ;z
LightPosition(3)=1.0 ;w
Global filter.l ;Which Filter To Use
Global Dim texture.l(6) ;Storage For 6 Textures (MODIFIED)
Global object.l=1 ;Which Object To Draw
Declare.l WndProc(hWnd.l,uMsg.l,wParam.l,lParam.l) ;Declaration For WndProc
Procedure.l LoadBMP(Filename.s) ;Loads A Bitmap Image
Protected File.l=#Null ;File Handle
If Filename="" ;Make Sure A Filename Was Given
ProcedureReturn #Null ;If Not Return NULL
EndIf
File=ReadFile(#PB_Any,Filename) ;Check To See If The File Exists
If File ;Does The File Exist?
CloseFile(File) ;Close The Handle
ProcedureReturn auxDIBImageLoad(Filename) ;Load The Bitmap And Return A Pointer
EndIf
ProcedureReturn #Null ;If Load Failed Return NULL
EndProcedure
Procedure.l LoadGLTextures() ;Load Bitmaps And Convert To Textures
Protected Status.l=#False ;Status Indicator
Protected Dim *TextureImage.AUX_RGBImageRec(2) ;Create Storage Space For The Texture
Protected loop.l
;Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
*TextureImage(0)=LoadBMP("Data/BG.bmp")
*TextureImage(1)=LoadBMP("Data/Reflect.bmp")
If *TextureImage(0) And *TextureImage(1)
Status=#True ;Set The Status To TRUE
glGenTextures_(6,@texture(0)) ;Create Three Textures
For loop=0 To 2-1
;Create Nearest Filtered Texture
glBindTexture_(#GL_TEXTURE_2D,texture(loop)) ;Gen Tex 0 and 1
glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MAG_FILTER,#GL_NEAREST)
glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MIN_FILTER,#GL_NEAREST)
glTexImage2D_(#GL_TEXTURE_2D,0,3,*TextureImage(loop)\sizeX,*TextureImage(loop)\sizeY,0,#GL_RGB,#GL_UNSIGNED_BYTE,*TextureImage(loop)\Data)
;Create Linear Filtered Texture
glBindTexture_(#GL_TEXTURE_2D,texture(loop+2)) ;Gen Tex 2 and 3
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,*TextureImage(loop)\sizeX,*TextureImage(loop)\sizeY,0,#GL_RGB,#GL_UNSIGNED_BYTE,*TextureImage(loop)\Data)
;Create MipMapped Texture
glBindTexture_(#GL_TEXTURE_2D,texture(loop+4)) ;Gen Tex 4 and 5
glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MAG_FILTER,#GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D,#GL_TEXTURE_MIN_FILTER,#GL_LINEAR_MIPMAP_NEAREST)
gluBuild2DMipmaps_(#GL_TEXTURE_2D,3,*TextureImage(loop)\sizeX,*TextureImage(loop)\sizeY,#GL_RGB,#GL_UNSIGNED_BYTE,*TextureImage(loop)\Data)
Next
EndIf
For loop=0 To 2-1
If *TextureImage(loop) ;If Texture Exists
If *TextureImage(loop)\Data ;If Texture Image Exists
;FreeMemory(*TextureImage(loop)\Data) ;Free The Texture Image Memory
EndIf
;FreeMemory(*TextureImage(loop)) ;Free The Image Structure
EndIf
Next
ProcedureReturn Status ;Return The Status
EndProcedure
Procedure ReSizeGLScene(width.l,height.l) ;Resize And Initialize The GL Window
If height=0 : height=1 : EndIf ;Prevent A Divide By Zero Error
glViewport_(0,0,width,height) ;Reset The Current Viewport
glMatrixMode_(#GL_PROJECTION) ;Select The Projection Matrix
glLoadIdentity_() ;Reset The Projection Matrix
gluPerspective(45.0,Abs(width/height),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.l InitGL() ;All Setup For OpenGL Goes Here
If LoadGLTextures()=0 ;Jump To Texture Loading Routine
ProcedureReturn #False ;If Texture Didn't Load Return FALSE
EndIf
glEnable_(#GL_TEXTURE_2D) ;Enable Texture Mapping
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()) ;Setup The Ambient Light
glLightfv_(#GL_LIGHT1,#GL_DIFFUSE,LightDiffuse()) ;Setup The Diffuse Light
glLightfv_(#GL_LIGHT1,#GL_POSITION,LightPosition()) ;Position The Light
glEnable_(#GL_LIGHT1) ;Enable Light One
quadratic=gluNewQuadric_() ;Create A Pointer To The Quadric Object, returns 0 if failed
gluQuadricNormals_(quadratic,#GLU_SMOOTH) ;Create Smooth Normals
gluQuadricTexture_(quadratic,#GL_TRUE) ;Create Texture Coords
glTexGeni_(#GL_S,#GL_TEXTURE_GEN_MODE,#GL_SPHERE_MAP) ;Set The Texture Generation Mode For S To Sphere Mapping ( NEW )
glTexGeni_(#GL_T,#GL_TEXTURE_GEN_MODE,#GL_SPHERE_MAP) ;Set The Texture Generation Mode For T To Sphere Mapping ( NEW )
ProcedureReturn #True ;Initialization Went OK
EndProcedure
Procedure glDrawCube() ;Draw A Cube
glBegin_(#GL_QUADS) ;Start Drawing Quads
;Front Face
glNormal3f_( 0.0, 0.0, 0.5) ;Normal Facing Towards
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
glNormal3f_( 0.0, 0.0,-0.5) ;Normal Facing Away
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
glNormal3f_( 0.0, 0.5, 0.0) ;Normal Facing Up
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
glNormal3f_( 0.0,-0.5, 0.0) ;Normal Facing Down
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
glNormal3f_( 0.5, 0.0, 0.0) ;Normal Facing Right
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
glNormal3f_(-0.5, 0.0, 0.0) ;Normal Facing Left
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_() ;Done Drawing Quads
EndProcedure
Procedure.l DrawGLScene() ;Here's Where We Do All The Drawing
glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT) ;Clear The Screen And The Depth Buffer
glLoadIdentity_() ;Reset The View
glTranslatef_(0.0,0.0,z) ;Translate Into/Out Of The Screen By z
glEnable_(#GL_TEXTURE_GEN_S) ;Enable Texture Coord Generation For S ( NEW )
glEnable_(#GL_TEXTURE_GEN_T) ;Enable Texture Coord Generation For T ( NEW )
glBindTexture_(#GL_TEXTURE_2D,texture((filter*2)+1)) ;Select The Sphere Map
glPushMatrix_()
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
Select object ;Check object To Find Out What To Draw
Case 0 ;Drawing Object 1
glDrawCube() ;Draw Our Cube
Case 1 ;Drawing Object 2
glTranslatef_(0.0,0.0,-1.5) ;Center The Cylinder
gluCylinder(quadratic,1.0,1.0,3.0,32,32) ;Draw A Cylinder With Radius Of 1 And Height Of 3
Case 2 ;Drawing Object 3
gluSphere(quadratic,1.3,32,32) ;Draw A Sphere With Radius Of 1.3 And 32 Longitude And Latitude Segments
Case 3 ;Drawing Object 4
glTranslatef_(0.0,0.0,-1.5) ;Center The Cone
gluCylinder(quadratic,1.0,0.0,3.0,32,32) ;Draw A Cone With Bottom Radius Of 1 And Height Of 3
EndSelect
glPopMatrix_()
glDisable_(#GL_TEXTURE_GEN_S)
glDisable_(#GL_TEXTURE_GEN_T)
glBindTexture_(#GL_TEXTURE_2D,texture(filter*2)) ;Select The BG Texture ( NEW )
glPushMatrix_()
glTranslatef_(0.0,0.0,-24.0)
glBegin_(#GL_QUADS)
glNormal3f_( 0.0, 0.0, 1.0)
glTexCoord2f_(0.0, 0.0) : glVertex3f_(-13.3,-10.0, 10.0)
glTexCoord2f_(1.0, 0.0) : glVertex3f_( 13.3,-10.0, 10.0)
glTexCoord2f_(1.0, 1.0) : glVertex3f_( 13.3, 10.0, 10.0)
glTexCoord2f_(0.0, 1.0) : glVertex3f_(-13.3, 10.0, 10.0)
glEnd_()
glPopMatrix_()
xrot+xspeed ;Add xspeed To xrot
yrot+yspeed ;Add yspeed To yrot
ProcedureReturn #True ;Keep Going
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
gluDeleteQuadric_(quadratic) ;Delete The Quadratic To Free System Resources
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("NeHe & TipTup's Environment Mapping Tutorial",640,480,16,fullscreen)=0 ;Create The Window
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
Delay(5)
SwapBuffers_(hDC) ;Swap Buffers (Double Buffering)
If keys(#VK_L) And lp=0 ;L Key Being Pressed Not Held?
lp=#True ;lp Becomes TRUE
light=~light & 1 ;Toggle Light TRUE/FALSE
If light=0 ;If Not Light
glDisable_(#GL_LIGHTING) ;Disable Lighting
Else ;Otherwise
glEnable_(#GL_LIGHTING) ;Enable Lighting
EndIf
EndIf
If keys(#VK_L)=0 ;Has L Key Been Released?
lp=#False ;If So, lp Becomes FALSE
EndIf
If keys(#VK_F) And fp=0 ;Is F Key Being Pressed?
fp=#True ;fp Becomes TRUE
filter+1 ;filter Value Increases By One
If filter>2 ;Is Value Greater Than 2?
filter=0 ;If So, Set filter To 0
EndIf
EndIf
If keys(#VK_F)=0 ;Has F Key Been Released?
fp=#False ;If So, fp Becomes FALSE
EndIf
If keys(#VK_PRIOR) ;Is Page Up Being Pressed?
z-0.02 ;If So, Move Into The Screen
EndIf
If keys(#VK_NEXT) ;Is Page Down Being Pressed?
z+0.02 ;If So, Move Towards The Viewer
EndIf
If keys(#VK_UP) And xspeed>-0.5 ;Is Up Arrow Being Pressed?
xspeed-0.01 ;If So, Decrease xspeed
EndIf
If keys(#VK_DOWN) And xspeed<0.5 ;Is Down Arrow Being Pressed?
xspeed+0.01 ;If So, Increase xspeed
EndIf
If keys(#VK_RIGHT) And yspeed<0.5 ;Is Right Arrow Being Pressed?
yspeed+0.01 ;If So, Increase yspeed
EndIf
If keys(#VK_LEFT) And yspeed>-0.5 ;Is Left Arrow Being Pressed?
yspeed-0.01 ;If So, Decrease yspeed
EndIf
If keys(#VK_SPACE) And sp=0 ;Is Spacebar Being Pressed?
sp=#True ;If So, Set sp To TRUE
object+1 ;Cycle Through The Objects
If object>3 ;Is object Greater Than 3?
object=0 ;If So, Set To Zero
EndIf
EndIf
If keys(#VK_SPACE)=0 ;Has The Spacebar Been Released?
sp=#False ;If So, Set sp To FALSE
EndIf
EndIf
If keys(#VK_F1) ;Is F1 Being Pressed?
keys(#VK_F1)=#False ;If So Make Key FALSE
KillGLWindow() ;Kill Our Current Window
fullscreen=~fullscreen & 1 ;Toggle Fullscreen / Windowed Mode
;Recreate Our OpenGL Window
If CreateGLWindow("NeHe & TipTup's Environment Mapping Tutorial",640,480,16,fullscreen)=0
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