光照和键盘控制
OpenGL——纹理过滤函数glTexParameteri()
图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),这时就可用glTexParmeteri()函数来确定如何把纹理象素映射成像素.
部分参数功能说明如下:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
GL_TEXTURE_2D: 操作2D纹理.
GL_TEXTURE_WRAP_S: S方向上的贴图模式.
GL_CLAMP: 将纹理坐标限制在0.0,1.0的范围之内.如果超出了会如何呢.不会错误,只是会边缘拉伸填充.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
这里同上,只是它是T方向
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
这是纹理过滤
GL_TEXTURE_MAG_FILTER: 放大过滤
GL_LINEAR: 线性过滤, 使用距离当前渲染像素中心最近的4个纹素加权平均值.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
GL_TEXTURE_MIN_FILTER: 缩小过滤
GL_LINEAR_MIPMAP_NEAREST: 使用GL_NEAREST对最接近当前多边形的解析度的两个层级贴图进行采样,然后用这两个值进行线性插值.
BOOL light; //光源开关
BOOL lp; //L键是否按下
BOOL fp; //F键是否按下
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}; //光源位置
//最后一个参数告诉OpenGL这里指定的坐标就是光源的位置
GLuint filter; //滤波类型
GLuint texture[3]; //存储3种纹理
int LoadGLTextures(){ //载入位图并转换成纹理
int Status = FALSE; //状态指示器
AUX_RGBImageRec* TextureImage[1]; //存储纹理
memset(TextureImage,0,sizeof(void*)*1);
//载入位图,
if(TextureImage[0] = LoadBMP("Data/Create.bmp")){
Status = TRUE; //载入成功
glGenTextures(3,&Texture[0]); //创建纹理,分配一个纹理对象的编号
//创建Nearest滤波贴图
glBindTexture(GL_TETURE_2D,texture[0]); //绑定2D纹理,存储到texture[0]
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[0]->sizeX,TextureImage[0]->sizeY,
0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data); //把一幅图像载入为2D纹理
//创建线性滤波纹理
glBindTexture(GL_TEXTURE_2D,texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
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_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST);
//生成mipmapped纹理,这里使用三种颜色来生成一个2D纹理
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;
}
//在ini InitGL(GLvoid)函数中添加下面的代码
glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient); //设置环境光
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse); //设置漫射光
glLightfv(GL_LIGHT1,GL_POSITION,lightPosition); //设置光源位置
glEnable(GL_LIGHT1); //启用一号光源!!!
int 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);
glRotatef(zrot,0.0f,0.0f,1.0f);
glBindTexture(GL_TEXTURE_2D,texture[filter]); //按下F键,filter会增加
glBegin(GL_QUADS); //开始绘制四边形
//指定光源时必须指定一条法线,法线告诉OpenGL这个多边形的朝向,并指明正反面,法线应指向外侧
//前侧面
glNormal3f(0.0f,0.0f,1.0f); //法线指向观察者
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f,1.0f); //左下角
glTexCoord2d(1.0f,0.0f); glVertex3f(1.0f,-1.0f,1.0f);
glTexCoord2f(1.0f,1.0f); glVertex3f(1.0f,1.0f,1.0f);
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f,1.0f,1.0f);
//后侧面
glNormal3f(0.0f,0.0f,-1.0f); //法线背对观察者
glTexCoord2f(1.0f,0.0f); glVertex3f(-1.0f,-1.0f,-1.0f); //右下角
glTexCoord2f(1.0f,1.0f); glVertex3f(-1.0f,1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); glVertex3f(1.0f,1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); glVertex3f(1.0f,-1.0f,-1.0f);
//顶面
glNormal3f(0.0f,1.0f,0.0f); //法线向上
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f,1.0f,-1.0f); //左上角
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,1.0f,1.0f);
glTexCoord2f(1.0f,0.0f); glVertex3f(1.0f,1.0f,1.0f);
glTexCoord2f(1.0f,1.0f); glVertex3f(1.0f,1.0f,-1.0f);
//底面
glNormal3f(0.0f,-1.0f,0.0f); //法线朝下
glTexCoord2f(1.0f,1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); //不明觉厉?
glTexCoord2f(0.0f,1.0f); glVertex3f(1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f,0.0f); glVertex3f(1.0f,-1.0f,1.0f);
glTexCoord2f(1.0f,0.0f); glVertex3f(-1.0f,-1.0f,1.0f);
//右侧面
glNormal3f(1.0f,0.0f,0.0f); //法线向右
glTexCoord2f(1.0f,0.0f); glVertex3f(1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,1.0f); glVertex3f(1.0f,1.0f,-1.0f);
glTexCoord2f(0.0f,1.0f); glVertex3f(1.0f,1.0f,1.0f);
glTexCoord2f(0.0f,0.0f); glVertex3f(1.0f,-1.0f,1.0f);
//左侧面
glNormal3f(-1.0,0.0f,0.0f); //法线向左
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f,0.0f); glVertex3f(-1.0f,-1.0f,1.0f);
glTexCoord2f(1.0f,1.0f); glVertex3f(-1.0f,1.0f,1.0f);
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f,1.0f,-1.0f);
glEnd(); //四边形绘制结束
xrot += xspeed;
yrot += yspeed;
return TRUE;
}
//WinMain()
SwapBuffers(hDC); //交换缓存
if(keys['L'] && !lp){ //L键被按下且松开了
lp = TRUE;
light = !light;
if(!light){
glDisable(GL_LIGHTING); //禁用光源
}else{
glEnable(GL_LIGHTING); //启用光源
}
}
if(!keys['L']){ //若L键松开了
lp = FALSE;
}
if(keys['F'] && !fp){
fp = TRUE;
filter += 1;
if(filter > 2){
filter = 0;
}
}
if(!keys['F']){
fp = FALSE;
}
if(keys[VK_PRIOR]) { //PageUp按下
z -= 0.02f;
}
if(keys[VK_NEXT]) { //PageDown
z += 0.02f;
}
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;
killGLWindow(); //摧毁当前窗口
fullscreen = !fullscreen;
if(!CreateGLWindow("kai",640,480,16,fullscreen)){
return 0; //无法创建窗口,退出
}
}
killGLWindow(); //销毁窗口
return (msg.wParam); //退出程序