OpenGL入门学习之二——绘制几何图形
OpenGL 3基本图形绘制
模型-视图变换过程就是一个将顶点坐标从世界坐标变换到 视觉坐标的过程。这里很重要的是对两个坐标系的认识。 世界坐标系也称为全局坐标系。它是一个右手坐标系,可 以认为该坐标系是固定不变的,在初始态下,其x轴为沿屏
幕水平向右,y轴为沿屏幕垂直向上,z轴则为垂直屏幕面
向外指向用户。
视觉坐标系(即观察坐标系)也称为局部坐标系。它是一个
(1)确定当前矩阵栈 void glMatrixMode(Glenum mode); 参数取值:
GL_MODELVIEW:模型视图矩阵
GL_PROJECTION:投影矩阵 GL_TEXTURE:纹理矩阵 默认的选定矩阵为模型-视图变换。
矩阵栈及其操作(2/8)
清矩阵栈栈顶
void glLoadIdentity(void); •将栈顶矩阵替换为单位矩阵 •取消之前变换的作用 M … I
对于二维图形向二维屏幕的投影,则应使用实 用库中的如下函数:
void gluOrtho2D(Gldouble left, Gldouble right,
Gldouble bottom, Gldouble top);
前面提到过,用二维顶点命令绘制的二维物体 的z坐标均为零,而gluOrtho2D()命令假定场景 中的 z 坐标介于-1.0和 1.0 之间。
左手坐标系,该坐标系是可以活动的。在初始态下,其原
点及x、y轴分别与世界坐标系的原点及x、y轴重合,而z轴 则正好相反,即为垂直屏幕面向内。
默认:视点在原点,视线沿Z轴负方向。
坐标系
右手坐标系
y
窗口 x
o z
缺省的观察坐标系
视点变换
View变换可以改变视点的位置和方向,要在 Model变换之前调用。设置任意观察坐标点。
OpenGL编程轻松入门之二次几何体
OpenGL编程轻松入门之二次几何体2006-05-22 10:10作者:黄燕出处:天极开发责任编辑:方舟这一章我们讲一下二次几何物体的绘制。
二次几何物体的绘制有几种不同的方式,在本例中可以看出不同的绘制方式的不同效果,如图十五所示。
例13:本例使用GLU库函数绘制了四个几何物体,分别为圆柱体、球体、圆盘和部分圆盘。
#include <windows.h>#include <GL/glut.h>#include <math.h>/*声明四个二次曲面物体*/GLUquadricObj *quadObj1;GLUquadricObj *quadObj2;GLUquadricObj *quadObj3;GLUquadricObj *quadObj4;static float light_ambient[] = {0.1,0.1,0.1,1.0};static float light_diffuse[] = {0.5,1.0,1.0,1.0};static float light_position[] = {90.0,90.0,150.0,0.0};static float front_mat_shininess[] = {60.0};static float front_mat_specular[] = {0.2,0.2,0.2,1.0};static float front_mat_diffuse[] = {0.5,0.5,0.28,1.0};static float back_mat_shininess[] = {60.0};static float back_mat_specular[] = {0.5,0.5,0.2,1.0};static float back_mat_diffuse[] = {1.0,0.9,0.2,1.0};static float Imodel_ambient[] = {1.0,1.0,1.0,1.0};static float Imodel_twoside[] = {GL_TRUE};static float Imodel_oneside[] = {GL_FALSE};void myInit(void){/*设置背景色*/glClearColor(1.0,1.0,1.0,1.0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LEQUAL);/*设置光照*/glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);glLightfv(GL_LIGHT0,GL_POSITION,light_position);/*设置材质*/glMaterialfv(GL_FRONT,GL_DIFFUSE,front_mat_diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,front_mat_specular);glMaterialfv(GL_FRONT,GL_SHININESS,front_mat_shininess);glMaterialfv(GL_BACK,GL_DIFFUSE,back_mat_diffuse);glMaterialfv(GL_BACK,GL_SPECULAR,back_mat_specular);glMaterialfv(GL_BACK,GL_SHININESS,back_mat_shininess);/*设置光照模型参数*/glLightModelfv(GL_LIGHT_MODEL_AMBIENT,Imodel_ambient);glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE,Imodel_twoside);/*激活关照*/glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glShadeModel(GL_SMOOTH);}void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);/*创建四个二次曲面物体*/quadObj1 = gluNewQuadric();quadObj2 = gluNewQuadric();quadObj3 = gluNewQuadric();quadObj4 = gluNewQuadric();/*绘制一个圆柱体*/glPushMatrix();gluQuadricDrawStyle(quadObj1,GLU_FILL); gluQuadricNormals(quadObj1,GL_FLAT); gluQuadricOrientation(quadObj1,GLU_INSIDE); gluQuadricTexture(quadObj1,GL_TRUE);glColor3f(1.0,1.0,0.0);glRotatef(30,1.0,0.0,0.0);glRotatef(40,0.0,1.0,0.0);gluCylinder(quadObj1,2.0,2.0,9.0,20.0,8.0); glPopMatrix();/*绘制一个球体*/glPushMatrix();gluQuadricDrawStyle(quadObj2,GLU_SILHOUETTE); glTranslatef(-5.0,-1.0,0.0);gluSphere(quadObj2,3.0,20.0,20.0);glPopMatrix();/*绘制一个圆盘*/glPushMatrix();gluQuadricDrawStyle(quadObj3,GLU_LINE); glTranslatef(-2.0,4.0,0.0);gluDisk(quadObj3,2.0,5.0,15.0,10.0);glPopMatrix();/*绘制一个部分圆盘*/glPushMatrix();gluQuadricDrawStyle(quadObj4,GLU_POINT); glTranslatef(-3.0,-7.0,0.0);gluPartialDisk(quadObj4,2.0,5.0,15.0,10.0,10.0,100.0); glPopMatrix();/*删除四个二次曲面物体对象*/gluDeleteQuadric(quadObj1);gluDeleteQuadric(quadObj2);gluDeleteQuadric(quadObj3);gluDeleteQuadric(quadObj4);glFlush();}void myReshape(int w,int h){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(45.0,(GLfloat)w/(GLfloat)h,1.0,50.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef(0.0,0.0,-25.0);}int main(int argc,char ** argv){/*初始化*/glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);glutInitWindowSize(400,400);glutInitWindowPosition(100,100);/*创建窗口*/glutCreateWindow(" DRAW QUADRIC OBJECTS ");/*绘制与显示*/myInit();glutReshapeFunc(myReshape);glutDisplayFunc(myDisplay);glutMainLoop();return 0;}·gluNewQuadric创建一个二次对象。
OpenGL_Qt学习笔记之_02(绘制简单平面几何图形)
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绘制⼀个⽴⽅体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基本图形的绘制
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编程基础(二)
OpenGL编程基础
显示点、直线和多边形: 三、多边形的细节 2. 设置点画多边形的函数: glPolygonStipple() 句法:void glPolygonStipple(const GLubyte *mask); 描述:定义填充多边形的当前点画模式。Mask参数是一 个指向32x32位图的指针,后者被解释为0和1的掩码。如果 模式中出现的是1,则多边形对应的像素就被绘制,如果模
OpenGL编程基础
显示点、直线和多边形: 二、直线的细节 直线的细节包括直线的宽度和不同点画模式的直线。 1. 设置直线的宽度函数: glLineWidth() 句法:void glLineWidth(GL float Width); 描述:设置被渲染直线的粗细,以像素为单位。Width必 须大于0.0,默认值为1.0 。在未使用反走样功能时,直线的
OpenGL编程基础
OpenGL基础函数
OpenGL图元绘制
OpenGL编程基础
显示点、直线和多边形: 一、点的细节 点的基本大小对应屏幕上的1个像素。使用glPointSize()函 数可设置被渲染点的大小。 句法:void glPointSize(GL float size); 描述:设置被渲染点的大小,以像素为单位。Size必须 大于0.0,默认值为1.0 。被渲染的点呈正方形方块。如果 启用了反走样或多重采样,被渲染的点呈圆形。调用函数 glEnable(),并将参数设置为GL_POINT_SMOOTH,启 用反走样。例:point
x[i ] xc r (cos(t ) t sin( t )) y[i ] yc r (sin( t ) t cos(t ))
绘制渐开线,如图所示。
opengl绘制三角形
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坐标的数据的集合。
12_2012三维图形学_OpenGL编程(2)
(1)OpenGL进行几何变换的基本方法。 在OpenGL中,一般使用矩阵左乘的方法描述图形进行 几何变换,矩阵右乘表达式与矩阵左乘表达式如下:
P1点经过矩阵T1、T2变换之后变成了P2点,
用矩阵右乘可以表示为 用矩阵左乘可以表示为
P2=P1T1T2; P2T=T2TT1TP1T ;
即矩阵左乘描述方法与矩阵右乘描述方法可以相互转
换,只需把各矩阵进行转置变换处理即可;
对于矩阵左乘描述方法,OpenGL的函数只需把T2T、T1T、 P1T依次推入OpenGL的矩阵乘法器中进行运算处理,最后 可求出P2T。这样处理,硬件设计简单。
2020/12/12
OpenGL编程2
1
(2)OpenGL提供下述函数供用户定义几何变换功能 函数
函数 void glTranslatef ( GLfloat x , GLfloat y , GLfloat z ); 表示图形分别沿x,y,z方向进行平移变换。
OpenGL还提供了直接定义变换矩阵与其矩阵元素等函 数,略。
2020/12/12
OpenGL编程2
2
(3)OpenGL提供矩阵堆栈功能,供用户使用 OpenGL为了便于用户编程操作矩阵运算,特提供了对 矩阵进行堆栈操作的功能,即 进栈矩阵函数 glPushMatrix() 出栈矩阵函数 glPopMatrix() 利用这两项操作,用户可以随时进栈保存矩阵乘法器当 前的矩阵参数,并在需要时恢复该矩阵的数据。 这样用户就能在OpenGL的编程过程中,对不同的图形 分别做不同的几何变换。 灯光在OpenGL中是一个没有几何形状、但有几何位置、 能发射光线的物体(需要灯光物体几何形状时另建几何模 型模拟),故灯光的几何位置,也能进行几何变换 看sample2.cpp程序清单 该程序在sample1.cpp的基础上扩展而来。
OpenGL入门教程(精)
4、把解压得到的 glut.dll 和 glut32.dll 放到操作系统目录下面的 system32 文件夹内。(典型的位置为: C:\Windows\Sy st em32) 第三步,建立一个 OpenGL 工程 这里以 VisualStudio2005 为例。 选择 File->New->Project,然后选择 Win32 Console Application,选择一个名字,然后按 OK。 在谈出的对话框左边点 Application Settings,找到 Empty project 并勾上,选择 Finish。 然后向该工程添加一个代码文件,取名为“OpenGL.c”,注意用.c 来作为文件结尾。 搞定了,就跟平时的工程没什么两样的。 第一个 OpenGL 程序
在 glutDisplayFunc 函数中,我们设置了“当需要画图时,请调用 myDisplay 函数”。于是 myDisplay 函数就 用来画图。观察 myDisplay 中的三个函数调用,发现它们都以 gl 开头。这种以 gl 开头的函数都是 OpenGL 的标准函数,下面对用到的函数进行介绍。 1、glClear,清除。GL_COLOR_BUFFER_BIT 表示清除颜色,glClear 函数还可以清除其它的东西,但这里 不作介绍。 2、glR ect f,画一个矩形。四个参数分别表示了位于对角线上的两个点的横、纵坐标。 3、glFlush,保证前面的 OpenGL 命令立即执行(而不是让它们在缓冲区中等待)。其作用跟 fflush(stdout) 类似。
OpenGL 入门教程
1.第一课:
说起编程作图,大概还有很多人想起 TC 的#include < graphics.h>吧? 但是各位是否想过,那些画面绚丽的 PC 游戏是如何编写出来的?就靠 TC 那可怜的 640*480 分辨率、16 色来做吗?显然是不行的。
浅谈怎样使用OpenGL绘制简单二维图形
浅谈怎样使用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进行曲线、曲面的绘制
⽤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绘制几何图形的一些细节问题
但也有一些表面比较特殊。例如“麦比乌斯带”(请自己Google一下),可以全部使用“正面”或全部使用“背面”来表示。
可以通过glFrontFace函数来交换“正面”和“反面”的概念。
0x10, 0x18, 0x18, 0x08,
0x10, 0x00, 0x00, 0x08 //这是最上面的一行
};
这样一堆数据非常缺乏直观性,我们需要很费劲的去分析,才会发现它表示的竟然是一只苍蝇。
如果将这样的数据保存成图片,并用专门的工具进行编辑,显然会方便很多。下面介绍如何做到这一点。
首先,用Windows自带的画笔程序新建一副图片,取名为mask.bmp,注意保存时,应该选择“单色位图”。在“图象”->“属性”对话框中,设置图片的高度和宽度均为32。
}
3、关于多边形
多边形的内容较多,我们将讲述以下四个方面。
(1)多边形的两面以及绘制方式。
虽然我们目前还没有真正的使用三维坐标来画图,但是建立一些三维的概念还是必要的。
从三维的角度来看,一个多边形具有两个面。每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点,其中“填充”是默认的方式。可以为两个面分别设置不同的方式。
glPolygonMode(GL_FRONT, GL_FILL); //设置正面为填充方式
glPolygonMode(GL_BACK, GL_LINE); //设置反面为边缘绘制方式
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); //设置两面均为顶点绘制方式
OpenGL入门学习之一至六(精排版可打印学习)
OpenGL入门学习之一至六OpenGL入门学习(一)OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX(微软公司对硬件编程的接口)更优越的特性。
1、与C语言紧密结合。
OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL是容易理解和学习的。
如果你曾经接触过TC的graphics.h,你会发现,使用OpenGL作图甚至比TC更加简单。
2、强大的可移植性。
微软的Direct3D虽然也是十分优秀的图形API,但它只用于Windows系统(现在还要加上一个XBOX游戏机)。
而OpenGL 不仅用于Windows,还可以用于Unix/Linux等其它系统,它甚至在大型计算机、各种专业计算机(如:医疗用显示设备)上都有应用。
并且,OpenGL 的基本命令都做到了硬件无关,甚至是平台无关。
3、高性能的图形渲染。
OpenGL是一个工业标准,它的技术紧跟时代,现今各个显卡厂家无一不对OpenGL提供强力支持,激烈的竞争中使得OpenGL性能一直领先。
总之,OpenGL是一个很NB的图形软件接口。
至于究竟有多NB,去看看DOOM3和QUAKE4等专业游戏就知道了。
下面将对Windows下的OpenGL编程进行简单介绍。
学习OpenGL前的准备工作第一步,选择一个编译环境现在Windows系统的主流编译环境有Visual Studio,Broland C++ Builder,Dev-C++等,它们都是支持OpenGL的。
但这里我们选择Visual Studio 2005作为学习OpenGL的环境。
第二步,安装GLUT工具包GLUT不是OpenGL所必须的,但它会给我们的学习带来一定的方便,推荐安装。
Windows环境下安装GLUT的步骤:1、将下载的压缩包解开,将得到5个文件2、在“我的电脑”中搜索“gl.h”,并找到其所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\PlatformSDK\include\gl文件夹”)。
OpenGL图形编程2基本图形绘制(陈永强)只是分享
这个函数采用一个参数来指定画点时以象素为单位的近似 直径。
7
2.2点的绘制
点的属性(大小)
通常使用下面的代码来获取点大小的范围和它们之间最小的中间值:
GLfloat sizes[2]; //保存绘制点的尺寸范围
GLfloat step;
将指定的各个顶点用于创建单个的点
GL_LINES GL_LINE_STRIP GL_LINE_LOOP
GL_TRIANGLES
将指定的顶点用于创建线段。每两个顶点指定一条单独的线 段。如果顶点个数是奇数,则忽略后一个
将指定的顶点用于创建线条。第一个顶点之后的每个顶点指 定的是线条延伸到的下一个点
特性和GL_LINE_STRIP 相似,只不过最后一条线段是在 指定的后一个和第一个顶点之间绘制。典型情况下,这用于 绘制那些可能违反了 GL_POLYGON 用法规则的封闭区域
glBegin(GL_LINE_STRIP); glVertex3f(0.0f,0.0f,0.0f); glVertex3f(10.0f,10.0f,0.0f); glVertex3f(20.0f,5.0f,0.0f);
glEnd();
在xy平面内绘制了两条直线(0,0,0)到(10,0,0)和(0,10,0)到(20,5,0)。
OpenGL图形编程2基本图形绘 制(陈永强)
2.1glBegin/glEnd
OpenGL的图元绘制放在函数glBegin和 glEnd之间,由函数glBegin的参数指定绘制 图元的类型。
2.1glBegin/glEnd
模式
GL_POINTS
表 glBegin可支持的OpenGL图元
OpenGL基本几何图形的绘制
2020/7/1
2
3终都是通过一组有序顶点来描述的。 OpenGL中有十种基本图元,从空间中绘制的简单的 点到任意边数的封闭多边形。用glBegin命令可告诉 OpenGL开始把一组顶点解释为特定图元。然后用 glEnd命令结束该图元的顶点列表。
glEnd();
100 150 200
2020/7/1
8
3.4.2 线的绘制(续)
连接线段的绘制:
glColor3f(1.0,0.0,0.0);
glLineWidth(5.0);
200
glBegin(GL_LINE_STRIP);
150
glVertex3f(0.0,0.0,0.0);
100
glVertex3f(50.0,50.0,0.0);
glVertex3f(-10.0,5.0,0.0);
glVertex3f(-10.0, 0.0,0.0);
glEnd();
2020/7/1
12
3.4.3 多边形的绘制(续)
四边形的绘制:
✓OpenGL中的GL_QUADS图元用来绘制一个四边形。 与三角形一样,GL_QUADS_STRIP图元指定一条相互连 接的四边形。 ✓由于矩形在图形应用中非常普遍,它不必通过glBegin 和glEnd之间的顶点来进行绘制,而是通过使用如下的函 数:
10
3.4.3 多边形的绘制
三角形的绘制:
glColor3f(1.0,0.0,0.0);
glBegin(GL_TRIANGLES); glVertex3f(0.0,0.0,0.0); glVertex3f(5.0,5.0,0.0); glVertex3f(10.0, 0.0,0.0);
3.4 OpenGL基本几何图形的绘制-08
Pointjx.exe
2006
4
3.4.2 3.4.2 线的绘制
线属性
void glLineWidth(GLfloat width); 以象素为单位设置线绘制的宽度。 以象素为单位设置线绘制的宽度。 void glLineStipple(GLint factor,GLushort pattern); 指定点画模式(线型)。 指定点画模式(线型)。 指定线型模式中每位的乘数。factor的值在 的值在[1,255] factor 指定线型模式中每位的乘数。factor的值在[1,255] 之间,缺省值为1 之间,缺省值为1。 16位整数指定位模式 位为1 位整数指定位模式。 指定要绘; pattern 用16位整数指定位模式。位为1时,指定要绘;位 指定不绘。缺省时,全部为1 位模式从低位开始。 为0时,指定不绘。缺省时,全部为1。位模式从低位开始。
2006
3
3.4.1 点的绘制( 3.4.1 点的绘制(续) 点的绘制: 点的绘制:
glBegin(GL_POINTS); glVertex3f(0.0,0.0,0.0); glVertex3f(5.0,5.0,5.0); glEnd(); 在绘制一个点时,点的大小的默认值是一个像素。 在绘制一个点时,点的大小的默认值是一个像素。可以用 函数glPointSize()来对点的大小进行修改。函数如下: 来对点的大小进行修改。 函数 来对点的大小进行修改 函数如下: void glPointSize(GLfloat size); 该命令以像素为单位设置绘制点的大小。 该命令以像素为单位设置绘制点的大小。
OpenGL画直线、圆、椭圆
使用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维的平面上。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
假设现在我已经指定了若干顶点,那么 OpenGL 是如何知道我想拿这些顶点来干什么呢?是 一个一个的画出来,还是连成线?或者构成一个ቤተ መጻሕፍቲ ባይዱ边形?或者做其它什么事情?
为了解决这一问题,OpenGL 要求:指定顶点的命令必须包含在 glBegin 函数之后,glEnd 函 数之前(否则指定的顶点将被忽略)。并由 glBegin 来指明如何使用这些点。 例如我写: glBegin(GL_POINTS);
OpenGL 入门学习之二——绘制几何图形 2009-01-07 11:25 一、点、直线和多边形 我们知道数学(具体的说,是几何学)中有点、直线和多边形的概念,但这些概念在计算机 中会有所不同。 数学上的点,只有位置,没有大小。但在计算机中,无论计算精度如何提高,始终不能表示 一个无穷小的点。另一方面,无论图形输出设备(例如,显示器)如何精确,始终不能输出 一个无穷小的点。一般情况下,OpenGL 中的点将被画成单个的像素(像素的概念,请自己 搜索之~),虽然它可能足够小,但并不会是无穷小。同一像素上,OpenGL 可以绘制许多 坐标只有稍微不同的点,但该像素的具体颜色将取决于 OpenGL 的实现。当然,过度的注意 细节就是钻牛角尖,我们大可不必花费过多的精力去研究“多个点如何画到同一像素上”。 同样的,数学上的直线没有宽度,但 OpenGL 的直线则是有宽度的。同时,OpenGL 的直线 必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL 的“直线”概念与 数学上的“线段”接近,它可以由两个端点来确定。 多边形是由多条线段首尾相连而形成的闭合区域。OpenGL 规定,一个多边形必须是一个 “凸多边形”(其定义为:多边形内任意两点所确定的线段都在多边形内,由此也可以推导 出,凸多边形不能是空心的)。多边形可以由其边的端点(这里可称为顶点)来确定。(注 意:如果使用的多边形不是凸多边形,则最后输出的效果是未定义的——OpenGL 为了效率, 放宽了检查,这可能导致显示错误。要避免这个错误,尽量使用三角形,因为三角形都是凸 多边形)
/* 在这里使用 glVertex*系列函数 */ /* 指定你所希望的顶点位置 */ glEnd(); glFlush(); } 把这段代码改成你喜欢的样子,然后用它替换第一课中的 myDisplay 函数,编译后即可运行。
两个例子 例一、画一个圆 /* 正四边形,正五边形,正六边形,……,直到正 n 边形,当 n 越大时,这个图形就越接近圆 当 n 大到一定程度后,人眼将无法把它跟真正的圆相区别 这时我们已经成功的画出了一个“圆” (注:画圆的方法很多,这里使用的是比较简单,但效率较低的一种) 试修改下面的 const int n 的值,观察当 n=3,4,5,8,10,15,20,30,50 等不同数值时输出的变化情况 将 GL_POLYGON 改为 GL_LINE_LOOP、GL_POINTS 等其它方式,观察输出的变化情况 */ #include <math.h> const int n = 20; const GLfloat R = 0.5f; const GLfloat Pi = 3.1415926536f; void myDisplay(void) {
PointA[2] = { 0, a }, PointB[2] = { bx, by }, PointC[2] = { 0.5, cy }, PointD[2] = { -0.5, cy }, PointE[2] = { -bx, by };
glClear(GL_COLOR_BUFFER_BIT); // 按照 A->C->E->B->D->A 的顺序,可以一笔将五角星画出 glBegin(GL_LINE_LOOP);
glVertex2f(0.0f, 0.0f); glVertex2f(0.5f, 0.0f); glEnd(); 则这两个点将分别被画出来。如果将 GL_POINTS 替换成 GL_LINES,则两个点将被认为是 直线的两个端点,OpenGL 将会画出一条直线。 我们还可以指定更多的顶点,然后画出更复杂的图形。
另一方面,glBegin 支持的方式除了 GL_POINTS 和 GL_LINES,还有 GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRI ANGLE_FAN 等,每种方式的大致效果见下图:
声明:该图片来自 ,该图片是《OpenGL 编程指南》一书的附图,由于该书 的旧版(第一版,1994 年)已经流传于网络,我希望没有触及到版权问题。
可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧 看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样 一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个 “曲面”。 二、在 OpenGL 中指定顶点 由以上的讨论可以知道,“点”是一切的基础。 如何指定一个点呢?OpenGL 提供了一系列函数。它们都以 glVertex 开头,后面跟一个数字 和 1~2 个字母。例如: glVertex2d glVertex2f glVertex3f glVertex3fv 等等。 数字表示参数的个数,2 表示有两个参数,3 表示三个,4 表示四个(我知道有点罗嗦~)。 字母表示参数的类型,s 表示 16 位整数(OpenGL 中将这个类型定义为 GLshort),
GLfloat a = 1 / (2-2*cos(72*Pi/180)); GLfloat bx = a * cos(18 * Pi/180); GLfloat by = a * sin(18 * Pi/180); GLfloat cy = -a * cos(18 * Pi/180); GLfloat
本课讲述了点、直线和多边形的概念,以及如何使用 OpenGL 来描述点,并使用点来描述几 何图形。
大家可以发挥自己的想象,画出各种几何图形,当然,也可以用 GL_LINE_STRIP 把很多位 置相近的点连接起来,构成函数图象。如果有兴趣,也可以去找一些图象比较美观的函数,
自己动手,用 OpenGL 把它画出来。
glVertex2fv(PointA); glVertex2fv(PointC); glVertex2fv(PointE); glVertex2fv(PointB); glVertex2fv(PointD); glEnd(); glFlush(); }
例三、画出正弦函数的图形 /* 由于 OpenGL 默认坐标值只能从-1 到 1,(可以修改,但方法留到以后讲) 所以我们设置一个因子 factor,把所有的坐标值等比例缩小, 这样就可以画出更多个正弦周期
glVertex2f(-1.0f, 0.0f); glVertex2f(1.0f, 0.0f); // 以上两个点可以画 x 轴 glVertex2f(0.0f, -1.0f); glVertex2f(0.0f, 1.0f); // 以上两个点可以画 y 轴 glEnd(); glBegin(GL_LINE_STRIP); for(x=-1.0f/factor; x<1.0f/factor; x+=0.01f) { glVertex2f(x*factor, sin(x)*factor); } glEnd(); glFlush(); } 小结
(四)glVertex4f(1.0f, 3.0f, 0.0f, 1.0f); (五)GLfloat VertexArr3[] = {1.0f, 3.0f, 0.0f};
glVertex3fv(VertexArr3); 以后我们将用 glVertex*来表示这一系列函数。 注意:OpenGL 的很多函数都是采用这样的形式,一个相同的前缀再加上参数说明标记,这 一点会随着学习的深入而有更多的体会。
int i; glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); for(i=0; i<n; ++i)
glVertex2f(R*cos(2*Pi/n*i), R*sin(2*Pi/n*i)); glEnd(); glFlush(); }
例二、画一个五角星 /* 设五角星的五个顶点分布位置关系如下:
A EB
DC 首先,根据余弦定理列方程,计算五角星的中心到顶点的距离 a (假设五角星对应正五边形的边长为.0) a = 1 / (2-2*cos(72*Pi/180)); 然后,根据正弦和余弦的定义,计算 B 的 x 坐标 bx 和 y 坐标 by,以及 C 的 y 坐标 (假设五角星的中心在坐标原点) bx = a * cos(18 * Pi/180); by = a * sin(18 * Pi/180); cy = -a * cos(18 * Pi/180); 五个点的坐标就可以通过以上四个量和一些常数简单的表示出来 */ #include <math.h> const GLfloat Pi = 3.1415926536f; void myDisplay(void) {
i 表示 32 位整数(OpenGL 中将这个类型定义为 GLint 和 GLsizei), f 表示 32 位浮点数(OpenGL 中将这个类型定义为 GLfloat 和 GLclampf), d 表示 64 位浮点数(OpenGL 中将这个类型定义为 GLdouble 和 GLclampd)。 v 表示传递的几个参数将使用指针的方式,见下面的例子。 这些函数除了参数的类型和个数不同以外,功能是相同的。例如,以下五个代码段的功能是 等效的: (一)glVertex2i(1, 3); (二)glVertex2f(1.0f, 3.0f); (三)glVertex3f(1.0f, 3.0f, 0.0f);
试修改 factor 的值,观察变化情况 */ #include <math.h> const GLfloat factor = 0.1f;