Lesson07
使用三种映射滤镜给立方体添加纹理:线性映射(LINEAR),NEAREST映射,MipMap映射;三者的效果渐增,处理速度递减。
添加通过键盘控制立方体的旋转速度,距离屏幕的距离和映射方法的选择。
在模型中添加光照:环境光(Ambient)和散射光(Diffuse),通过键盘来打开和关闭光照。
创建纹理:
//
all setup for OpenGL goes here
bool InitGL(GLvoid)
{
if ( ! CreateTextures(_T( " Data/CrateSmall.bmp " )))
return false ;
glEnable(GL_TEXTURE_2D);
// enable smooth shading
glShadeModel(GL_SMOOTH);
// black background
glClearColor( 0.0f , 0.0f , 0.0f , 0.5f );
// setup the depth buffer
glClearDepth( 1.0f );
// enable depth testing
glEnable(GL_DEPTH_TEST);
// the type of depth test to do
glDepthFunc(GL_LEQUAL);
// really nice perspective calculation
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
// Set up the lighting
// set the amount of ambient light that light1 will give off
glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient);
// set the amount of diffues light that light1 will give off
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse);
// set the position of the light
glLightfv(GL_LIGHT1,GL_POSITION,LightPosition);
// Enable the light but it does not start work until GL_LIGHTING is enabled
glEnable(GL_LIGHT1);
return true ;
}
bool InitGL(GLvoid)
{
if ( ! CreateTextures(_T( " Data/CrateSmall.bmp " )))
return false ;
glEnable(GL_TEXTURE_2D);
// enable smooth shading
glShadeModel(GL_SMOOTH);
// black background
glClearColor( 0.0f , 0.0f , 0.0f , 0.5f );
// setup the depth buffer
glClearDepth( 1.0f );
// enable depth testing
glEnable(GL_DEPTH_TEST);
// the type of depth test to do
glDepthFunc(GL_LEQUAL);
// really nice perspective calculation
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
// Set up the lighting
// set the amount of ambient light that light1 will give off
glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient);
// set the amount of diffues light that light1 will give off
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse);
// set the position of the light
glLightfv(GL_LIGHT1,GL_POSITION,LightPosition);
// Enable the light but it does not start work until GL_LIGHTING is enabled
glEnable(GL_LIGHT1);
return true ;
}
在创建纹理时,开始使用的图片是256×256大小的,运行时总是在glTexImage2D()这个函数出出现越界访问错误,分析一下越界信息,发现程序要访问BMP.bmBits[256][256]处的值,这当然越界,可是为什么呢?无奈之下,把图片缩小为128×128的以后,程序就可以正常运行,晕!查看有关glTexImage2D()的函数,纹理大小都只要no more than 256就可以,为什么,自己的程序就不能使用256的?一直没有搞懂,如果那位高手,知道希望多多指教,谢谢!
加载纹理:
bool
CreateTextures(LPTSTR szFileName)
//
Creates Texture From A Bitmap File
{
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure
glGenTextures( 3 , & texture[ 0 ]); // Create The Texture
hBMP = (HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0 , 0 , LR_CREATEDIBSECTION | LR_LOADFROMFILE );
if ( ! hBMP) // Does The Bitmap Exist?
return false ; // If Not Return False
GetObject(hBMP, sizeof (BMP), & BMP); // Get The Object
// hBMP: Handle To Graphics Object
// sizeof(BMP): Size Of Buffer For Object Information
// &BMP: Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT, 4 ); // Pixel Storage Mode (Word Alignment / 4 Bytes)
// Typical Texture Generation Using Data From The Bitmap
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[ 0 ]); // Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Linear Min Filter
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Linear Mag Filter
glTexImage2D(GL_TEXTURE_2D, 0 , 3 , BMP.bmWidth, BMP.bmHeight, 0 , GL_RGB, GL_UNSIGNED_BYTE, BMP.bmBits);
// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D,texture[ 1 ]);
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.bmWidth,BMP.bmHeight, 0 ,GL_RGB,GL_UNSIGNED_BYTE,BMP.bmBits);
// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D,texture[ 2 ]);
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 ,BMP.bmWidth,BMP.bmHeight,GL_RGB,GL_UNSIGNED_BYTE,BMP.bmBits);
DeleteObject(hBMP); // Delete The Object
return true ; // Loading Was Successful
}
{
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure
glGenTextures( 3 , & texture[ 0 ]); // Create The Texture
hBMP = (HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0 , 0 , LR_CREATEDIBSECTION | LR_LOADFROMFILE );
if ( ! hBMP) // Does The Bitmap Exist?
return false ; // If Not Return False
GetObject(hBMP, sizeof (BMP), & BMP); // Get The Object
// hBMP: Handle To Graphics Object
// sizeof(BMP): Size Of Buffer For Object Information
// &BMP: Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT, 4 ); // Pixel Storage Mode (Word Alignment / 4 Bytes)
// Typical Texture Generation Using Data From The Bitmap
// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[ 0 ]); // Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Linear Min Filter
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Linear Mag Filter
glTexImage2D(GL_TEXTURE_2D, 0 , 3 , BMP.bmWidth, BMP.bmHeight, 0 , GL_RGB, GL_UNSIGNED_BYTE, BMP.bmBits);
// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D,texture[ 1 ]);
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.bmWidth,BMP.bmHeight, 0 ,GL_RGB,GL_UNSIGNED_BYTE,BMP.bmBits);
// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D,texture[ 2 ]);
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 ,BMP.bmWidth,BMP.bmHeight,GL_RGB,GL_UNSIGNED_BYTE,BMP.bmBits);
DeleteObject(hBMP); // Delete The Object
return true ; // Loading Was Successful
}
显示立方体:
//
here we do all the drawings
bool DrawGLScene(GLvoid)
{
// clear the screen and the depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// reset the current modelview matrix
glLoadIdentity();
// position and rotate the texture mapped cube
glTranslatef( 0.0f , 0.0f ,z);
glRotatef(xrot, 1.0f , 0.0f , 0.0f );
glRotatef(yrot, 0.0f , 1.0f , 0.0f );
// bind texture to the cube
glBindTexture(GL_TEXTURE_2D,texture[filter]);
glBegin(GL_QUADS);
// Front Face
glNormal3f( 0.0f , 0.0f , 1.0f ); // Normal Pointing Towards Viewer
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 1.0f ); // Point 1 (Front)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 1.0f ); // Point 2 (Front)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , 1.0f ); // Point 3 (Front)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , 1.0f ); // Point 4 (Front)
// Back Face
glNormal3f( 0.0f , 0.0f , - 1.0f ); // Normal Pointing Away From Viewer
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , - 1.0f ); // Point 1 (Back)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , - 1.0f ); // Point 2 (Back)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , - 1.0f ); // Point 3 (Back)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , - 1.0f ); // Point 4 (Back)
// Top Face
glNormal3f( 0.0f , 1.0f , 0.0f ); // Normal Pointing Up
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , - 1.0f ); // Point 1 (Top)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( - 1.0f , 1.0f , 1.0f ); // Point 2 (Top)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( 1.0f , 1.0f , 1.0f ); // Point 3 (Top)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , - 1.0f ); // Point 4 (Top)
// Bottom Face
glNormal3f( 0.0f , - 1.0f , 0.0f ); // Normal Pointing Down
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( - 1.0f , - 1.0f , - 1.0f ); // Point 1 (Bottom)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( 1.0f , - 1.0f , - 1.0f ); // Point 2 (Bottom)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 1.0f ); // Point 3 (Bottom)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 1.0f ); // Point 4 (Bottom)
// Right face
glNormal3f( 1.0f , 0.0f , 0.0f ); // Normal Pointing Right
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , - 1.0f ); // Point 1 (Right)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , - 1.0f ); // Point 2 (Right)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , 1.0f ); // Point 3 (Right)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 1.0f ); // Point 4 (Right)
// Left Face
glNormal3f( - 1.0f , 0.0f , 0.0f ); // Normal Pointing Left
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , - 1.0f ); // Point 1 (Left)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 1.0f ); // Point 2 (Left)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , 1.0f ); // Point 3 (Left)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , - 1.0f ); // Point 4 (Left)
glEnd();
// increase the rotation angle
xrot += xspeed;
yrot += yspeed;
return true ;
}
bool DrawGLScene(GLvoid)
{
// clear the screen and the depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// reset the current modelview matrix
glLoadIdentity();
// position and rotate the texture mapped cube
glTranslatef( 0.0f , 0.0f ,z);
glRotatef(xrot, 1.0f , 0.0f , 0.0f );
glRotatef(yrot, 0.0f , 1.0f , 0.0f );
// bind texture to the cube
glBindTexture(GL_TEXTURE_2D,texture[filter]);
glBegin(GL_QUADS);
// Front Face
glNormal3f( 0.0f , 0.0f , 1.0f ); // Normal Pointing Towards Viewer
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 1.0f ); // Point 1 (Front)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 1.0f ); // Point 2 (Front)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , 1.0f ); // Point 3 (Front)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , 1.0f ); // Point 4 (Front)
// Back Face
glNormal3f( 0.0f , 0.0f , - 1.0f ); // Normal Pointing Away From Viewer
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , - 1.0f ); // Point 1 (Back)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , - 1.0f ); // Point 2 (Back)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , - 1.0f ); // Point 3 (Back)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , - 1.0f ); // Point 4 (Back)
// Top Face
glNormal3f( 0.0f , 1.0f , 0.0f ); // Normal Pointing Up
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , - 1.0f ); // Point 1 (Top)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( - 1.0f , 1.0f , 1.0f ); // Point 2 (Top)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( 1.0f , 1.0f , 1.0f ); // Point 3 (Top)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , - 1.0f ); // Point 4 (Top)
// Bottom Face
glNormal3f( 0.0f , - 1.0f , 0.0f ); // Normal Pointing Down
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( - 1.0f , - 1.0f , - 1.0f ); // Point 1 (Bottom)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( 1.0f , - 1.0f , - 1.0f ); // Point 2 (Bottom)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 1.0f ); // Point 3 (Bottom)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 1.0f ); // Point 4 (Bottom)
// Right face
glNormal3f( 1.0f , 0.0f , 0.0f ); // Normal Pointing Right
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , - 1.0f ); // Point 1 (Right)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , - 1.0f ); // Point 2 (Right)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( 1.0f , 1.0f , 1.0f ); // Point 3 (Right)
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( 1.0f , - 1.0f , 1.0f ); // Point 4 (Right)
// Left Face
glNormal3f( - 1.0f , 0.0f , 0.0f ); // Normal Pointing Left
glTexCoord2f( 0.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , - 1.0f ); // Point 1 (Left)
glTexCoord2f( 1.0f , 0.0f ); glVertex3f( - 1.0f , - 1.0f , 1.0f ); // Point 2 (Left)
glTexCoord2f( 1.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , 1.0f ); // Point 3 (Left)
glTexCoord2f( 0.0f , 1.0f ); glVertex3f( - 1.0f , 1.0f , - 1.0f ); // Point 4 (Left)
glEnd();
// increase the rotation angle
xrot += xspeed;
yrot += yspeed;
return true ;
}
处理键盘响应:
///
/win32 functions
// the entry point of our windows application
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
bool done = false ;
bool vkF1 = false ;
if ( ! CreateGLWindow(_T( " Lesson01 " ), 640 , 480 , 16 ,fullscreen))
{
return 0 ;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LESSON01));
while ( ! done)
{
if (PeekMessage( & msg,NULL, 0 , 0 ,PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
if (vkF1)
vkF1 = false ;
else
done = true ;
}
else
{
TranslateMessage( & msg);
DispatchMessage( & msg);
}
} else
{
if (active)
{
if (keys[VK_ESCAPE])
{
keys[VK_ESCAPE] = false ;
done = true ;
} else
{
DrawGLScene();
SwapBuffers(hDC);
// use lp to avoid when you hold key 'L' that light will change from on to off and off to on all the time during holding
if (keys[ ' L ' ] && ! lp)
{
lp = true ;
light =! light;
if ( ! light)
{
glDisable(GL_LIGHTING);
} else
{
glEnable(GL_LIGHTING);
}
}
if ( ! keys[ ' L ' ])
{
lp = false ;
}
// the same reason for fp
if (keys[ ' F ' ] && ! fp)
{
fp = true ;
filter += 1 ;
if (filter > 2 )filter = 0 ;
}
if ( ! keys[ ' F ' ])
{
fp = false ;
}
// if 'Page Up' pressed,move into the screen
if (keys[VK_PRIOR])
{
z -= 0.02f ;
}
// if 'Page down' pressed ,move near the user
if (keys[VK_NEXT])
{
z += 0.02f ;
}
// checking the arrow keys
if (keys[VK_UP])
xspeed -= 0.01f ;
if (keys[VK_DOWN])
xspeed += 0.01f ;
if (keys[VK_RIGHT])
yspeed += 0.01f ;
if (keys[VK_LEFT])
yspeed -= 0.01f ;
}
}
if (keys[VK_F1])
{
keys[VK_F1] = false ;
vkF1 = true ;
KillGLWindow();
fullscreen =! fullscreen;
if ( ! CreateGLWindow(_T( " Textures,Lighting & Keyboard Tutorial " ), 640 , 480 , 16 ,fullscreen))
{
return 0 ;
}
}
}
}
KillGLWindow();
return (msg.wParam);
}
// the entry point of our windows application
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
bool done = false ;
bool vkF1 = false ;
if ( ! CreateGLWindow(_T( " Lesson01 " ), 640 , 480 , 16 ,fullscreen))
{
return 0 ;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LESSON01));
while ( ! done)
{
if (PeekMessage( & msg,NULL, 0 , 0 ,PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
if (vkF1)
vkF1 = false ;
else
done = true ;
}
else
{
TranslateMessage( & msg);
DispatchMessage( & msg);
}
} else
{
if (active)
{
if (keys[VK_ESCAPE])
{
keys[VK_ESCAPE] = false ;
done = true ;
} else
{
DrawGLScene();
SwapBuffers(hDC);
// use lp to avoid when you hold key 'L' that light will change from on to off and off to on all the time during holding
if (keys[ ' L ' ] && ! lp)
{
lp = true ;
light =! light;
if ( ! light)
{
glDisable(GL_LIGHTING);
} else
{
glEnable(GL_LIGHTING);
}
}
if ( ! keys[ ' L ' ])
{
lp = false ;
}
// the same reason for fp
if (keys[ ' F ' ] && ! fp)
{
fp = true ;
filter += 1 ;
if (filter > 2 )filter = 0 ;
}
if ( ! keys[ ' F ' ])
{
fp = false ;
}
// if 'Page Up' pressed,move into the screen
if (keys[VK_PRIOR])
{
z -= 0.02f ;
}
// if 'Page down' pressed ,move near the user
if (keys[VK_NEXT])
{
z += 0.02f ;
}
// checking the arrow keys
if (keys[VK_UP])
xspeed -= 0.01f ;
if (keys[VK_DOWN])
xspeed += 0.01f ;
if (keys[VK_RIGHT])
yspeed += 0.01f ;
if (keys[VK_LEFT])
yspeed -= 0.01f ;
}
}
if (keys[VK_F1])
{
keys[VK_F1] = false ;
vkF1 = true ;
KillGLWindow();
fullscreen =! fullscreen;
if ( ! CreateGLWindow(_T( " Textures,Lighting & Keyboard Tutorial " ), 640 , 480 , 16 ,fullscreen))
{
return 0 ;
}
}
}
}
KillGLWindow();
return (msg.wParam);
}
全部源码:Lesson07.rar