实验一 VS+OpenGL绘图环境及基本图形绘制
一、实验目的
- 熟悉OpenGL的主要功能;
- 掌握OpenGL的绘图流程和原理;
- 掌握OpenGL核心函数的使用;
- 熟悉OpenGL基本图形元素的绘制函数。
二、实验内容
- 如预备知识所述,创建一个OpenGL工程,修改第一个程序中的Display()函数,如下:
void Display(void)
{
glClear (GL_COLOR_BUFFER_BIT); //清除缓存
glColor3f (1.0f, 1.0f, 0.0f); //设置颜色为黄色
//设置第一根线的两个端点,请注意:OpenGL坐标系的原点是在屏幕左下角
glVertex2f(10.0f, 50.0f);
glVertex2f(110.0f, 50.0f);
glColor3f (1.0f, 0.0f, 0.0f); //设置颜色为红色
//设置第二根线的两个端点
glVertex2f(110.0f, 50.0f);
glVertex2f(110.0f, 150.0f);
glEnd(); //画线结束
glFlush ();
}
该程序是在窗口中画两条线,分别用黄色和红色绘制。如上所述,OpenGL是一个状态机,glBegin(UINT State)可以设定如下状态:
GL_POINTS 画点
GL_LINES 画线,每两个顶点(Vertex)为一组
GL_LINE_STRIP 画线,把若干个顶点顺次连成折线
GL_LINE_LOOP 画线,把若干个顶点顺次连成封闭折线
GL_TRIANGLES 画三角形,每三个顶点为一组
GL_QUADS 画四边形,每四个顶点为一组
GL_POLYGON 画多边形
还有GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUAD_STRIP 等等。另外,程序可以有多组glBegin()、glEnd()并列的形式,如:
... ...
glBegin(GL_LINES);
......
glEnd();
glBegin(GL_QUADS);
... ...
glEnd();
... ...
要求:利用OpenGL库函数绘制基本图形,输出绘制结果。
- 绘制函数编辑,通过设置观察矩形和视口,使得曲线在窗口的显示效果如下图所示。
编辑
- 利用OpenGL函数绘制圆弧和心脏线。
圆弧通过其中心c,外接圆的半径R,以及开始的角度a和它展开的角度b来表示,函数可以表示为:
void drawArc(Point2 center, float radius, float startAngle, float sweep)
心脏线要求平铺屏幕窗口,并创建菜单,通过菜单设定心脏线的大小(K值决定大小),通过鼠标动作改变心脏线的颜色。心脏线的极坐标形式为:
编辑
参考代码:
恐龙平铺屏幕窗口polyline.cpp
菜单GlutMenu.cpp
三、实验设计思路
1. 创建一个OpenGL工程,修改初始化代码Display函数,glBegin(GL_LINES)开始画线;glColor3f ()设置颜色;glVertex2f()设置第一根线的两个端点。从而得到两条颜色及位置不同的线段。
2.修改Display函数,glBegin(GL_LINE_STRIP);开始画线,把若干个顶点顺次连成折线glColor3f(0.0f, 0.0f, 0.0f);设置颜色,利用for循环描点glVertex2f(i, exp(-i) * cos(2 * 3.14 * i));函数。再修改Initial函数中gluOrtho2D(0.0, 4.0, -1.0, 1.0);的X与Y轴显示区域。
3. 圆弧通过其中心c,外接圆的半径R,以及开始的角度a和它展开的角度b来表示;对心脏线进行绘制,创建菜单以控制心脏线的大小,用鼠标左键控制菜单弹出,K设置了五个心脏线大小。通过鼠标右键来控制颜色,glColor3f(red/256.0+0.5, green/256.0+0.5, blue/256.0+0.5);设置随机数,最后通过glViewport调节视口,来实现了一个5*5的平铺屏幕窗口效果。
四、实验代码
1.
#include <gl/glut.h> void Initial(void) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //设置窗口背景颜色为白色 glMatrixMode(GL_PROJECTION); //设置投影参数 glLoadIdentity(); gluOrtho2D(0.0, 200.0, 0.0, 200.0); } void Display(void) { glClear(GL_COLOR_BUFFER_BIT); //清除缓存 glBegin(GL_LINES); //开始画线 glColor3f(1.0f, 1.0f, 0.0f); //设置颜色为黄色 //设置第一根线的两个端点,请注意:OpenGL坐标系的原点是在屏幕左下角 glVertex2f(10.0f, 50.0f); glVertex2f(110.0f, 50.0f); glColor3f(1.0f, 0.0f, 0.0f); //设置颜色为红色 //设置第二根线的两个端点 glVertex2f(110.0f, 50.0f); glVertex2f(110.0f, 150.0f); glEnd(); //画线结束 glFlush(); } void main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //初始化窗口的显示模式 glutInitWindowSize(400, 400); //设置窗口的尺寸 glutInitWindowPosition(100, 120); //设置窗口的位置 glutCreateWindow("矩形"); //创建一个名为矩形的窗口 glutDisplayFunc(Display); //设置当前窗口的显示回调函数 Initial(); //完成窗口初始化 glutMainLoop(); //启动主GLUT事件处理循环 // return 0; }
2.
#include <gl/glut.h> #include<math.h> void Initial(void) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); //设置窗口背景颜色为白色 glMatrixMode(GL_PROJECTION); //设置投影参数 glLoadIdentity(); gluOrtho2D(0.0, 4.0, -1.0, 1.0); } void Display(void) { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_LINE_STRIP); glColor3f(0.0f, 0.0f, 0.0f); for (float i = 0; i <= 4; i = i + 0.01) { glVertex2f(i, exp(-i) * cos(2 * 3.14 * i)); } glEnd(); glFlush(); } void main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //初始化窗口的显示模式 glutInitWindowSize(400, 400); //设置窗口的尺寸 glutInitWindowPosition(100, 120); //设置窗口的位置 glutCreateWindow("矩形"); //创建一个名为矩形的窗口 glutDisplayFunc(Display); //设置当前窗口的显示回调函数 Initial(); //完成窗口初始化 glutMainLoop(); //启动主GLUT事件处理循环 // return 0; }
3.1
#include <GL/glut.h> #include <stdio.h> #include <stdlib.h> GLuint startList; void init(void) { GLUquadricObj* qobj; startList = glGenLists(1); qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); /* 只画边缘 */ gluQuadricNormals(qobj, GLU_NONE);/*不算NORMAL(顶点的方向)*/ glNewList(startList, GL_COMPILE);/*只编译DISPLAY LIST不绘制*/ gluPartialDisk(qobj, 0.0, 1.0, 20, 4, 0.0, 225.0);/* 第一个参数是A quadric object,然后内圆半径为0.0,外圆半径为1.0,z轴向分割片数,最后两个参数是圆弧的起始角和结束角 */ glEndList(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glColor3f(1.0, 1.0, 0.0); glCallList(startList); glPopMatrix(); glFlush(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-2.5, 2.5, -2.5 * (GLfloat)h / (GLfloat)w, 2.5 * (GLfloat)h / (GLfloat)w, -10.0, 10.0); else glOrtho(-2.5 * (GLfloat)w / (GLfloat)h, 2.5 * (GLfloat)w / (GLfloat)h, -2.5, 2.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* ARGSUSED1 */ void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(300, 300); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }
3.2
#include <windows.h> #include<iostream> #include <GL/glut.h> #include <cmath> #define PI 3.1415926 #define RED 1 #define GREEN 2 #define BLUE 3 #define WHITE 4 //初始化OpenGL场景 float red = 1.0, blue = 1.0, green = 1.0; float K = 1; void myinit(void) { glClearColor(0.0, 0.0, 0.0, 0.0); //将背景置成黑色 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-12.0, 12.0, -12.0, 12.0); } //用户的绘图过程 void mydisplay() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glColor3f(1.0, 0.0, 0.0); glColor3f(red / 256.0 + 0.5, green / 256.0 + 0.5, blue / 256.0 + 0.5); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { glViewport(i * 64, j * 64, 100, 100); glBegin(GL_LINE_LOOP); for (float x = 0; x < 2 * 3.14; x = x + 0.1) { glVertex2f((1 + cos(x)) * cos(x) * K, (1 + cos(x)) * sin(x) * K); } glEnd(); } } glFlush(); } void myMouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) { if (button == GLUT_RIGHT_BUTTON) { red = rand() / 128; blue = rand() / 128; green = rand() / 128; } else if (button == GLUT_RIGHT_BUTTON) { glClearColor(1.0f, 0.0f, 0.0f, 0.0f); // Red glClear(GL_COLOR_BUFFER_BIT); glFlush(); } } } void processMenuEvents_two(int option) { switch (option) { case 1:K = 1; break; case 2:K = 2; break; case 3:K = 3; break; case 4:K = 4; break; case 5:K = 5; break; default: break; } } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(0, 0); glutInitWindowSize(400, 400); glutCreateWindow("心脏线"); myinit(); glutDisplayFunc(mydisplay); glutIdleFunc(mydisplay);//空闲回调函数 glutMouseFunc(myMouse); glutCreateMenu(processMenuEvents_two); glutAddMenuEntry("one", 1); glutAddMenuEntry("two", 2); glutAddMenuEntry("three", 3); glutAddMenuEntry("four", 4); glutAddMenuEntry("five", 5); glutAttachMenu(GLUT_LEFT_BUTTON); glutMainLoop(); }
五、实验结果及心得体会
1.
编辑
2.
编辑
3
编辑
编辑编辑
编辑编辑
此次实验,学会了基本的VS+OpenGL绘图环境及基本图形绘制,了解了OpenGL的主要功能以及绘图流程和原理。实现了OpenGL核心函数的使用以及基本图形元素的绘制函数。还实现了鼠标交互等功能。通过本次实验绘制了不同的函数图像,对今后的学习也有了较大的帮助。