【期末】openGL基础知识+编程题

头文件的使用

若应用程序使用OpenGL核心函数,应包括头文件<gl/gl.h> 
使用GLU库函数,应包括头文件<gl/glu.h> 
使用AUX库函数,应包括头文件<gl/glaux.h> 
使用WGL和Win32应包括头文件<windows.h>

基本程序结构

1.定义窗口

auxInitDisplayMode 定义窗口的特性

void auxInitDisplayMode(Glbitfield mask) //定义窗口的特性,如颜色和缓存区的性质
例如:
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA)
//窗口显示单缓存和RGB(彩色)模式

auxInitPosition 定义窗口在屏幕上的位置和大小

void auxInitPosition(Glint x,Glint y, Glint width, Glint height)定义窗口在屏幕上的位置和大小

auxInitWindow:打开窗口。窗口的标题为字符串titleString

void auxInitWindow(Glbyte *titleString)

2.初始化操作

glClearColor:

glClearColor(0.0,0.0,0.0,0.0);  //将窗口清为黑色
glClear(GL_COLOR_BUFFER_BIT);  //将颜色缓存清为glClearColor命令所设置的颜色,即背景色

glBegin:开始一个绘图操作

当使用 glBegin(GL_POLYGONS) 时,这表示接下来的顶点将构成一个或多个多边形。
使用 glBegin(GL_POINTS) 表示接下来的顶点将被解释为独立的点。

3.观察坐标系

glViewport 设置屏幕上视口大小

void  glViewport (GLint x, Glint y, Glsizei width, Glsizei height)(x, y)指定视口左下角在窗口坐标系中的位置,width和height分别确定矩形视口宽和高,均以像素为单位。

glOrtho:设置投影方式为正交投影(平行投影)

void glOrtho(left, right, bottom, top, near, far)
其取景体积是一个各面均为矩形的六面体,在默认状态为平行正交投影

gluPerspective:设置投影方式为透视投影

void gluPerspective(fovy, aspect, zNear, zFar)

4.多边形绘制

多边形的描述方式如下:

glBegin(GL_POLYGON);
    glVertex*(v0);
    glVertex*(v1);
    ……..
    glVertex*(vn);
glEnd();

其中,*表示glVertex函数的上述任一种组合形式,由多边形顶点v0,v1,…,vn的表示形式而定。注意:多边形顶点应按一定顺序排列(如逆时针)。

5.矩形的绘制

glRect:绘制矩形

void glRect{dfis}(TYPE x1, TYPE y1, TYPE x2, TYPE y2);
void glRect{dfis}v (TYPE *v1, TYPE *v2);

6.坐标变换

glMatrixMode:指定当前的矩阵模式

void  glMatrixMode(Glenum mode); 
决定了随后的矩阵操作(如变换)将应用于哪个矩阵
参数取值:GL_MODELVIEW、GL_PROJECTION或GL_TEXTURE 
默认的选定矩阵为GL_MODELVIEW变换矩阵

glLoadIdentity:重置当前选定的矩阵为单位矩阵

void glLoadIdentity(void);
将当前选定的矩阵重置为单位矩阵。这意味着所有的变换都将被清除,矩阵状态回到起始状态。

glTanslate:平移变化

void glTanslate{fd}(TYPE x, TYPE y, TYPE z); 

glRotate:旋转变换

void glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z); 

glScale:缩放变换

void glScale{fd}( TYPE x, TYPE y, TYPE z); 

7.投影变换

调用投影变换命令前必须先在程序中加入下述语句:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective :透视投影

void  gluPerspective (Gldouble fovy, Gldouble aspect, Gldouble zNear, Gldouble zFar) ; 

glOrtho:正交投影

void  glOrtho (Gldouble left, Gldouble right, Gldouble bottom, Gldouble top, Gldouble near, Gldouble far) ; 

gluOrtho2D:二维图形向二维屏幕的投影

void  gluOrtho2D(Gldouble left, Gldouble right, Gldouble bottom, Gldouble top);
用二维顶点命令绘制的二维物体的z坐标均为零,而gluOrtho2D()命令假定场景中的 z 坐标介于-1.01.0 之间。 

glViewport:视口变换

void  glViewport(GLint x, Glint y, Glsizei width, Glsizei height); 
注意:应该使视口的长宽比与取景体积的长宽比相等,否则会使图像变形

例题:三维空间绘制立方体的程序cube.c

#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);
} 

【期末】openGL基础知识+编程题_第1张图片

8.材质属性:

glMaterialfv:设置物体表面的材质属性

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指定的材质属性的值。

9.Shading模式

glShadeModel:设置着色模式

Void glShadeModel(GLenum mode)
GLenum mode:指定使用的着色模式。可选的模式有:
GL_FLAT:平面着色。
GL_SMOOTH:平滑着色(通常基于Gouraud着色)。

10.光照属性

//光照状态设置
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

11.颜色属性

//颜色状态
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 函数将被不断调用以重绘窗口。
}

纹理映射:

glGenTextures:生成和绑定纹理名称

void glGenTextures(GLsizei n,GLuint *textures);
函数功能:生成纹理名称。
输入参数:参数n为纹理名称的数目,参数textures表示被生成的纹理名称构成的数组。
输出参数:无
返回值:无。

glTexImage2D:定义一个二维纹理图像

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是指向像素数据的指针。
输出参数:无
返回值:无。

glTexParameter:设置纹理参数

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的值。
输出参数:无
返回值:无。

glTexCoord:设置纹理坐标

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为纹理坐标。
输出参数:无
返回值:无。

glTexEnv:设置纹理环境参数

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的值。
输出参数:无
返回值:无。

glTexGen:自动生成纹理坐标

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:深度测试

glClearDepth(1.0f); 
// 启用深度测试
glEnable(GL_DEPTH_TEST); 
// 所作深度测试的类型
glDepthFunc(GL_LEQUAL); 

KillGLWindow:销毁窗口

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;                                                
 }

实例三:给三角形和正方形着色

【期末】openGL基础知识+编程题_第2张图片

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:让对象绕某个轴旋转

glRotatef(Angle,Xvector,Yvector,Zvector)
Angle 通常是个变量,代表对象转过的角度。
 Xvector , Yvector 和 Zvector 三个参数则共同决定旋转轴的方向
glRotatef(rtri,0.0f,1.0f,0.0f); 

实例五:建立3D对象

【期末】openGL基础知识+编程题_第3张图片
【期末】openGL基础知识+编程题_第4张图片
【期末】openGL基础知识+编程题_第5张图片

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; // 继续运行
}

实例六:纹理映射

【期末】openGL基础知识+编程题_第6张图片

//为了引用文件操作函数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;
}

你可能感兴趣的:(笔记,c++)