【实验目的】
1. 学习了解真实感图形绘制相关函数。
2. 学习了解真实感图形绘制流程。
【实验原理】
【实验题目】
1. 练习OpenGL中加光照:给chap10-1.cpp中的函数加注释并运行结果。
#include <windows.h>
#include <gl/glut.h>
// 设置材质和光源属性
void Initial(void)
{
// 定义材质属性
GLfloat mat_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat mat_shininess[] = { 50.0f };
// 定义光源属性
GLfloat light0_diffuse[] = { 0.0f, 0.0f, 1.0f, 1.0f }; // 漫反射的蓝色点光源
GLfloat light0_position[] = { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat light1_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat light1_diffuse[] = { 1.0f, 0.0f, 0.0f, 1.0f }; // 红色聚光光源
GLfloat light1_specular[] = { 1.0f, 0.6f, 0.6f, 1.0f };
GLfloat light1_position[] = { -3.0f, -3.0f, 3.0f, 1.0f };
GLfloat spot_direction[] = { 1.0f, 1.0f, -1.0f };
// 设置材质属性
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
// 设置光源属性,light0为漫反射的蓝色点光源
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
//light1为红色聚光光源
glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 30.0);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
// 启用光照和深度测试
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
// 窗口大小变化时的回调函数
void ChangeSize(GLsizei w, GLsizei h)
{
if (h == 0) h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.5f, 5.5f, -5.5f * h / w, 5.5f * h / w, -10.0f, 10.0f);
else
glOrtho(-5.5f * w / h, 5.5f * w / h, -5.5f, 5.5f, -10.0f, 10.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// 渲染函数
void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslated(-3.0f, -3.0f, 3.0f);
glPopMatrix();
glutSolidSphere(2.0f, 50, 50);
glFlush();
}
// 主函数
void main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("多光源球");
glutDisplayFunc(Display);
glutReshapeFunc(ChangeSize);
Initial();
- 制作旋转飞机模型,学习示例程序chap10-2.cpp,为函数加注释并运行结果。
#include <GL/glut.h>
void Cube() //正方体
{
glBegin(GL_QUAD_STRIP);//填充凸多边形
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glEnd();
glBegin(GL_QUAD_STRIP);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glEnd();
}
void Circle() //圆面
{
glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串
glVertex3f(0.0f, 0.0f, 0.0f);
int i = 0;
for (i = 0; i <= 375; i += 15)
{
float p = i * 3.14 / 180;
glVertex3f(sin(p), cos(p), 0.0f);
}
glEnd();
}
void Cylinder() //圆柱
{
glBegin(GL_QUAD_STRIP);//连续填充四边形串
int i = 0;
for (i = 0; i <= 375; i += 15)
{
float p = i * 3.14 / 180;
glVertex3f(sin(p), cos(p), 1.0f);
glVertex3f(sin(p), cos(p), 0.0f);
}
glEnd();
Circle();
glTranslatef(0, 0, 1);
Circle();
}
void Cone() //圆锥
{
glBegin(GL_QUAD_STRIP);//连续填充四边形串
int i = 0;
for (i = 0; i <= 390; i += 15)
{
float p = i * 3.14 / 180;
glVertex3f(0, 0, 1.0f);
glVertex3f(sin(p), cos(p), 0.0f);
}
glEnd();
Circle();
}
//函数中,通过使用不同的变换和颜色设置,绘制了飞机的各个部分,包括螺旋桨、机身、圆柱体和圆锥体等。
void AirPlane(float x, float y, float z) {
static float i = 0, f = 0;
i += 0.1;
f += 0.01;
if (i > 360)
i = 0;
if (f > 360)
f = 0;
glPushMatrix();
glTranslatef(x, y, z); // 平移飞机位置
glRotatef(f, 1, 1, 1); // 绕着飞机中心旋转
glPushMatrix(); // 保存当前模型视图矩阵
glColor3f(0.5, 1.5, 0.5); // 设置颜色
glRotatef(i, 0, 1, 0); // 绕y轴旋转
glTranslatef(0, 0, 0.5); // 平移位置
glScalef(0.1, 0.05, 1); // 缩放
Cube(); // 绘制螺旋桨
glPopMatrix(); // 恢复之前保存的模型视图矩阵
glTranslatef(0, -0.1, 0); // 平移位置
glScalef(0.1, 0.1, 0.1); // 缩放
Cube(); // 绘制机身
glScalef(10, 10, 10); // 恢复缩放
// 绘制圆柱体
glColor3f(1, 0, 1); // 设置颜色
glTranslatef(0.04, -0.05, -0.9); // 平移位置
glScalef(0.1, 0.1, 1.5); // 缩放
Cylinder();
// 绘制圆锥体
glColor3f(0, 1, 0); // 设置颜色
glScalef(1, 1, 0.2); // 缩放
Cone();
// 绘制尾部
glColor3f(0, 1, 1); // 设置颜色
glTranslatef(0, 0.7, -4.5); // 平移位置
glScalef(0.2, 2, 1); // 缩放
Cube();
// 绘制翅膀
glTranslatef(-13, 0.3, 0); // 平移位置
glScalef(27, 0.1, 1); // 缩放
Cube();
}
//renderScene函数中进行场景的绘制和渲染
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // 重置模型视图矩阵
AirPlane(0, 0, -3); // 绘制飞机
glutSwapBuffers(); // 交换缓冲区
}
//changeSize函数用于处理窗口大小改变时的操作
void changeSize(int w, int h) {
if (h == 0)
h = 1;
float ratio = 1.0 * w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45, ratio, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(320, 320);
glutCreateWindow("Hello OpenGL");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
2. 编程实现:
1)设计并画出一个花盆(二维或三维);
2)让其做自由落体运动,并实现在地面上的弹跳效果,并逐渐停止,用键盘切换左右运动方向。
#include <GL/glut.h>
#include <math.h>
float potHeight = -5.0; // 花瓶的高度
float potPosX = 0.0; // 花瓶的初始水平位置
float potPosY = 7.0; // 花瓶的初始垂直位置
float potVelocityY = 0.0; // 花瓶的初始垂直速度
float gravity = -0.01; // 重力加速度
float damping = 0.7; // 弹跳时的速度损耗系数
float potSize = 1.0; // 花瓶的大小
void init(void) {
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void update(int value) {
// 更新花瓶的位置和速度
potPosY += potVelocityY;
potVelocityY += gravity;
// 处理花瓶触地时的弹跳效果
if (potPosY < potHeight) {
potPosY = potHeight; // 限制花瓶的高度不低于地面
if (fabs(potVelocityY) > 0.01) { // 当速度绝对值大于0.5时进行反弹
potVelocityY = -potVelocityY * damping;
}
else {
potVelocityY = 0.0; // 速度较低时,不再反弹
}
}
glutPostRedisplay();
glutTimerFunc(16, update, 0); // 设置下一帧的更新
}
void drawFlowerPot(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.8, 0.6, 0.4); // 设置花瓶的颜色为棕色
glPushMatrix();
glTranslatef(potPosX, potPosY, 0.0);
glBegin(GL_QUADS);
glVertex2f(-2.0, 0.0); // 花瓶的底部
glVertex2f(2.0, 0.0); // 花瓶的底部
glVertex2f(1.0, 4.0); // 花瓶的右侧
glVertex2f(-1.0, 4.0); // 花瓶的左侧
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 'a':
potPosX -= 0.5; // 按下a键,花瓶向左移动
break;
case 'd':
potPosX += 0.5; // 按下d键,花瓶向右移动
break;
}
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("Flower Pot");
init();
glutDisplayFunc(drawFlowerPot);
glutTimerFunc(16, update, 0); // 设置定时器用于更新花瓶的位置和速度
glutKeyboardFunc(handleKeypress); // 捕获键盘输入
glutMainLoop();
return 0;
}