【代码都从框架的基础上添加】
纹理:
使用到的函数
auxDIBImageLoadA(char* FileName); //载入位图并返回其指针
glGenTextures(GLsizei n, GLuint *textures) //生成纹理
glBindTexture(GLenum target, GLuint texture ); //将纹理和目标进行绑定
glTexImage2D(GLenum target, GLint level, GLenum internalformat,GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); //根据指定的参数,生成一个2D纹理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //缩小过滤
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); //放大过滤
添加四个全局变量
GLfloat xrot; //x的旋转量
GLfloat yrot; //y的旋转量
GLfloat zrot; //z的旋转量
GLuint texture[1]; //存储一个纹理
在WndProc的定义前加上以下代码
//载入位图
AUX_RGBImageRec* LoadBmp(char* Filename)
{
FILE* File = NULL;
if(!Filename){
return NULL;
}
File = fopen(Filename,"r");
if(File){
fclose(File);
return auxDIBImageLoadA(Filename);
}
return NULL;
}
//载入纹理
bool LoadGLTextures()
{
bool Status = FALSE;
AUX_RGBImageRec* TextureImage[1]; //纹理的存储空间
memset(TextureImage,0,sizeof(void*)*1);
if(TextureImage[0] = LoadBmp("Data/NeHe.bmp")){
Status = true;
glGenTextures(1,&texture[0]); //创建了一个纹理名
glBindTexture(GL_TEXTURE_2D,texture[0]);
glTexImage2D(GL_TEXTURE_2D, //2D纹理
0, //图像的详细程度
3, //图像的成分数(eg:rgb 3)
TextureImage[0]->sizeX, //纹理的宽度
TextureImage[0]->sizeY, //纹理的高度
0, //边框值
GL_RGB, //颜色类型RGB
GL_UNSIGNED_BYTE, //数据类型无符号字节型
TextureImage[0]->data //纹理的数据
);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //比原始纹理小,线形滤波
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //比原始纹理大,线形滤波
}
//释放空间
if(TextureImage[0]){
if(TextureImage[0]->data){
free(TextureImage[0]->data);
}
free(TextureImage[0]);
}
return Status;
}
在initGL()中加上以下代码
if(!LoadGLTextures())
return FALSE;
在DrawGLScene()中加上以下代码
glTranslatef(0.0f,0.0f,-5.0f);
glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);
glBindTexture(GL_TEXTURE_2D,texture[0]);
glBegin(GL_QUADS);
/*front-side*/
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f(-1.0f, 1.0f, 1.0f);
/*back-side*/
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f( 1.0f,-1.0f,-1.0f);
/*top-side*/
glTexCoord2f(0.0f,1.0f); //letf_top
glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); //letf_bottom
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f( 1.0f, 1.0f,-1.0f);
/*bottom-side*/
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f( 1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottoms
glVertex3f(-1.0f,-1.0f, 1.0f);
/*right-side*/
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f( 1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottoms
glVertex3f( 1.0f,-1.0f, 1.0f);
/*left-side*/
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f(-1.0f, 1.0f,-1.0f);
glEnd();
xrot += 0.03f;
yrot += 0.02f;
zrot += 0.04f;
到了这里我们可以看到一个6各面都贴上图片的正方体在旋转。光照,混合(透明)及键盘控制:
使用到的新的函数
int gluBuild2DMipmaps(GLenum target,GLint components,GLint width,GLint height,
GLenumformat,GLenum type,const void *data); //和glTexImage2D(...)功能一样也是生成纹理
添加以下全局变量
<span style="font-family:SimSun;font-size:12px;">bool islight = false; //光源的开/关
bool isblend = false; //透明开/关
bool lp = false; //L键的按下及弹起
bool fp = false; //F键的按下及弹起
bool bp = false; //B键的按下及弹起
GLfloat xrot; //x 轴的偏转角度
GLfloat yrot; //y 轴的偏转角度
GLfloat xspeed; //x 轴的偏转步距
GLfloat yspeed; //y 轴的偏转步距
GLfloat z=-5.0f; //深入屏幕的距离
GLfloat LightAmbient[]={0.5f,0.5f,0.5f,1.0f}; //环境光参数
GLfloat LightDiffuse[]={1.0f,1.0f,1.0f,1.0f}; //漫射光参数
GLfloat LightPosition[]={0.0f,0.0f,2.0f,1.0f,}; //光源的位置
GLuint filter; //滤波的类型
GLuint texture[3]; //3种纹理的存储空间</span>
添加以下代码
AUX_RGBImageRec* LoadBmp(char* Filename)
{
FILE* File = NULL;
if(!Filename){
return NULL;
}
File = fopen(Filename,"r");
if(File){
fclose(File);
return auxDIBImageLoadA(Filename);
}
return NULL;
}
bool LoadGLTextures()
{
bool Status = false;
AUX_RGBImageRec* TextureImage[1];
memset(TextureImage,0,sizeof(void*)*1);
if(TextureImage[0]=LoadBmp("Data/Glass.bmp"))
{
Status = true;
glGenTextures(3,&texture[0]);
//创建Nearest滤波贴图
glBindTexture(GL_TEXTURE_2D,texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,
TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);
//创建Linear滤波贴图
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,TextureImage[0]->sizeX,
TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);
//创建Mipmapped滤波贴图
glBindTexture(GL_TEXTURE_2D,texture[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,TextureImage[0]->sizeX,
TextureImage[0]->sizeY,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);
}
if(TextureImage[0])
{
if(TextureImage[0]->data)
{
free(TextureImage[0]->data);
}
free(TextureImage[0]);
}
return Status;
}
在initGL()的最前面加上以下代码
<span style="white-space:pre"> </span>glColor4f(1.0f,1.0f,1.0f,0.5f);<span style="white-space:pre"> </span>//全亮,半透明
glBlendFunc(GL_SRC_ALPHA,GL_ONE);<span style="white-space:pre"> </span>//基于源像素的Apha通道
if(!LoadGLTextures())
return FALSE;
在initGL()的最后加上以下代码
<span style="white-space:pre"> </span>glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient); //设置环境光
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse); //设置漫射光
glLightfv(GL_LIGHT1,GL_POSITION,LightPosition); //设置光源位置
glEnable(GL_LIGHT1); <span style="white-space:pre"> </span>//启用一号光源
在DrawGLScene()中加入以下代码
int wh_DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,z);
glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glBindTexture(GL_TEXTURE_2D,texture[filter]);
glBegin(GL_QUADS);
/*front-side*/
glNormal3f( 0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f(-1.0f, 1.0f, 1.0f);
/*back-side*/
glNormal3f( 0.0f, 0.0f,-1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f( 1.0f,-1.0f,-1.0f);
/*top-side*/
glNormal3f( 0.0f, 1.0f,0.0f);
glTexCoord2f(0.0f,1.0f); //letf_top
glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); //letf_bottom
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f( 1.0f, 1.0f,-1.0f);
/*bottom-side*/
glNormal3f( 0.0f, -1.0f,0.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f( 1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottoms
glVertex3f(-1.0f,-1.0f, 1.0f);
/*right-side*/
glNormal3f( 1.0f, 0.0f,0.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f( 1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f,0.0f); //left_bottoms
glVertex3f( 1.0f,-1.0f, 1.0f);
/*left-side*/
glNormal3f( -1.0f, 0.0f,0.0f);
glTexCoord2f(0.0f,0.0f); //left_bottom
glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,0.0f); //right_bottom
glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f,1.0f); //right_top
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f,1.0f); //left_top
glVertex3f(-1.0f, 1.0f,-1.0f);
glEnd();
xrot += xspeed;
xrot += yspeed;
return true;
}
在WinMain()结尾处添加以下代码
SwapBuffers(wh_hDC); //交换缓存,双缓存可实现动画转换无闪烁
//"L"
if(wh_keys['L'] && !lp)
{
lp = true;
islight = !islight;
}
if(!islight){
glDisable(GL_LIGHTING);
}else{
glEnable(GL_LIGHTING);
}
if(!wh_keys['L']){
lp = false;
}
//"F"
if(wh_keys['F'] && !fp)
{
fp = true;
filter++;
if(filter>2){
filter = 0;
}
}
if(!wh_keys['F']){
fp = false;
}
//"PageUp"
if(wh_keys[VK_PRIOR]){
z -= 0.02f;
}
//"PageDown"
if(wh_keys[VK_NEXT]){
z += 0.02f;
}
//"Up"
if(wh_keys[VK_UP]){
xspeed -= 0.01f;
}
//"Down"
if(wh_keys[VK_DOWN]){
xspeed += 0.01f;
}
//"Right"
if(wh_keys[VK_RIGHT]){
yspeed -= 0.01f;
}
//"Left"
if(wh_keys[VK_LEFT]){
yspeed += 0.01f;
}
//"B"
if(wh_keys['B'] && !bp)
{
bp = true;
isblend = !isblend;
if(isblend){
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}else{
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
}
if(!wh_keys['B'])
{
bp = false;
}
这里我们可以按下B键可以看见透明的正方体,同时按PageUp or PageDown 可以拉近,拉远目标,上下左右可以调整正方体的旋转速度。按L可以开启光照,如果光照关闭了话,是看不到透明的效果的。按F键可以切换三种不同的滤波效果。【需要指出的是,其中加载纹理的方法不好,因为glaux库过时了,所以在网上我看到一篇文章通过SOIL库来载入纹理 SOIL库加载纹理】