资源描述
计算机 学院 计算机科学与技术 专业 班 学号
姓名 协作者 教师评定
实验三 光照和纹理技术
1、 实验目的与要求
1. 理解并编程实现场景光照和纹理技术;
2. 建立实验的场景模型-一个六面体盒子;
3. 通过控制光源亮度、位置、方向等特性,实现不同光照效果。要求熟悉OpenGL中光源定义、顶点法向量计算、材质属性设置等函数。
4. 掌握OpenGL中二维颜色纹理技术的应用,熟悉OpenGL中相应纹理函数的使用,给六面体盒子贴上纹理。
2、 实验方案
1. 实验1:
² 把bmp格式的图片载入,并且转换为纹理。
² 利用三维坐标,用点确定面的方式,建立六面体。
² 在六面体的六个面上固定好纹理的载入点,然后载入纹理。
² 设置六面体旋转,沿X,Y,Z轴旋转。
2. 实验2:
² 在实验1的基础上加上光效果
² 设置光源亮度,设置方向,设置光源位置,在这里设置光源的位置是360度转动的。
² 材质属性设置,设置了反光等特性
3、 实验结果和数据处理
1. 实验1的实验结果:
² 程序代码如下:
#pragma comment(lib, "glaux.lib")
#include <gl\glaux.h>
#include <gl\glut.h>
GLuint g_texture = 0;
GLfloat xrot =0;
GLfloat yrot =0;
GLfloat zrot =0; // Keep Going
//绘制一个立方体
int DrawCube(void)
{
glBindTexture(GL_TEXTURE_2D, g_texture); //使用贴图纹理
glPushMatrix(); //压入变换矩阵
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轴旋转,这里zrot是角度制的度数。
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();
glPopMatrix(); //弹出变换矩阵
return 1;
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚颜色数据和深度数据(清屏)
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f);
DrawCube();
glutSwapBuffers(); //交换缓冲区。显示图形
}
//载入一个.bmp格式的贴图纹理
int LoadGLTextures(GLuint& unTexture, const char* chFileName)
{
AUX_RGBImageRec *TextureImage; //保存贴图数据的指针
TextureImage = auxDIBImageLoad("android.bmp"); //载入贴图数据
glGenTextures(1, &unTexture); // 创建一个纹理,unTexture
glBindTexture(GL_TEXTURE_2D, unTexture); //绑定纹理,然后对该纹理区添加纹理数据
//设置纹理的信息,
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //设置滤波为线性滤波
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //线性滤波
if (TextureImage) //释放资源
{
if (TextureImage->data)
{
free(TextureImage->data);
}
free(TextureImage);
}
return 1;
}
//初始化
void init (void)
{
glClearColor (0.0, 0.0, 0.0, 0.0); //清理颜色,为黑色,(也可认为是背景颜色)
glCullFace(GL_BACK); //背面裁剪(背面不可见)
glEnable(GL_CULL_FACE); //启用裁剪
glEnable(GL_TEXTURE_2D);
LoadGLTextures(g_texture, "android.bmp"); //载入纹理贴图
}
//当窗口大小改变时,会调用这个函数
void reshape(GLsizei w,GLsizei h)
{
//这里小说明一下:矩阵模式是不同的,他们各自有一个矩阵。投影相关
//只能用投影矩阵。(只是目前情况下哦,等我学多了可能就知道为什么了。)
glViewport(0,0,w,h); //设置视口
glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影变换矩阵,
glLoadIdentity(); //变为单位矩阵
gluPerspective(60, (GLfloat)w / h, 0, 1000); //设置投影矩阵
glMatrixMode(GL_MODELVIEW); //设置矩阵模式为视图矩阵(模型)
glLoadIdentity(); //变为单位矩阵
}
//闲置函数,当主循环空闲时就会调用这个函数
void MyIdle(void)
{
Sleep(10);
xrot+=0.3f; //增加旋转的角度。
yrot+=0.2f;
zrot+=0.4f;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); //Opnegl初始化
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA); //设置显示模式为双缓冲,RGEBA
glutInitWindowSize (800, 600); //窗口大小
glutInitWindowPosition (100, 100); //窗口位置
glutCreateWindow ("hello"); //创建一个标题为hello的窗口
init (); //初始化资源,这里一定要在创建窗口以后,不然会无效。
glutDisplayFunc(display); //窗口大小改变时的回调
glutReshapeFunc(reshape); //绘制图形时的回调
glutIdleFunc(MyIdle);
glutMainLoop(); //主循环。
return 0;
}
² 实验结果截图:
2. 实验2的实验结果:
² 程序代码如下:
#pragma comment(lib, "glaux.lib")
#include "gl\glaux.h"
#include <gl\glut.h>
float yRot = 0;
unsigned int nPre = 0;
GLfloat light_position[4] = {0,0,0,1}; //光位置
GLfloat light_diffuse[4] = {1,0,1,1}; //光的漫反色
GLfloat light_direction[4] = {-1, -2, -1, 1}; //光源聚光灯方向
GLfloat light_change[3] = {3,3,-1}; //光源移动位置。
GLuint g_texture = 0;
GLfloat xrot =0;
GLfloat yrot =0;
GLfloat zrot =0; // Keep Going
//绘制一个立方体
int DrawCube(void)
{
glBindTexture(GL_TEXTURE_2D, g_texture); //使用贴图纹理
glPushMatrix(); //压入变换矩阵
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轴旋转,这里zrot是角度制的度数。
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();
glPopMatrix(); //弹出变换矩阵
return 1;
}
//载入一个.bmp格式的贴图纹理
int LoadGLTextures(GLuint& unTexture, const char* chFileName)
{
AUX_RGBImageRec *TextureImage; //保存贴图数据的指针
TextureImage = auxDIBImageLoad("android.bmp"); //载入贴图数据
glGenTextures(1, &unTexture); // 创建一个纹理,unTexture
glBindTexture(GL_TEXTURE_2D, unTexture); //绑定纹理,然后对该纹理区添加纹理数据
//设置纹理的信息,
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //设置滤波为线性滤波
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //线性滤波
if (TextureImage) //释放资源
{
if (TextureImage->data)
{
free(TextureImage->data);
}
free(TextureImage);
}
return 1;
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚颜色数据和深度数据(清屏)
glColor3f(1.0,1.0,1.0);
glLoadIdentity(); //初始变换矩阵为单位矩阵
glTranslated(0,-1,-5); //平移0,0,-5向Z负方向平移5个单位
glPushMatrix(); //压缩矩阵,设定光源的位置
glDisable(GL_LIGHTING);
glRotatef(yRot, 0, 1, 0); //光源的旋转
glTranslatef(light_change[0],light_change[1],light_change[2]); //光源的位置
glTranslatef(light_position[0], light_position[1],light_position[2]); //光源位置
glutSolidSphere(0.1, 4,4);//利用库函数绘制一个半径为1的球体。表示光源在这里
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glPopMatrix();
light_direction[0] = -light_change[0];
light_direction[1] = -light_change[1];
light_direction[2] = -light_change[2];
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glPopMatrix(); //光源设置完毕
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚颜色数据和深度数据(清屏)
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f);
DrawCube(); //弹出矩阵。
glutSwapBuffers(); //交换缓冲区。显示图形
}
//初始化
void init (void)
{
glClearColor (0.5, 0.5, 0.5, 0.0); //清理颜色,为黑色,(也可认为是背景颜色)
GLfloat light_param[] = { 1, 1, 1, 1.0 }; //初始化光参数。
//glLightfv(GL_LIGHT0, GL_AMBIENT, light_param); //设置光为环境光。
//glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); //设置聚光的范围为45度。
glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,2.0); //设置聚光灯的聚光强度。
glMaterialfv(GL_FRONT, GL_SPECULAR, light_param); //设置材质的漫反射属性
//glMaterialfv(GL_FRONT, GL_AMBIENT, light_param); //设置材质的环境属性
glMaterialf(GL_FRONT, GL_SHININESS, 64); //设置材质的高光属性
glEnable(GL_LIGHTING); //启动光照
glEnable(GL_LIGHT0); //启动GL_LIGHTO光
glCullFace(GL_BACK); //剔除背面
glEnable(GL_CULL_FACE); //启动剔除
glDepthFunc(GL_LEQUAL); //深度检测为小于等于
glEnable(GL_DEPTH_TEST); //启动深度检测
glFrontFace(GL_CCW); //定义逆时针为正面
glClearColor (0.0, 0.0, 0.0, 0.0); //清理颜色,为黑色,(也可认为是背景颜色)
glCullFace(GL_BACK); //背面裁剪(背面不可见)
glEnable(GL_CULL_FACE); //启用裁剪
glEnable(GL_TEXTURE_2D);
LoadGLTextures(g_texture, "android.bmp"); //载入纹理贴图
}
//当窗口大小改变时,会调用这个函数
void reshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h); //设置视口
glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影变换矩阵,
glLoadIdentity(); //变为单位矩阵
gluPerspective(60, (GLfloat)w / h, 0, 1000); //设置投影矩阵
glMatrixMode(GL_MODELVIEW); //设置矩阵模式为视图矩阵(模型)
glLoadIdentity(); //变为单位矩阵
}
void Keyboard(unsigned char key, int x, int y)
{
}
//闲置函数,当主循环空闲时就会调用这个函数
void MyIdle(void)
{
unsigned int nNow = ::GetTickCount();
float delt = nNow - nPre;
if (delt > 100)
{
nPre = nNow;
yRot += 0.1 * delt; //旋转角度
/**//*light_diffuse[0] = (rand() % 255) / 255.0;//太花不用了。
light_diffuse[1] = (rand() % 255) / 255.0;
light_diffuse[2] = (rand() % 255) / 255.0;*/
glutPostRedisplay();
}
Sleep(10);
xrot+=0.3f; //增加旋转的角度。
yrot+=0.2f;
zrot+=0.4f;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); //Opnegl初始化
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA); //设置显示模式为双缓冲,RGEBA
glutInitWindowSize (800, 600); //窗口大小
glutInitWindowPosition (100, 100); //窗口位置
glutCreateWindow ("hello"); //创建一个标题为hello的窗口
init (); //初始化资源,这里一定要在创建窗口以后,不然会无效。
glutDisplayFunc(display); //窗口大小改变时的回调
glutReshapeFunc(reshape); //绘制图形时的回调
glutKeyboardFunc(Keyboard);
glutIdleFunc(MyIdle);
glutMainLoop(); //主循环。
return 0;
}
² 实验结果截图如下:
11
展开阅读全文