若应用程序使用OpenGL核心函数,应包括头文件<gl/gl.h>
使用GLU库函数,应包括头文件<gl/glu.h>
使用AUX库函数,应包括头文件<gl/glaux.h>
使用WGL和Win32应包括头文件<windows.h>
void auxInitDisplayMode(Glbitfield mask) //定义窗口的特性,如颜色和缓存区的性质
例如:
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA)
//窗口显示单缓存和RGB(彩色)模式
void auxInitPosition(Glint x,Glint y, Glint width, Glint height)定义窗口在屏幕上的位置和大小
void auxInitWindow(Glbyte *titleString)
glClearColor(0.0,0.0,0.0,0.0); //将窗口清为黑色
glClear(GL_COLOR_BUFFER_BIT); //将颜色缓存清为glClearColor命令所设置的颜色,即背景色
当使用 glBegin(GL_POLYGONS) 时,这表示接下来的顶点将构成一个或多个多边形。
使用 glBegin(GL_POINTS) 表示接下来的顶点将被解释为独立的点。
void glViewport (GLint x, Glint y, Glsizei width, Glsizei height):
(x, y)指定视口左下角在窗口坐标系中的位置,width和height分别确定矩形视口宽和高,均以像素为单位。
void glOrtho(left, right, bottom, top, near, far)
其取景体积是一个各面均为矩形的六面体,在默认状态为平行正交投影
void gluPerspective(fovy, aspect, zNear, zFar)
多边形的描述方式如下:
glBegin(GL_POLYGON);
glVertex*(v0);
glVertex*(v1);
……..
glVertex*(vn);
glEnd();
其中,*表示glVertex函数的上述任一种组合形式,由多边形顶点v0,v1,…,vn的表示形式而定。注意:多边形顶点应按一定顺序排列(如逆时针)。
void glRect{dfis}(TYPE x1, TYPE y1, TYPE x2, TYPE y2);
void glRect{dfis}v (TYPE *v1, TYPE *v2);
void glMatrixMode(Glenum mode);
决定了随后的矩阵操作(如变换)将应用于哪个矩阵
参数取值:GL_MODELVIEW、GL_PROJECTION或GL_TEXTURE
默认的选定矩阵为GL_MODELVIEW变换矩阵
void glLoadIdentity(void);
将当前选定的矩阵重置为单位矩阵。这意味着所有的变换都将被清除,矩阵状态回到起始状态。
void glTanslate{fd}(TYPE x, TYPE y, TYPE z);
void glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z);
void glScale{fd}( TYPE x, TYPE y, TYPE z);
调用投影变换命令前必须先在程序中加入下述语句:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
void gluPerspective (Gldouble fovy, Gldouble aspect, Gldouble zNear, Gldouble zFar) ;
void glOrtho (Gldouble left, Gldouble right, Gldouble bottom, Gldouble top, Gldouble near, Gldouble far) ;
void gluOrtho2D(Gldouble left, Gldouble right, Gldouble bottom, Gldouble top);
用二维顶点命令绘制的二维物体的z坐标均为零,而gluOrtho2D()命令假定场景中的 z 坐标介于-1.0和 1.0 之间。
void glViewport(GLint x, Glint y, Glsizei width, Glsizei height);
注意:应该使视口的长宽比与取景体积的长宽比相等,否则会使图像变形
#include
#include
#include
#include
#include
void myinit(void);
void CALLBACK myReshape(int w, int h);
void CALLBACK display(void);
//初始化
void myinit(void)
{
glClearColor(0.0,0.0,0.0,0.0); //将窗口清为黑色
glShadeModel(GL_FLAT); //常量明暗处理方式
}
void CALLBACK display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
//将颜色缓存清为glClearColor命令所设置的颜色,即背景色
glColor3f(1.0,1.0,1.0); //选当前颜色(R,G,B)为白色
glLoadIdentity(); //设置当前矩阵为单位矩阵
glTranslatef(0.0, 0.0, -3.0); //平移变换
glRotatef(45,1.0,1.0,0.0); //旋转变换
glScalef(1.0,2.0,1.0); //缩放变换
auxWireCube(1.0); //绘制立方体
glFlush(); //强制绘图,不驻留缓存
}
void CALLBACK myReshape (int w, int h) //用于窗口改变大小时的处理,与绘图无关
{
glMatrixMode(GL_PROJECTION); //指明当前矩阵操作是针对投影矩阵进行的
glLoadIdentity(); //设置当前矩阵为单位矩阵
gluPerspective(70.0, (GLfloat)w/ (GLfloat)h, 1.5, 40.0); // 投影变换
glMatrixMode(GL_MODELVIEW); // 返回视点-模型矩阵
glViewport(0,0,w,h); //定义视口变换
}
void main(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
//窗口显示单缓存和RGB(彩色)模式
auxInitPosition(0,0,200,200); //大小 x=200、y=200 , (0,0)是屏幕左上点
auxInitWindow(“Perspective 3-D Cubes”); //初始化窗口,参数是标题
myinit();
auxReshapeFunc(myReshape);
auxMainLoop(display);
}
glMaterialfv(GLenum face, GLenum pname, const GLfloat *params)
Face:GL_FRONT, GL_BACK, GL_FRONT_AND_BACK
Pname:GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_SHININESS
参数:
GLenum face:指定哪一面的材质属性将被设置。可用的选项包括:
GL_FRONT:仅设置物体的前面材质。
GL_BACK:仅设置物体的背面材质。
GL_FRONT_AND_BACK:同时设置物体的前面和背面材质。
GLenum pname:指定要设置的材质属性。常用的属性包括:
GL_AMBIENT:环境光颜色。
GL_DIFFUSE:漫反射光颜色。
GL_SPECULAR:镜面反射光颜色。
GL_SHININESS:镜面高光系数,决定高光的亮度和尺寸。
const GLfloat *params:一个指向数组的指针,数组中包含了pname指定的材质属性的值。
Void glShadeModel(GLenum mode)
GLenum mode:指定使用的着色模式。可选的模式有:
GL_FLAT:平面着色。
GL_SMOOTH:平滑着色(通常基于Gouraud着色)。
//光照状态设置
glEnable(GL_LIGHT);
//最大光源数量查询
glGetIntegerv(GL_MAX_LIGHTS);
//光源属性
void glLightfv(GLenum light, GLenum pname, const GLfloat *params);
pname可能是GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION
//光源状态设置
glEnable(GL_LIGHTi),其中i是从0到GL_MAX_LIGHTS
//颜色状态
glEnable(GL_COLOR_MATERIAL)
//设置颜色材料属性
glColorMaterial(GLenum face, GLenum mode)
//设置颜色
glColor3f(r,g,b);
#include
#include
#include
#include
void myinit(void);
void CALLBACK myReshape(int w, int h);
void CALLBACK display(void);
void myinit(void) //初始化
{
glClearColor(0.0,0.0,0.0,0.0); //将窗口清为黑色
Glfloat mat_specular[]={1.0, 1.0, 1.0, 1.0}; //数组中的四个值分别对应红、绿、蓝和alpha(透明度)通道的镜面反射强度。
//这里设置为 {1.0, 1.0, 1.0, 1.0} 意味着对所有颜色光线都有最大强度的镜面反射。
Glfloat mat_shininess={50.0};
Glfloat light_position[] = {1.0, 1.0,1.0,0.0};//0.0表示无穷远光源
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); //设置前面(正面)的材质属性,以反射镜面光。
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); //设置材质的镜面高光属性。
glLightfv(GL_LIGHT0,GL_POSITION,light_position); //设置第一个光源(GL_LIGHT0)的位置或方向。
glEnable(GL_LIGHTING); //启用OpenGL的光照处理。
glEnable(GL_LIGHT0); //启用第一个光源。
glDepthFunc(GL_LESS); //设置深度测试的函数。GL_LESS意味着如果一个像素的深度值小于当前的深度缓冲区的值,它将被绘制。
glEnable(GL_DEPTH_TEST); //启用深度测试。
}
void CALLBACK display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//将颜色缓存清为glClearColor命令所设置的颜色,即背景色
glNormal3f(1.0f, 1.0f, 1.0f); //法线,法线用于确定物体表面与光源方向的关系。
Glfloat ambient[]={0.8f,0.8f,0.8f,1.0f} //环境光颜色数组
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient) //设置全局环境光的强度。
glColor4f(0.2,0.8,1.0,1.0); //选颜色(R,G,B)
auxSolidSphere(1.0); //绘制一个半径为1.0的实心球体。
glFlush(); //强制绘图,不驻留缓存
}
void CALLBACK myReshape (int w, int h) //定义视口变换和投影变换
{
glViewport(0,0,w,h); //设置视口大小和位置。
glMatrixMode(GL_PROJECTION); //切换到投影矩阵模式
glLoadIdentity();
//保证了无论窗口的宽高比如何变化,渲染出的图形都能保持正确的比例和形状。
if(w<=h) //正交投影
glOrtho(-1.5,1.5,-1.5*(GLfoalt)h/(GLfloat)w,1.5*(GLfoalt)h/(GLfloat)w,-10.0,10.0);
else
glOrtho(-1.5*(GLfoalt)h/(GLfloat)w, 1.5*(GLfoalt)h/(GLfloat)w, -1.5, 1.5,-10.0,10.0);
glMatrixMode(GL_MODELVIEW); //将矩阵模式切换回模型视图矩阵,用于设置物体的位置和方向。
glLoadIdentity();
}
/* Mainp Loop
* Open window with initial window size, title bar,
* RGBA display mode, and handle input events.
*/
void main(void)
{
auxI/nitDisplayMode(AUX_SINGLE|AUX_RGBA|AUX_DEPTH);
auxInitPosition(0,0,500,500); //设置窗口的初始位置和大小。这里窗口被放置在屏幕左上角(坐标0,0),窗口大小为500x500像素。
auxInitWindow(“Lighting”); //创建一个窗口,窗口标题为“Lighting”。
myinit();
auxReshapeFunc(myReshape); //当窗口大小改变时,这个函数会被调用。
auxMainLoop(display); //display 函数将被不断调用以重绘窗口。
}
void glGenTextures(GLsizei n,GLuint *textures);
函数功能:生成纹理名称。
输入参数:参数n为纹理名称的数目,参数textures表示被生成的纹理名称构成的数组。
输出参数:无
返回值:无。
void glTexImage2D(GLenum target,GLint level,GLint internalFormat,GLsizei width, GLsizei height,GLint border, GLenum format, GLenum type,const GLvoid *pixels);
函数功能:定义一个二维纹理图像。
输入参数:参数target为纹理类型,只能是GL_TEXTURE_2D,参数level表示多分率图像的级数,参数internalFormat表示纹理中颜色分量的数目,参数width和height表示图像的宽和高,参数border表示图像边界的大小,参数format表示像素数据的格式,参数type表示像素数据的类型,参数pixels是指向像素数据的指针。
输出参数:无
返回值:无。
void glTexParameter{i,f}(GLenum target, GLenum pName,TYPE param);
void glTexParameter{i,f}v(GLenum target, GLenum pName,TYPE *param);
函数功能:设置纹理参数。
输入参数:参数target为纹理类型(GL_TEXTURE_1D, GL_TEXTURE_2D) ,参数pName表示纹理名称(GL_TEXTURE_BORDER_COLOR 、GL_TEXTURE_WRAP_S 、GL_TEXTURE_WRAP_T 、 GL_TEXTURE_MIN_FILTER 、 GL_TEXTURE_MAG_FILTER),参数param表示pName的值。
输出参数:无
返回值:无。
void glTexCoord{1,2,3,4}{d,f,i,s}(TYPE s, TYPE t, TYPE r, TYPE q);
void glTexCoord{1,2,3,4}{d,f,i,s}v(const TYPE *v);
函数功能:设置纹理坐标。
输入参数:参数s,t,r,q为纹理坐标。
输出参数:无
返回值:无。
void glTexEnv{i,f}(GLenum target, GLenum pName,TYPE param);
void glTexEnv{i,f}v(GLenum target, GLenum pName,TYPE *param);
函数功能:设置纹理环境参数。
输入参数:参数target表示纹理环境(GL_TEXTURE_ENV),参数pName纹理环境参数名,参数param表示pName的值。
输出参数:无
返回值:无。
void glTexGen{i,f,d}(GLenum coord, GLenum pName,TYPE param);
void glTexGen{i,f,d}v(GLenum coord, GLenum pName,TYPE *param);
函数功能:自动生成纹理坐标。
输入参数:参数coord表示纹理坐标(GL_S、GL_T、GL_R、GL_Q),参数pName表示纹理坐标生成函数名或函数参数,参数param表示pName的值。
输出参数:无
返回值:无。
glClearDepth(1.0f);
// 启用深度测试
glEnable(GL_DEPTH_TEST);
// 所作深度测试的类型
glDepthFunc(GL_LEQUAL);
GLvoid KillGLWindow(GLvoid)
{
……………………….
}
只在程序退出之前调用
作用是依次释放着色描述表,设备描述表和窗口句柄。
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f); //左移 1.5 单位,并移入屏幕 6.0
glBegin(GL_TRIANGLES); // 绘制三角形
glVertex3f( 0.0f, 1.0f, 0.0f); // 上顶点
glVertex3f(-1.0f,-1.0f, 0.0f); // 左下
glVertex3f( 1.0f,-1.0f, 0.0f); // 右下
glEnd(); // 三角形绘制结束
glTranslatef(3.0f,0.0f,0.0f); // 右移3单位
glBegin(GL_QUADS); // 绘制正方形
glVertex3f(-1.0f, 1.0f, 0.0f); // 左上
glVertex3f( 1.0f, 1.0f, 0.0f); // 右上
glVertex3f( 1.0f,-1.0f, 0.0f); // 左下
glVertex3f(-1.0f,-1.0f, 0.0f); // 右下
glEnd(); // 正方形绘制结束
return TRUE;
}
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
//平滑着色
glColor3f(1.0f,0.0f,0.0f); //参数:红、绿、蓝三色分量,取值范围从0,0f到1.0f
glVertex3f( 0.0f, 1.0f, 0.0f); //设置当前色为红色
glColor3f(0.0f,1.0f,0.0f); // 上顶点
glVertex3f(-1.0f,-1.0f, 0.0f); //设置当前色为绿色
glColor3f(0.0f,0.0f,1.0f); // 左下
glVertex3f( 1.0f,-1.0f, 0.0f); //设置当前色为蓝色
glEnd();
glTranslatef(3.0f,0.0f,0.0f); // 右移3单位
glColor3f(0.5f,0.5f,1.0f); // 一次性将当前色设置为蓝色
//单调着色
glBegin(GL_QUADS); // 绘制正方形
glVertex3f(-1.0f, 1.0f, 0.0f); // 左上
glVertex3f( 1.0f, 1.0f, 0.0f); // 右上
glVertex3f( 1.0f,-1.0f, 0.0f); // 左下
glVertex3f(-1.0f,-1.0f, 0.0f); // 右下
glEnd(); // 正方形绘制结束
return TRUE;
}
bool keys[256];// 用于键盘例程的数组
bool active=TRUE;// 窗口的活动标志,缺省为TRUE
bool fullscreen=TRUE;// 全屏标志缺省设定成全屏模式
// 用于三角形的角度
GLfloat rtri;
// 用于四边形的角度
GLfloat rquad;
int DrawGLScene(GLvoid) // 此过程中包括所有的绘制代码
{
//清除颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // 重置模型观察矩阵
glTranslatef(-1.5f,0.0f,-6.0f); // 左移 1.5 单位,并移入屏幕 6.0
glRotatef(rtri,0.0f,1.0f,0.0f); //绕 Y 轴旋转一个物体
//在屏幕的左面画了一个彩色渐变三角形,并绕着Y轴从左向右旋转。
glBegin(GL_TRIANGLES); // 绘制三角形
glColor3f(1.0f,0.0f,0.0f); //设置当前色为红色
glVertex3f( 0.0f, 1.0f, 0.0f); // 上顶点
glColor3f(0.0f,1.0f,0.0f);//设置当前色为绿色
glVertex3f(-1.0f,-1.0f, 0.0f); // 左下
glColor3f(0.0f,0.0f,1.0f);//设置当前色为蓝色
glVertex3f( 1.0f,-1.0f, 0.0f); // 右下
glEnd(); // 三角形绘制结束
glLoadIdentity(); //重置模型观察矩阵。
glTranslatef(1.5f,0.0f,-6.0f); //重置模型观察矩阵之后,X,Y,Z轴都以复位,调用glTranslate。
// 绕X轴旋转四边形
glRotatef(rquad,1.0f,0.0f,0.0f); //当我们移到新位置后,绕X轴旋转四边形。正方形将上下转动。
//在屏幕的右侧画一个蓝色的正方形。
glColor3f(0.5f,0.5f,1.0f);
glBegin(GL_QUADS); // 绘制正方形
glVertex3f(-1.0f, 1.0f, 0.0f); // 左上
glVertex3f( 1.0f, 1.0f, 0.0f); // 右上
glVertex3f( 1.0f,-1.0f, 0.0f); // 左下
glVertex3f(-1.0f,-1.0f, 0.0f); // 右下
glEnd(); // 正方形绘制结束
rtri+=0.2f; // 增加三角形的旋转变量(新增)
rquad-=0.15f; // 减少四边形的旋转变量(新增)
return TRUE; // 继续运行
}
glRotatef(Angle,Xvector,Yvector,Zvector)
Angle 通常是个变量,代表对象转过的角度。
Xvector , Yvector 和 Zvector 三个参数则共同决定旋转轴的方向
glRotatef(rtri,0.0f,1.0f,0.0f);
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glRotatef(rtri,0.0f,1.0f,0.0f);
//绘制四棱锥
//所有的面都是逆时针次序绘制的
glBegin(GL_TRIANGLES);
//第一个面
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
//第二个面
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
//第三个面
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f, -1.0f);
//第四个面
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
//因为四棱锥只绕着Y轴旋转,永远都看不见底面,因而没有必要添加底面
glEnd();
glLoadIdentity();
glTranslatef(1.5f,0.0f,-7.0f); // 右移
//绘制立方体
glRotatef(rquad,1.0f,1.0f,1.0f); // 在XYZ轴上旋转立方体
//绘制立方体的六个面(四边形)
//所有的四边形都以逆时针次序绘制
glBegin(GL_QUADS); // 开始绘制立方体
//正方体顶面
glColor3f(0.0f,1.0f,0.0f); // 颜色改为绿色
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右上顶点
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左上顶点
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左下顶点
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右下顶点
//底面:
glColor3f(1.0f,0.5f,0.0f); // 颜色改成橙色
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
//立方体的前面
glColor3f(1.0f,0.0f,0.0f); // 颜色改成红色
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右上顶点
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左上顶点
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的左下顶点
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的右下顶点
//立方体的后面
glColor3f(1.0f,1.0f,0.0f); // 颜色改成黄色
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
//立方体的左侧面
glColor3f(0.0f,0.0f,1.0f); // 颜色改成蓝色
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
//立方体的右侧面
glColor3f(1.0f,0.0f,1.0f); // 颜色改成紫罗兰色
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd(); // 立方体绘制结束
rtri+=0.2f; // 增加三角形的旋转变量
rquad-=0.15f; // 减少四边形的旋转变量
return TRUE; // 继续运行
}
//为了引用文件操作函数fopen()
#include // Windows的头文件
#include // 标准输入/输出库的头文件
#include // OpenGL32库的头文件
#include // GLu32库的头文件
#include // GLaux库的头文件
//三个浮点变量使立方体绕X、Y、Z轴旋转
GLfloat xrot; // X 旋转量
GLfloat yrot; // Y 旋转量
GLfloat zrot; // Z 旋转量
//为一个纹理分配存储空间
//如果需要不止一个的纹理,应该将数字1改成所需要的数字
GLuint texture[1]; // 存储一个纹理
//GLuint 是32-bit unsigned integer
// WndProc的定义,WndProc函数负责接收和处理发送到窗口的所有消息
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//加载位图文件
//标准的纹理尺寸
//图像的宽和高必须是2的n次方;
//宽度和高度最小必须是64象素;
//出于兼容性的原因,图像的宽度和高度不应超过256象素。
AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL; // 文件句柄
if (!Filename) // 确保文件名已提供
{
return NULL; // 如果没提供,返回 NULL
}
//检查文件是否存在
File=fopen(Filename,“r”); //尝试打开文件
if (File) // 文件存在么?
{
fclose(File); // 关闭句柄
return auxDIBImageLoad(Filename); //载入纹理位图并返回指向图像文件的指针
}
return NULL; // 如果载入失败,返回 NULL
}
//调用上段代码载入位图,并转换成纹理
int LoadGLTextures()
{
//设置一个Status 的变量, 来跟踪是否能够载入位图以及能否创建纹理。
//Status 缺省设为 FALSE ,表示没有载入。
int Status=FALSE; // 状态指示器
AUX_RGBImageRec *TextureImage[1]; //创建纹理的存储空间
memset(TextureImage,0,sizeof(void *)*1); //清除图像记录,确保其内容为空,将TextureImage清0
if (TextureImage[0]=LoadBMP("Data/NeHe.bmp")) //载入 Data 目录下的 NeHe.bmp 位图文件。如果一切正常,图像数据将存放在TextureImage[0] 中, Status 被设为 TRUE ,然后开始创建纹理。
{
Status=TRUE;
//创建纹理,生成一个纹理名字
glGenTextures(1, &texture[0]);
// 使用来自位图数据生成的典型纹理。将纹理名字 texture[0] 绑定到纹理目标上
glBindTexture(GL_TEXTURE_2D, texture[0]);
//(2D纹理,图像的详细程度,R,G,B三种数据成分,纹理的宽度,纹理的高度,边框宽度,图像数据由红、绿、蓝三色数据组成,组成图像的数据是无符号字节类型,纹理数据的来源)
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_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]); // 释放图像结构。TextureImage[0] 图像结构以保证所有的内存都能释放。
}
//最后返回状态变量。如果一切OK,变量 Status 的值为 TRUE 。否则为 FALSE
return Status;
}
//调用纹理载入子例程 启用2D纹理映射
int InitGL(GLvoid) {
if (!LoadGLTextures()) // 调用纹理载入子例程
{
return FALSE; // 如果未能载入,返回FALSE
}
glEnable(GL_TEXTURE_2D); // 启用纹理映射
glShadeModel(GL_SMOOTH); // 启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景
glClearDepth(1.0f); // 设置深度缓存
glEnable(GL_DEPTH_TEST); // 启用深度测试
glDepthFunc(GL_LEQUAL); // 所作深度测试的类型
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //指定OpenGL的行为建议。
return TRUE; // 初始化 OK
}
//绘制图像
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
//使立方体绕X、Y、Z轴旋转
//旋转多少依赖于变量 xrot , yrot 和 zrot 的值
glRotatef(xrot,1.0f,0.0f,0.0f); // 绕X轴旋转
glRotatef(yrot,0.0f,1.0f,0.0f); // 绕Y轴旋转
glRotatef(zrot,0.0f,0.0f,1.0f); // 绕Z轴旋转
//选择纹理
//改变纹理时,应该绑定新的纹理
//不能在 glBegin() 和 glEnd() 之间绑定纹理,必须在 glBegin() 之前或 glEnd() 之后绑定
glBindTexture(GL_TEXTURE_2D, texture[0]);
//映射规则
//将纹理的右上角映射到四边形的右上角
//纹理的左上角映射到四边形的左上角
//纹理的右下角映射到四边形的右下角
//纹理的左下角映射到四边形的左下角
//纹理映射-前面
glBegin(GL_QUADS);
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);
//纹理映射-后面
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); // 纹理和四边形的左下
//纹理映射-顶面
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); // 纹理和四边形的右上
//纹理映射-底面
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); // 纹理和四边形的右下
//纹理映射-右面
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); // 纹理和四边形的左下
//纹理映射-左面
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+=0.3f; // X 轴旋转
yrot+=0.2f; // Y 轴旋转
zrot+=0.4f; // Z 轴旋转
return true; // 继续运行
}
#include
#include
#include
#include
#include
GLfloat xrot;
GLfloat yrot;
GLfloat zrot;
GLuint texture[1];
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL; // 文件句柄
if (!Filename) // 确保文件名已提供
{
return NULL; // 如果没提供,返回 NULL
}
//检查文件是否存在
File=fopen(Filename,“r”); //尝试打开文件
if (File) // 文件存在么?
{
fclose(File); // 关闭句柄
return auxDIBImageLoad(Filename); //载入纹理位图并返回指向图像文件的指针
}
return NULL; // 如果载入失败,返回 NULL
}
//调用上段代码载入位图,并转换成纹理
int LoadGLTextures()
{
//设置一个Status 的变量, 来跟踪是否能够载入位图以及能否创建纹理。
//Status 缺省设为 FALSE ,表示没有载入。
int Status=FALSE; // 状态指示器
AUX_RGBImageRec *TextureImage[1]; //创建纹理的存储空间
memset(TextureImage,0,sizeof(void *)*1); //清除图像记录,确保其内容为空,将TextureImage清0
if (TextureImage[0]=LoadBMP("Data/NeHe.bmp")) //载入 Data 目录下的 NeHe.bmp 位图文件。如果一切正常,图像数据将存放在TextureImage[0] 中, Status 被设为 TRUE ,然后开始创建纹理。
{
Status=TRUE;
//创建纹理,生成一个纹理名字
glGenTextures(1, &texture[0]);
// 使用来自位图数据生成的典型纹理。将纹理名字 texture[0] 绑定到纹理目标上
glBindTexture(GL_TEXTURE_2D, texture[0]);
//(2D纹理,图像的详细程度,R,G,B三种数据成分,纹理的宽度,纹理的高度,边框宽度,图像数据由红、绿、蓝三色数据组成,组成图像的数据是无符号字节类型,纹理数据的来源)
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_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]); // 释放图像结构。TextureImage[0] 图像结构以保证所有的内存都能释放。
}
//最后返回状态变量。如果一切OK,变量 Status 的值为 TRUE 。否则为 FALSE
return Status;
}
void myinit(void) {
// 光照和纹理映射的初始化设置...
if (!LoadGLTextures()) {
// 如果纹理加载失败
return;
}
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// 设置光照
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {50.0};
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
//绘制图像
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
//光照
glNormal3f(1.0f, 1.0f, 1.0f); //法线,法线用于确定物体表面与光源方向的关系。
Glfloat ambient[]={0.8f,0.8f,0.8f,1.0f} //环境光颜色数组
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient) //设置全局环境光的强度。
//使立方体绕X、Y、Z轴旋转
//旋转多少依赖于变量 xrot , yrot 和 zrot 的值
glRotatef(xrot,1.0f,0.0f,0.0f); // 绕X轴旋转
glRotatef(yrot,0.0f,1.0f,0.0f); // 绕Y轴旋转
glRotatef(zrot,0.0f,0.0f,1.0f); // 绕Z轴旋转
//选择纹理
//改变纹理时,应该绑定新的纹理
//不能在 glBegin() 和 glEnd() 之间绑定纹理,必须在 glBegin() 之前或 glEnd() 之后绑定
glBindTexture(GL_TEXTURE_2D, texture[0]);
//映射规则
//将纹理的右上角映射到四边形的右上角
//纹理的左上角映射到四边形的左上角
//纹理的右下角映射到四边形的右下角
//纹理的左下角映射到四边形的左下角
//纹理映射-前面
glBegin(GL_QUADS);
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);
//纹理映射-后面
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); // 纹理和四边形的左下
//纹理映射-顶面
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); // 纹理和四边形的右上
//纹理映射-底面
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); // 纹理和四边形的右下
//纹理映射-右面
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); // 纹理和四边形的左下
//纹理映射-左面
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+=0.3f; // X 轴旋转
yrot+=0.2f; // Y 轴旋转
zrot+=0.4f; // Z 轴旋转
return true; // 继续运行
}
void CALLBACK myReshape (int w, int h) //定义视口变换和投影变换
{
glViewport(0,0,w,h); //设置视口大小和位置。
glMatrixMode(GL_PROJECTION); //切换到投影矩阵模式
glLoadIdentity();
//保证了无论窗口的宽高比如何变化,渲染出的图形都能保持正确的比例和形状。
if(w<=h) //正交投影
glOrtho(-1.5,1.5,-1.5*(GLfoalt)h/(GLfloat)w,1.5*(GLfoalt)h/(GLfloat)w,-10.0,10.0);
else
glOrtho(-1.5*(GLfoalt)h/(GLfloat)w, 1.5*(GLfoalt)h/(GLfloat)w, -1.5, 1.5,-10.0,10.0);
glMatrixMode(GL_MODELVIEW); //将矩阵模式切换回模型视图矩阵,用于设置物体的位置和方向。
glLoadIdentity();
}
int main(int argc, char** argv) {
// 初始化窗口和OpenGL环境
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA | AUX_DEPTH);
auxInitPosition(0, 0, 500, 500); // 窗口位置和大小
auxInitWindow("OpenGL Textured Lit Cube"); // 窗口标题
myinit(); // 初始化光照和纹理映射
// 设置回调函数
auxReshapeFunc(myReshape); // 视口和投影的设置
auxMainLoop(DrawGLScene); // 主渲染循环
return 0;
}