用OpenGL绘制一个简单图形
- 格式:pdf
- 大小:1.75 MB
- 文档页数:70
OpenGL_Qt学习笔记之_02(绘制简单平⾯⼏何图形)本⽂来讲讲怎样使⽤opengl来画平⾯⼏何图形,这⼀节本来是很简单的,因为某些问题都弄⼤半天了。
当然,这还是按照NeHe的教程来的学习的。
这次实现的功能是在窗⼝中画⼀个三⾓形,⼀个矩形,⼀个圆形。
⾸先来简单的看⼀下opengl中的基本坐标规则,如下图所⽰:假设左下⾓那个点是⼈的眼睛观察的位置,则向左为x正⽅向,向上为y的正⽅向(这点与opencv中不同),向⾥为z的正⽅向。
下⾯来看看怎么绘制平⾯⼏何图形。
在设置好需要画的⼏何图形的属性后,⽐如颜⾊信息,就以glBegin()开始,以glEnd()结束,glBegin()中的参数为所画⼏何图形的类型,⽐如说GL_ TRIANGLES代表三⾓形,GL_QUADS为矩形等等。
在glBegin()和glEnd()之间是放的点,这⾥是三维的点,这些点是对应所画矩形的类型的。
画圆的话稍微⿇烦⼀点,因为opengl中没有直接对应的类型,⼀般都是采⽤三⾓形来逼近,其它很多⼏何图形也是类似的。
在⽤三⾓形逼近时,是⽤的画连续三⾓形,⼀般有2种类型。
GL_TRIANGLE_STRIP和GL_TRIANGLE_PAN,这2者的区别⾸先来看个⽰意图:如果给定有顺序的点v0,v1,v2,v3,v4,v5,则采⽤GL_TRIANGLE_STRIP模式时,所画的连续三⾓形应该依次为:(v0,v1,v2),(v1, v2, v3), (v2, v3, v4),(v3, v4, v5);如果采⽤的是GL_TRIANGLE_PAN模式,则第⼀个点是固定的,且后⾯每次都要跳⼀个顶点,所以它的结果为(v0, v1, v2), (v0, v2, v3), (v0, v3, v4),(v0, v4, v5)。
因此我这⾥要画圆盘的话,就采⽤的GL_TRIANGLE_PAN模式了,⼤家可以⼿动画⼀下就知道,具体可以参考后⾯给出的代码。
每次绘⼀个⼏何图形,都会移动当前的焦点,采⽤的函数是glTranslatef,⽽⽹上的教程给该函数的参数时,都是类似这样的glTranslatef(-1.5f, 0.0f, -6.0f);NeHe的教程中也是⼀样,他的解释是移动多少个单位,⽐如说-1.5f就是向左移动1.5个单位,我⼀开始也在程序中这么弄,结果调试了4个多⼩时,就是不显⽰三⾓形,在⽹上找了很多⽅法,都试过了还不⾏。
OpenGl绘制⼀个⽴⽅体OpenGl 绘制⼀个⽴⽅体 为了绘制六个正⽅形,我们为每个正⽅形指定四个顶点,最终我们需要指定6*4=24个顶点。
但是我们知道,⼀个⽴⽅体其实总共只有⼋个顶点,要指定24次,就意味着每个顶点其实重复使⽤了三次,这样可不是好的现象。
最起码,像上⾯这样重复烦琐的代码,是很容易出错的。
稍有不慎,即使相同的顶点也可能被指定成不同的顶点了。
如果我们定义⼀个数组,把⼋个顶点都放到数组⾥,然后每次指定顶点都使⽤指针,⽽不是使⽤直接的数据,这样就避免了在指定顶点时考虑⼤量的数据,于是减少了代码出错的可能性。
// 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯ ⽴⽅体的各个顶点的顺序如下图所⽰:1. 定义⽴⽅体的各个顶点数组 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯。
这样在指定顶点时,⽤指针,⽽不⽤直接⽤具体的数据。
1// 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯2static const GLfloat vertex_list[][3] = {3 -0.5f, -0.5f, -0.5f,40.5f, -0.5f, -0.5f,5 -0.5f, 0.5f, -0.5f,60.5f, 0.5f, -0.5f,7 -0.5f, -0.5f, 0.5f,80.5f, -0.5f, 0.5f,9 -0.5f, 0.5f, 0.5f,100.5f, 0.5f, 0.5f,11 }; 使⽤时可以直接采⽤指针绘制。
1 glBegin(GL_QUADS);2 glVertex3fv(vertex_list[0]);3 glVertex3fv(vertex_list[2]);4 glVertex3fv(vertex_list[3]);5 glVertex3fv(vertex_list[1]);67// ...8 glEnd(); 很容易就看出第0, 2, 3, 1这四个顶点构成⼀个正⽅形。
稍稍观察就可以发现,我们使⽤了⼤量的glVertex3fv函数,其实每⼀句都只有其中的顶点序号不⼀样,因此我们可以再定义⼀个序号数组,把所有的序号也放进去。
OpenGL基本图形的绘制1.使用glColor,glPointSize函数绘制三个不同颜色和大小的点// T.cpp : Defines the entry point for the console application. //#include "stdafx.h"#includevoid Display(void) {glClear(GL_COLOR_BUFFER_BIT);glPointSize(5.0f);glBegin(GL_POINTS);glColor3f(1.0,0.0,0.0);glVertex2f(0.3f,0.5f);glEnd();glPointSize(8.0f);glBegin(GL_POINTS);glColor3f(0.0,1.0,0.0);glVertex2f(0.0f,0.0f);glEnd();glPointSize(10.0f);glBegin(GL_POINTS);glColor3f(0.0,0.0,1.0);glVertex2f(-0.3f,-0.5f);glEnd();glFlush();}int main(int argc,char* argv[]) {glutInit(&argc,argv);glutInitDisplayMode(GLUT_RGB); glutInitWindowPosition(200,200);glutInitWindowSize(400,400);glutCreateWindow("Three Point");glutDisplayFunc(&Display);glutMainLoop();return 0;}2.使用glColor,glLineWidth,glLineStripple函数绘制实心、虚线及渐变色线(1)实心线// T.cpp : Defines the entry point for the console application.//#include "stdafx.h"#includevoid Display(void) {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);glEnable(GL_LINE_STIPPLE);glShadeModel(GL_SMOOTH);glLineStipple(2,0xFFFF);glLineWidth(2);glBegin(GL_LINES);glVertex2i(-100,0);glVertex2i(100,0);glEnd();glFlush();}int main(int argc,char* argv[]) {glutInit(&argc,argv);glutInitDisplayMode(GLUT_RGB);glutInitWindowPosition(200,200);glutInitWindowSize(400,400);glutCreateWindow("Solid Line");glutDisplayFunc(&Display);glutMainLoop();return 0;}(2)虚线// T.cpp : Defines the entry point for the console application. //#include "stdafx.h"#includevoid Display(void) {glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);glEnable(GL_LINE_STIPPLE);glShadeModel(GL_SMOOTH);glLineStipple(4,0xAAAA);glLineWidth(2);glBegin(GL_LINES);glVertex2i(-100,0);glVertex2i(100,0);glEnd();glFlush();}int main(int argc,char* argv[]) {glutInit(&argc,argv);glutInitDisplayMode(GLUT_RGB);glutInitWindowPosition(200,200);glutInitWindowSize(400,400);glutCreateWindow("Dotted Line");glutDisplayFunc(&Display);glutMainLoop();return 0;}(3)渐变线// T.cpp : Defines the entry point for the console application. //#include "stdafx.h"#includeGLuint Line;void Initial(void) {glClearColor(0.0f, 0.0f, 0.0f, 0.0f);Line = glGenLists(1);glNewList(Line, GL_COMPILE);glTranslatef(-50.0, 20.0, 0.0);glColor3f(255.0, 0.0, 0.0);glLineWidth(2);glBegin(GL_LINES);glColor3f(255.0, 0.0, 0.0);glVertex2i(0,-20);glColor3f(0.0, 0.0, 255.0);glVertex2i(100,-20);glEnd();glEndList();void ChangeSize(int w, int h) {glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D (-70.0f, 70.0f, -70.0f, 70.0f);}void Display(void) {glClear(GL_COLOR_BUFFER_BIT);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef(0.0, 0.0, 0.0);glCallList(Line);glFlush();}int main(int argc, char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(600,450);glutInitWindowPosition(100,100);glutCreateWindow("渐变色线");glutDisplayFunc(Display);glutReshapeFunc(ChangeSize);Initial();glutMainLoop();return 0;}3.使用glColor,glPolygonMode函数绘制纯色、渐变色、轮廓多边形(1)纯色六边形// a.cpp : Defines the entry point for the console application.//#include "stdafx.h"#includevoid init(){glClearColor (1.0, 1.0, 1.0, 0.0);glMatrixMode (GL_PROJECTION);gluOrtho2D (0.0, 200.0, 0.0, 150.0);}void polygon(void){glClear(GL_COLOR_BUFFER_BIT);int p1 [] = {20, 75};int p2 [] = {60, 5};int p3 [] = {140, 5};int p4 [] = {180, 75};int p5 [] = {140, 145};int p6 [] = {60, 145};glColor3f(0.0, 0.5, 1.0);glBegin(GL_POLYGON);glVertex2iv(p1);glVertex2iv(p2);glVertex2iv(p3);glVertex2iv(p4);glVertex2iv(p5);glVertex2iv(p6);glEnd();glFlush();}void main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(400, 300);glutCreateWindow("纯色六边形");init();glutDisplayFunc(polygon);glutMainLoop();}(2)渐变色六边形// a.cpp : Defines the entry point for the console application. //#include "stdafx.h"#includevoid init(){glClearColor (1.0, 1.0, 1.0, 0.0);glMatrixMode (GL_PROJECTION);gluOrtho2D (0.0, 200.0, 0.0, 150.0);}void polygon(void){glClear(GL_COLOR_BUFFER_BIT);int p1 [] = {20, 75};int p2 [] = {60, 5};int p3 [] = {140, 5};int p4 [] = {180, 75};int p5 [] = {140, 145};int p6 [] = {60, 145};glColor3f(0.0, 0.5, 1.0);glBegin(GL_POLYGON);glColor3f(0.0,0.0,1.0);glVertex2iv(p1);glColor3f(0.0,1.0,0.0);glVertex2iv(p2);glColor3f(1.0,0.0,0.0);glVertex2iv(p3);glColor3f(0.0,0.0,1.0);glVertex2iv(p4);glColor3f(0.0,1.0,0.0);glVertex2iv(p5);glColor3f(1.0,0.0,0.0);glVertex2iv(p6);glEnd();glFlush();}void main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(400, 300);glutCreateWindow("渐变色六边形");init();glutDisplayFunc(polygon);glutMainLoop();}(3)轮廓渐变色六边形// a.cpp : Defines the entry point for the console application. //#include "stdafx.h"#includevoid init(){glClearColor (1.0, 1.0, 1.0, 0.0); glPolygonMode (GL_FRONT_AND_BACK,GL_LINE); gluOrtho2D (0.0, 200.0, 0.0, 150.0);}void polygon(void){glClear(GL_COLOR_BUFFER_BIT);int p1 [] = {20, 75};int p2 [] = {60, 5};int p3 [] = {140, 5};int p4 [] = {180, 75};int p5 [] = {140, 145};int p6 [] = {60, 145};glColor3f(0.0, 0.5, 1.0);glBegin(GL_POLYGON);glColor3f(0.0,0.0,1.0);glVertex2iv(p1);glColor3f(0.0,1.0,0.0);glVertex2iv(p2);glColor3f(1.0,0.0,0.0);glVertex2iv(p3);glColor3f(0.0,0.0,1.0);glVertex2iv(p4);glColor3f(0.0,1.0,0.0);glVertex2iv(p5);glColor3f(1.0,0.0,0.0);glVertex2iv(p6);glEnd();glFlush();}void main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(400, 300); glutCreateWindow("轮廓渐变色六边形");init();glutDisplayFunc(polygon);glutMainLoop(); }。
opengl绘制三⾓形顶点数组对象:Vertex Array Object,VAO顶点缓冲对象:Vertex Buffer Object,VBO索引缓冲对象:Element Buffer Object,EBO或Index Buffer Object,IBO渲染管线在OpenGL中,任何事物都在3D空间中,⽽屏幕和窗⼝却是2D像素数组,这导致OpenGL的⼤部分⼯作都是关于把3D坐标转变为适应你屏幕的2D像素。
3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线管理的。
图形渲染管线可以被划分为两个主要部分:第⼀部分把你的3D坐标转换为2D坐标,第⼆部分是把2D坐标转变为实际的有颜⾊的像素。
2D坐标和像素也是不同的,2D坐标精确表⽰⼀个点在2D空间中的位置,⽽2D像素是这个点的近似值,2D像素受到你的屏幕/窗⼝分辨率的限制。
图形渲染管线接受⼀组3D坐标,然后把它们转变为你屏幕上的有⾊2D像素输出。
图形渲染管线可以被划分为⼏个阶段,每个阶段将会把前⼀个阶段的输出作为输⼊。
所有这些阶段都是⾼度专门化的(它们都有⼀个特定的函数),并且并⾏执⾏。
GPU上为每⼀个(渲染管线)阶段运⾏各⾃的⼩程序,从⽽在图形渲染管线中快速处理你的数据。
这些⼩程序叫做着⾊器(Shader)。
OpenGL着⾊器是⽤OpenGL着⾊器语⾔(OpenGL Shading Language, GLSL)写成的。
下⾯,你会看到⼀个图形渲染管线的每个阶段的抽象展⽰。
蓝⾊部分代表的是可以注⼊⾃定义的着⾊器的部分。
图形渲染管线包含很多部分,每个部分都将在转换顶点数据到最终像素这⼀过程中处理各⾃特定的阶段。
概括性地解释⼀下渲染管线的每个部分。
顶点数据⾸先,我们以数组的形式传递3个3D坐标作为图形渲染管线的输⼊,⽤来表⽰⼀个三⾓形,这个数组叫做顶点数据(Vertex Data);顶点数据是⼀系列顶点的集合。
⼀个顶点(Vertex)是⼀个3D坐标的数据的集合。
计算机图形学实验——利⽤OpenGL函数绘制五⾓星⼀、实验名称:五⾓星的绘制⼆、实验⽬的:了解 OpenGL 程序设计结构,掌握编程环三、境的设置,掌握绘制线段的⽅法。
四、实验内容:1.在 VC++ 环境下,练习利⽤ OpenGL 绘制三⾓形的程序。
2.编程实现绘制⼀个五⾓星。
(传统 OpenGL 或者 Shader)五、实验所需基本函数1.线段绘制glBegin(GL_LINES);//绘制参数GL_LINESglVertex2f(30,30);//起始点坐标glVertex2f(100,100);//终点坐标(两个为⼀组)glEnd();2.填充图像glBegin(GL_POLYGON);//绘制参数GL_POLYGONglVertex2f(x0, y0);//顶点坐标1glVertex2f(x1, y1);//2glVertex2f(cx, cy);//3glEnd();结果为对三个顶点组成的图像进⾏填充3.绘制颜⾊设置glColor3f(0.92, 0.89, 0.41);//⾦黄⾊六、实验原理根据⼩圆半径加⾓度算出第⼀个坐标然后⼤圆根据半径加⼀个⾓度算出第⼆个点坐标,然后旋转改变⾓度寻找所有顶点。
代码如下:1void DrawStar(float cx, float cy, float R,float r,float o)//五⾓星中⼼坐标x,y,⼤圆半径,⼩圆半径,初始⾓度2 {34float x0, y0, x1, y1;//5float o0 = o;//⼤圆对应⾓度6float o1 = o + 0.2 * 3.14;//⼩圆对应⾓度7for (int i = 0;i <10;i++)8 {9 x0 = cx+R * cos(o0);//⼤圆对应的x坐标10 y0 = cy+R * sin(o0);//⼤圆对应y坐标11 x1 = cx+r * cos(o1);//⼩圆对应x坐标12 y1 = cy+r * sin(o1);//⼩圆对应y坐标13if (i % 2 == 0)14 {15 glColor3f(1, 0, 0);16 }17else18 {19 glColor3f(0.92, 0.89, 0.41);20 }2122 glBegin(GL_POLYGON);//绘制23 glVertex2f(x0, y0);24 glVertex2f(x1, y1);25 glVertex2f(cx, cy);26 glEnd();27if (i % 2 == 0)28 {29 o0 = o0 + 0.4 * 3.14;//⼤圆对应⾓度变换30 }31else32 {33 o1 = o1 + 0.4 * 3.14;//⼩圆对应⾓度变换34 }3536 }37383940 }七、绘制结果⼋、附件所有代码1// OpenGLOld.cpp : 定义控制台应⽤程序的⼊⼝点。
浅谈怎样使用OpenGL绘制简单二维图形浅谈怎样使用OpenGL绘制简单二维图形摘要:在上一章节中我们讲解了OpenGL的基本原理,以及怎样在MFC中配置OpenGL 绘图环境,而在这一章节我开始正式绘图(注意上一章节的内容严格的来讲是属于window 编程,而不属于OpenGL)。
我们先从一个简单例子开始讲解:绘制一个在视图中央,长宽各为视图长宽一半的矩形。
1.1 视图设置与GDI二维函数库不同,OpenGL是一套三维绘图函数库。
使用GDI时,点的坐标对应的就是像素点坐标(已窗口左上角为(0,0)点),而OpenGL绘图时使用的是顶点坐标,要通过一系列转换最终换算成窗口的像素坐标,这种转换就是视图的设置,视图设置将在第三章详细讲解,本章只使用最简单的一种视图设置——2D正投影。
(视图设置的详细内容将在下一章讲解)设置2D正投影所需的函数如下:glMatrixMode(GL_PROJECTION);将投影矩阵设置为当前矩阵(后续设置矩阵的函数都是对投影矩阵起作用)glLoadIdentity();将当前矩阵设置为单位矩阵gluOrtho2D(left,right,bottom,top);创建一个把二维坐标投影到屏幕上的矩阵,并把当前矩阵与它相乘。
裁剪区域为矩形,它的左下坐标为(left,bottom),右上坐标为(right,top)。
glViewport(x,y,width,height);在窗口中定义一个像素矩形,最终的图像将映射到这个矩形中。
(x,y)参数指定了视口的左下角,width和height表示这个视口矩形的宽度和高度。
在默认情况下,视口的初始值是(0,0,winWidth,winHeight),其中winWidth和winHeight为对应窗口的大小。
在2D正投影模式下,OpenGL坐标于窗口显示的坐标对应逻辑如图 1 窗口映射关系所示:图 1 窗口映射关系1.2 绘制几何图元设置完视图和投影模式之后,我们便可以开始绘图了,但在这之前还要注意清空视图,防止绘图效果累加,比如要画一个移动圆形,如果不将前一帧的绘图擦除,我们将看到的是一系列的圆形,而不是一个移动的圆形,这和使用GDI在每次绘图都要用背景将上一次的绘图效果覆盖一样。
⽤OpenGL进⾏曲线、曲⾯的绘制实验⽬的理解Bezier曲线、曲⾯绘制的基本原理;理解OpenGL中⼀维、⼆维插值求值器的⽤法。
掌握OpenGL中曲线、曲⾯绘图的⽅法,对⽐不同参数下的绘图效果差异;代码1:⽤四个控制点绘制⼀条三次Bezier曲线#include "stdafx.h"#include <stdlib.h>#include <time.h>#include <GL/glut.h>//4个控制点的3D坐标——z坐标全为0GLfloat ctrlpoints[4][3] = {{ -4, -4, 0 }, { -2, 4, 0 }, { 2, -4, 0 }, { 4, 4, 0 }};void init(void){//背景⾊glClearColor(0.0, 0.0, 0.0, 1.0);//将控制点坐标映射为曲线坐标//参数1:GL_MAP1_VERTEX_3,3维点坐标//参数2和3:控制参数t或u的取值范围[0, 1]//参数4:曲线内插值点间的步长3————3维坐标//参数5:曲线间的补偿为顶点数4个————总步长为12//参数6:控制点⼆维数组⾸元素地址//注意: 若是在这⾥设置了相关参数,后续对ctrlpoints内容更改曲线不变glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);//打开开关——允许3维坐标控制点到参数点转换开关glEnable(GL_MAP1_VERTEX_3);glShadeModel(GL_FLAT);//代码开关2:去掉本注释,可启⽤反⾛样/*glEnable(GL_BLEND);glEnable(GL_LINE_SMOOTH); //允许直线反⾛样glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); // Antialias the linesglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/}void display(void){int i;glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 1.0, 1.0);//代码开关1:去掉本注释,查看动态的曲线绘图效果:动态更新控制点坐标/*for(int t = 0; t < 4; t++) {for(int j = 0; j < 3; j++)ctrlpoints[t][j] = (rand() % 1024 / 1024.0 - 0.5) * 10;}//动态映射glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);*/glLoadIdentity();glColor3f(1.0, 0.0, 0.0);//绘制连续线段glBegin(GL_LINE_STRIP);//参数t或u取值为i/30,共计31个点for (i = 0; i <= 30; i++)glEvalCoord1f((GLfloat)i / 30.0); //根据4个控制点坐标的参数化插值glEnd();/* 显⽰控制点 */glPointSize(5.0);glBegin(GL_POINTS);for (i = 0; i < 4; i++)glVertex3fv(&ctrlpoints[i][0]);glEnd();glTranslatef(-0.1f, 0.1f, 0.0f);glColor3f(0.0, 1.0, 0.0);//glLineWidth(2.0);//绘制连续线段——线段数越多,曲线越光滑glBegin(GL_LINE_STRIP);//设置参数t或u取值为i/60,共计61个点//实验:若让t从-2变化到+2,可看到什么效果for (i = 0; i <= 60; i++)glEvalCoord1f((GLfloat)i / 60.0); //根据4个控制点坐标的参数化插值glEnd();glTranslatef(-0.1f, 0.1f, 0.0f);glColor3f(1.0, 1.0, 1.0);//绘制连续线段glBegin(GL_LINE_STRIP);//设置参数t或u取值为i/60,共计61个点//实验:若让t从-2变化到+2,可看到什么效果for (i = 0; i <= 100; i++)glEvalCoord1f((GLfloat)i / 100.0);glEnd();glutSwapBuffers();}//3D空间中绘制2D效果,采⽤正交投影void reshape(GLsizei w, GLsizei h){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho(-5.0, 5.0, -5.0*(GLfloat)h / (GLfloat)w, 5.0*(GLfloat)h / (GLfloat)w, -5.0, 5.0);elseglOrtho(-5.0*(GLfloat)w / (GLfloat)h, 5.0*(GLfloat)w / (GLfloat)h, -5.0, 5.0, -5.0, 5.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void keyboard(unsigned char key, int x, int y){switch (key){case'x':case'X':case27: //ESC键exit(0);break;default:break;}}int main(int argc, char** argv){srand((unsigned int)time(0));glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//使⽤双缓存模式和深度缓存 glutInitWindowSize(800, 800);glutInitWindowPosition(0, 0);glutCreateWindow("2D Bezier曲线");init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutIdleFunc(display);//设置空闲时调⽤的函数glutMainLoop();return0;}此时我们打开代码开关1,查看动态Bezier曲线绘制效果:关闭代码开关1,打开代码开关2,查看直线反⾛样效果:对⽐刚开始的效果图,我们发现,使⽤了直线反⾛样后,绘制出的曲线很光滑,看着很舒服。
实验名称OpenGL程序结构与基本图形的绘制一、实验目的学习基于OpenGL的图形学编程,掌握程序设计的基本过程与程序的基本结构。
二、实验内容在VC6.0下生成基于控制台的应用程序,把OpenGL的基本头文件包含进应用程序中,并设置好相应的环境参数,编写基于OpenGL的应用程序,实现基本图形的绘制。
三、实验步骤1.在VC6.0环境下生成一基于控制台的应用程序(win32 console),选择存储目录为桌面,名字为学号或者姓名的拼音。
如下图:2.在创建的应用程序中选择创建一个“hello world”的应用程序。
3.把以下代码加入到应用程序的CPP文件中。
void display() {glClear( GL_COLOR_BUFFER_BIT); // Clear the frame buffer glColor3f( 0.0, 1.0, 0.0); // Set current color to green}void init() {glClearColor( 0.0, 0.0, 0.0, 0.0);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(-1.0, 1.0, -1.0, 1.0);glMatrixMode(GL_MODELVIEW);}并把原main函数中的内容用以下代码替换:glutInit( &argc, argv);glutInitWindowSize( 400, 400);glutInitWindowPosition( 200, 100);glutCreateWindow( "Green Triangle");glutDisplayFunc( display);init();glutMainLoop();return 0;4.修改display函数,实现三角形,多边形及圆等基本图形的绘制。
实验一、Ope nGL直线、圆的绘制1、实验目的1)了解OpenGL图形库的功能和结构;2)学习了解OpenGL程序的基本结构,及常用函数;3 )学习使用OpenGL绘制基本图形(线、圆);2、实验内容1 )使用OpenGL编写一个简单的C++程序,使该程序能够绘制出直线。
2 )使用OpenGL编写一个简单的C++程序,使该程序能够绘制出圆。
3、实验过程1)在系统上配置好OpenGL的环境(头文件,库文件,和链接库文件);2)使用Visual V++6.0新建一个C++文档,并创建相应的工程;3)在文档中引入OpenG啲头文件,编辑代码实现鼠标拖动画直线,画圆。
4、实验结果可单击鼠标左键,然后拖动鼠标画出两条直线,并同时画出圆; 可单击鼠标右键,然后拖动鼠标画出两个圆,并同时画出直线。
结果截图:1.鼠标左键主要控制绘制的直线:石Open诂L直找和园的锭制5、实验代码1. #in elude vgl/glut.h>2. #in elude <math.h>3.3. // GLint pNum = 0;4. GLint px1, py1, px2, py2, ex, cy, r;5. GLint winWidth=600, winHeight=600;-/25.} 26.7. 8. llllllllllllllllll 画直线 llllllllllll 9. void Draw_Brese nham(i nt pStartx,i nt pStarty,i nt 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.27. pEn dx,i nt pEndy) {ll 用Bresenham 算法画直线 int i; if(pStartx==pE ndx) ll 为竖线 if(pStartyv=pE ndy) for(i=pStarty;i<=pE ndy;i++) glVertex2f(pStartx,i); else for(i=pE ndy;i<=pStarty;i++) glVertex2f(pStartx,i); return;-/// 为横线 if(pStarty==pE ndy) { if(pStartx<=pE ndx) { for(i=pStartx;i<=pE ndx;i++) glVertex2f(i,pStarty);} else { for(i=pE ndx;i<=pStartx;i++) glVertex2f(i,pStarty); } return; } // 为斜线 float m=(pE ndy-pStarty)*1.0/(pE ndx-pStartx); 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49.-/ float p;}else-/p=2*m-1; if(m>0 && m<=1) { if(pStartx<pE ndx) { while(pStartx<=pE ndx) { glVertex2f(pStartx++,pStarty); if(p>=0) { p+=2*m-2; pStarty++; } else p+=2*m; } { while(pE ndx<=pStartx) {50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71.} else glVertex2f(pE ndx++,pE ndy); if(p>=0) { p+=2*m-2; pEndy++; } else p+=2*m; } } return; } p=-2*m-1; if(m<0 && m>=-1) { if(pStartx<pE ndx) { while(pStartx<=pE ndx) { glVertex2f(pStartx++,pStarty);72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93.} elseif(p>=0) { p+=-2*m-2; pStarty--; } else p+=-2*m; } } else { while(pE ndx<=pStartx) { glVertex2f(pE ndx++,pE ndy); if(p>=0) { p+=-2*m-2; pEn dy--; p+=-2*m;94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115.} else } return; } p=2/m-1; if(m>1) { if(pStartyvpE ndy) { while(pStartyv=pE ndy) { glVertex2f(pStartx,pStarty++); if(p>=0) { p+=2/m-2; pStartx++; p+=2/m; }116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137.-/else {while(pE ndyv=pStarty) {glVertex2f(pE ndx,pE ndy++); if(p>=0) {p+=2/m-2; pEndx++; } else p+=2/m; } }return;} p=-2/m-1; if(pStarty<pE ndy) { while(pStarty<=pE ndy)138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153.154. 155. 156. 157. 158. 159.-/181.{glVertex2f(pStartx,pStarty++);if(p>=0){p+=-2/m-2;pStartx--;}elsep+=-2/m;}}else{while(pE ndyv=pStarty){glVertex2f(pE ndx,pE ndy++);if(p>=0){p+=-2/m-2;pEn dx--;}else160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180.-/203. }182.p+=-2/m; 183. }184. }185. }186.187.////////////////// 画圆//////////// 188. /////////其他象限绘制189. void CirclePoi nts(i nt x,i nt y){190.// 第1象限191.glVertex2f(x,y); 192.glVertex2f(y,x);193.// 第2象限194.glVertex2f(-x,y); 195.glVertex2f(-y,x);196.// 第3象限197.glVertex2f(-y,-x); 198.glVertex2f(-x,-y);199.// 第4象限200.glVertex2f(x,-y); 201.glVertex2f(y,-x);202.-/void DrawCircle(i nt cx,i nt cy,i nt radis){ glPushMatrix(); gITra nslatef(cx,cy,0); glPoi ntSize(1);glColor3f(0.5f, 0.5f, 1.0f); glBegi n( GL_POINTS);int x,y; double p; x=0; y=radis; p=1.25-radis; while(x<=y+1) {CirclePoi nts(x,y); x++; if(p>=0) { y--;p+=2.0*(x-y)+5;204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225.〃////////中点算法画圆-/} else p+=2*x+3; }glE nd(); glPopMatrix(); }////////// 绘制坐标轴 void DrawOx(){ glColor3f(0.95, 0.7, 0.8); glPoi ntSize(1); glBeg in (GL_LINES); glVertex2f(-wi nWidth/2,0); glVertex2f(wi nWidth/2,0); glVertex2f(0,wi nH eight/2); glVertex2f(0,-wi nH eight/2); glE nd(); }226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243.244. 245. 246. 247.////////// 显示函数-/ 248. void Display(){249. 〃//////GL_COLOR_BUFFER_BIT(用背景颜色填充) 250. glClear(GL_COLOR_BUFFER_BIT);251.251. DrawOx();253.252. glColor3f(0.0,0.0,1.0);255.253. glBegi n( GL_POINTS);254. //Brese nhamL in e(px1, py1, px2, py2);255. Draw_Brese nham(px1, py1,px2, py2);256. glE nd();257. glBegi n( GL_POINTS);258. Draw_Brese nham(py1, px1,py2, px2);259. glE nd();260. //glBegi n(GL_LINES);261. 〃glVertex2f(px1,py1);262. 〃glVertex2f(px2,py2);263. 〃glVertex2f(py1,px1);264. 〃glVertex2f(py2,px2);265. //glE nd();269.270. DrawCircle(cx,cy,r);271. DrawCircle(cy,cx,r);272.273. III 交换缓冲区274. glutSwapBuffers();275. 〃glFlush();〃刷新绘图命令276. }277.278.279. II 设置渲染状态(听起来满下人,实际上很简单)280. void SetupRC(void)281. {282. II清除颜色(这里为黑色,为了方便找画的那个点)可以理解成背景颜色283. II和glColor4f(1.0f, O.Of, O.Of , 1.0f) 一样,所有参数都在0.0到1.0之间,后缀f是表示参数是浮点型的284. II最后的那个1.0f是透明度,0.0f表示全透明,1.0f 是完全不透明285. glClearColor(1.0f, 1.0f, 1.0f,1.0f);286. }287.287. II当绘制的窗口大小改变时重新绘制,使绘制的图形同比例变化,288. //几乎所有OpenGL程序中的这个函数都是一样的,所以,放心大胆的拷贝吧290. void Chan geSize(i nt w, i nt h)291. {292. wi nWidth = w;293. wi nH eight = h;294. //设置观察视野为窗口大小(用FLASH里面的话来说应该叫设置摄象机视野)295. glViewport(0,0,w,h);296. //重置坐标系统,指定设置投影参数297. glMatrixMode(GL_PROJECTION);298. /////// 调用单位矩阵,去掉以前的投影参数设置299. glLoadIde ntity();300. ////// 设置投影参数301. gluOrtho2D(-w/2,w/2,-h/2,h/2);302. }303.304. ///////////////// 鼠标点击305. void MousePlot(GLi nt butto n,GL int actio n,GL int xMouse,GLi nt yMouse){306. if(butto n==GLUT_LEFT_BUTTON &&-/324.307. px1 = xMouse - win Width/2; 308. py1 = winH eight/2 - yMouse;309. }310.if(butto n==GLUT_LEFT_BUTTONactio n==GLUT_UP){311. px2 = xMouse - win Width/2; 312. py2 = winH eight/2 - yMouse; 313. glutPostRedisplay();314. }315.if(butto n==GLUT_RIGHT_BUTTONactio n==GLUT_DOWN){316. cx=xMouse-wi nWidth/2; 317. cy=wi nH eight/2-yMouse; 318. }319. }320. //////////////// 鼠标移动321.void MouseMove(GLi nt xMouse,GL int yMouse){ 322. px2 = xMouse - win Width/2; 323. py2 = winH eight/2 - yMouse;actio n==GLUT_DOWN){ &&&&r=sqrt(pow((xMouse-wi nWidth/2-cx),2)+pow((wi nH eig-/ ht/2-yMouse-cy),2));325. glutPostRedisplay();326. }327.327. //主函数328. int main (i nt argc, char* argv[])329. {330. glutI ni t(&argc, argv);331. //设置显示模式332. glutI ni tDisplayMode(GLUT_DOUBLE | GLUT_RGB| GLUT_DEPTH);333. //设置窗口大小像素334. glutI nitWin dowSize(600, 600);335. ////设置窗口出现在屏幕的位置336. glutI nitWin dowPositio n(300,160);337. //建立一个叫OpenGL的窗口338. glutCreateWi ndow("Ope nGL-Li ne");340.339. //调用函数Display进行绘制340. glutDisplayF un c(Display);341. ////// 调用鼠标移动函数-/ 342. //glutPassiveMotio nFun c(PassiveMouseMove);-/ 357. } 345. glutMotio nFun c(MouseMove); 346. ... 调用鼠标点击函数 347. glutMouseFu nc(MousePlot); 348. 349.//如果窗口大小改变则调用函数 绘制 350. glutReshapeF un c(Cha ngeSize); 351. //清屏 352. SetupRC(); 353. //循环绘制 354. glutMai nLoop(); 355. 356.return 0; ChangeSize 重新进行。
计算机图形学习题参考答案第1章绪论1、第一届ACM SIGGRAPH会议是哪一年在哪里召开的?解:1974年,在Colorado大学召开了第一届SIGGRAPH年会。
2、计算机图形学之父是谁?解:Sutherland3、列举一些计算机图形学的应用领域(至少5个)。
解:计算机辅助设计、图示图形学、计算机艺术、娱乐、教学与培训、可视化、图像处理、图形用户界面等。
4、简要介绍计算机图形学的研究内容。
解:(1)图形的输入。
如何开发和利用图形输入设备及相关软件把图形输入到计算机中,以便进行各种处理。
(2)图形的处理。
包括对图形进行变换(如几何变换、投影变换)和运算(如图形的并、交、差运算)等处理。
(3)图形的生成和输出。
如何将图形的特定表示形式转换成图形输出系统便于接受的表示形式,并将图形在显示器或打印机等输出设备上输出。
5、简要说明计算机图形学与相关学科的关系。
解:与计算机图形学密切相关的学科主要有图像处理、计算几何、计算机视觉和模式识别等。
计算机图形学着重讨论怎样将数据模型变成数字图像。
图像处理着重研究图像的压缩存储和去除噪音等问题。
模式识别重点讨论如何从图像中提取数据和模型。
计算几何着重研究数据模型的建立、存储和管理。
随着技术的发展和应用的深入,这些学科的界限变得模糊起来,各学科相互渗透、融合。
一个较完善的应用系统通常综合利用了各个学科的技术。
6、简要介绍几种计算机图形学的相关开发技术。
解:(1)OpenGL。
OpenGL是一套三维图形处理库,也是该领域事实上的工业标准。
OpenGL独立于硬件、操作系统和窗口系统,能运行于不同操作系统的各种计算机,并能在网络环境下以客户/服务器模式工作,是专业图形处理、科学计算等高端应用领域的标准图形库。
以OpenGL为基础开发的应用程序可以十分方便地在各种平台间移植;OpenGL与C/C++紧密接合,便于实现图形的相关算法,并可保证算法的正确性和可靠性;OpenGL使用简便,效率高。
opengl学习(三)----绘制简单图形(⼀)今天说⼀说⼏种简单的图元。
所有的⼏何图元都是根据它们的顶点来描绘的。
⽽顶点就是它们在屏幕上的坐标位置。
我喜欢把这⼏个简单的图元称为点线⾯。
点,可以看到⼀个顶点;线,就是两个顶点指定的⼀条有限长度的线段;⾯,其实更准确讲是⼀个凸多边形。
opengl⾥所讲的多边形是内部⽤颜⾊填充的,视觉上称为⾯我个⼈认为是更贴近的。
当然,多边形也是由指定的顶点组成的。
需要注意的是,要想被opengl按照设计被绘制必须正确的认识到,所谓的多边形是顶点都处于⼀个平⾯上,凸多边形。
凸多边形不能理解的,请问度娘。
来看⼀个例⼦:C++代码1. glBegin(GL_POLYGON);2. glVertex2f(0.0, 0.0);3. glVertex2f(0.0, 3.0);4. glVertex2f(4.0, 3.0);5. glVertex2f(6.0, 1.5);6. glVertex2f(4.0, 0.0);7. glEnd();先不去关⼼代码本⾝,这段代码最终的结果是要指定5个顶点绘制⼀个凸五边形。
注意,不是5条线段⽽是⼀个凸五边形的平⾯。
不管是点线⾯的哪⼀种,都是需要指定⼀组顶点的。
如何判定顶点指定的开始和结束就是glBegin和glEnd的⼯作。
引⽤void glBegin(Glenum mode);标志着⼀个顶点数据列表的开始,它描述了⼀个⼏何图元。
mode参数指定了图元的类型。
void glEnd(void);标志着⼀个顶点数据列表的结束。
mode设置的不同,代表着将要绘制的图元也不同。
下⾯这个表就是图元的名称和含义:值含义GL_POINTS 单个的点GL_LINES ⼀对顶点被解释为⼀条直线GL_LINE_STRIP ⼀系列的连接直线GL_LINE_LOOP 和上⾯相同,但第⼀个顶点和最后⼀个顶点彼此相连GL_TRIANGLES 3个顶点被解释为⼀个三⾓形GL_TRIANGLES_STRIP 三⾓形的连接串GL_TRIANGLES_FAN 连接成扇形的三⾓形系列GL_QUADS 4个顶点被解释为⼀个四边形GL_QUADS_STRIP 四边形的连接串GL_POLYGON 简单的凸多边形的边界试想着,如果将glBegin(GL_POLYGON)修改为glBegin(GL_POINTS),绘制出来的将是什么图形呢? 哈哈,那就是5个点⽽已么。
使用openGl画直线(DDA算法)、画圆、椭圆(Bresenham算法)#include<stdlib.h>#include<iostream.h>#include <GL/glut.h>/* initialization: */void myinit(void){/* attributes */glClearColor(1.0, 1.0, 1.0, 0.0);//设置背景颜色glColor3f(1.0, 0.0, 0.0); //设置绘制颜色为红色/* set up viewing: *//* 500 x 500 window with origin lower left */glMatrixMode(GL_PROJECTION); //指定设置投影参数glLoadIdentity();/*OpenGL为我们提供了一个非常简单的恢复初始坐标系的手段,那就是调用glLoadIdentity()命令。
该命令是一个无参的无值函数,其功能是用一个4×4的单位矩阵来替换当前矩阵,实际上就是对当前矩阵进行初始化。
也就是说,无论以前进行了多少次矩阵变换,在该命令执行后,当前矩阵均恢复成一个单位矩阵,即相当于没有进行任何矩阵变换状态。
*/gluOrtho2D(0.0, 500.0, 0.0, 500.0); //设置投影参数glMatrixMode(GL_MODELVIEW);/*这两个都是glMatrixMode()函数的参数,那就先说说glMatrixMode吧~,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有,GL_PROJECTION,GL_MODELVIEW和GL_TEXTURE;如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。