利用opengl绘制三维图形的基本图元绘制一个圆柱

openGl从零开始之基本图元 - 推酷
openGl从零开始之基本图元
从本篇开始,会给出一些代码实例,所以要配置好编译环境。
环境配置:vs2012下配置链接
vc++6.0下配置链接
在给出具体的绘图代码之前,先讲解一下创建一个openGl程序窗口的初始化,在上一篇文章里已经介绍了,这里再贴一遍。
void display(void)
//这是我们自己的绘图函数,我们在这里进行具体地绘制。
int main(int argc, char** argv)
glutInit(&argc, argv);
//对GLUT进行初始化,必须一开始就初始化
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
//设置显示方式,参数之后再解释
glutInitWindowPosition(100, 100);
//设置程序窗口在屏幕中的位置
glutInitWindowSize(400, 400);
//设置程序窗口的大小
glutCreateWindow(&第一个OpenGL程序&);
//给程序窗口添加标题
glutDisplayFunc(&display);
//*调用我们自己的绘图函数来绘制
glutMainLoop();
//启动消息循环后程序运行起来
OpenGL的基本图元有 点(Point)、线段(Line)、多边形(Ploygon)、三角形(Triangle)、四边形(Quadrangle) 。组成关系我想大部分人都能够理解:
①无数个“点”的线性排列组成----“线段”
②多个“线段”可以围成一个“多边形”
③多个“多边形”在三维空间中可以围成“多面体”
有此,可以看出, 点是最基本的图元 ,其他的图元都是由顶点组合构成的,因此我们从点开始介绍。
在OpenGL中,“点”称为 顶点(Vertex) ,通常用一个形如(x, y, z)的三维坐标值表示。
有时候会采用齐次坐标表示,就是一个形如(x, y, z, w)的四元组,可以这样理解这个四元组,前面的(x,y,z)表示“点”所在的方向,而w表示在该方向上的距离比例,所以(x, y, z, w)表示的实际坐标值就是(x/w, y/w, z/w)坐标点。如果w为0,则表示方向为(x, y, z)的无穷远点;如果w=10,表示取(x,y,z)的十分之一作为坐标点(x/10,y/10,z/10)。
一般情况 下,OpenGL 中的点将被画成单个的像素。实际上点还可以更小,虽然它可能足够小,但并不会是无穷小,一个像素内可以描绘多个点,取决于对点大小的设定,默认一个点的大小为一个像素。
当然我们也可以改变点的大小,函数原型为:
//size 必须大于 0.0f,默认值为 1.0f,单位为“像素”。
//对于具体的 OpenGL 实现,点的大小都有个限度的,如果设置的 size 超过最大值,则设置可能会有问题,一般情况是不在增大。
void glPointSize(GLfloat size);
代码实现画一个点,我们只需要在我们的绘图函数中添加如下代码即可:
void display(void)
glPointSize(5);//在绘制之前要设置要相关参数,这里设置点的大小为5像素
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f); //OpenGl内的点是齐次坐标的四元组,缺省的z坐标为0.0f,w为1.0f,所以该点为(1, 2, 0, 1)
glVertex2f(0.0f, 0.5f); //绘制的第二个点
glVertex2f(0.5f, 0.25f); //绘制的第三个点
glFlush();//glFlush,保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)
需要注意的是:坐标的值默认是1.0为最大,即屏幕边缘,所以如果大于1,则会超出屏幕,这时候除非改变观察点,否则是看不到的。(0,0)表示在屏幕的中间,也就是坐标系原点。
OpenGL中绘制几何图元,必须使用 glBegain() 和 glEnd() 这一对函数,glBegin() 和 glEnd() 需要成对使用,两者之间是绘图语句。
glBegin()的参数 就是需要绘制的图元类型,它决定了在glBegin()和glEnd()之间绘图的点将如何组织成目标图元,如参数为“GL_POINTS”,表示每一个点都是独立的,互不相连的,因此也就绘制出了一个个“点”。
线段是由两个顶点连接起来形成的图元。线段间的连接方式有三种:
①独立线段:图元类型参数--
②线段间首尾相连但最终不闭合:折线,图元类型参数--
GL_LINE_STRIP
③线段间首尾相连最终封口闭合:图形,图元类型参数--
GL_LINE_LOOP
对应的图例:
线段代码实例:
void display(void)
/*同样用5个点,画出不同类型的线段组合*/
//独立线段,5个点能画出2条线段
glBegin(GL_LINES);
glVertex2f(-0.8f, -0.5f);
glVertex2f(-0.5f, -0.5f);
glVertex2f(-0.8f, 0.0f);
glVertex2f(-0.5f, 0.0f);
glVertex2f(-0.8f, 0.5f); //最后的这个点没有与之配对的点,无法连成线段,所以不会被画出来,在独立线段模式下被舍弃
//连续不闭合折线,5个点能画出4条线段
glBegin(GL_LINE_STRIP);
glVertex2f(-0.3f, -0.5f); //起始点
//后面的每一个点都会与前一个相连生成一条线段
glVertex2f(-0.0f, -0.5f);
glVertex2f(-0.3f, 0.0f);
glVertex2f(-0.0f, 0.0f);
glVertex2f(-0.3f, 0.5f);
//连续闭合折线,5个点能画出5条线段
glBegin(GL_LINE_LOOP);
glVertex2f(0.2f, -0.5f); //起始点
//后面的每一个点都会与前一个相连生成一条线段
glVertex2f(0.5f, -0.5f);
glVertex2f(0.2f, 0.0f);
glVertex2f(0.5f, 0.0f);
//最后一个点不仅与前一个点相连,还与起始点相连,形成闭合
glVertex2f(0.2f, 0.5f);
glFlush();//保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)
程序运行示例图:
同样的, 直线可以指定宽度:
void glLineWidth(GLfloat width); //width表示线宽,单位:像素
特殊的是线除了直线,还有
。可以用虚线连接两个点。
在绘制虚线之前必须先启动“虚线模式”:glEnable( GL_LINE_STIPPLE );
虚线有不同的类型,调节函数如下:
参数pattern是16位二进制数(0或1),如OxAAAA表示1010
从低位开始,每一个二进制位代表一个像素, 1表示用当前颜色绘制一个像素,0表示当前不绘制,只移动一个像素位,中间留下一个像素的空白
factor是用来调节二进制位0和1代表的像素个数,如果factor为2,则表示遇到二进制1的时候用当前颜色绘制两个像素,0移动两个像素不绘制
void glLineStipple(GLint factor,GLushort pattern);
void display(void)
//开启虚线模式
glEnable(GL_LINE_STIPPLE);
//调节虚线类型参数
glLineStipple(2,0xAAAA);
//调节线宽
glLineWidth(3);
//绘制一条虚线
glBegin(GL_LINES);
glVertex2f(0,0);
glVertex2f(0.5,0.5);
glFlush();//保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)
程序运行示例:
类似于点组合线段的方式,OpenGL定义的多边形是由多个点连接成线段再围成封闭区域。
多边形有两种:凸多边形(指多边形任意非相邻的两点的连线位于多边形的内部)和凹多边形,但 OpenGL中规定的多边形必须是凸多边形 。
但有时需要绘制一些凹多边形,通常解决的办法是对它们进行分割,用多个三角形来组合替代。显然,绘制这些三角形时,有些边不应该进行绘制,否则,多边形内部就会出现多余的线框。OpenGL提供的解决办法是通过设置边标志命令glEdgeFlag()来控制某些边产生绘制,而另外一些边不产生绘制,这里只需知道有这个工能,具体细节待遇到在研究,接下来看重点。
(1)连接方式
&1&按点的定义顺序依次连接:图元类型参数--
GL_POLYGON
&2&从第1个点开始,每三个点一组画一个三角形,三角形之间是独立的:图元类型参数--
GL_TRIANGLES
&3&从第三个点开始,每点与前面的两个点组合画一个三角形,即线性连续三角形串:图元类型参数--
GL_TRIANGLE_STRIP
&4&从第三个点开始,每点与前一个点和第一个点组合画一个三角形,即扇形连续三角形:图元类型参数--
GL_TRIANGLE_FAN
对应的图例:
四边形的绘制模式和三角形类似。
(2)多边形的正反两面
多边形为什么会有正反面这一说法呢?举个简单的例子。
虽然多边形是二维的,但是我们知道三维物体可以理解为多边形围成的,也就是说在三维空间物体上有二维多边形的存在。
一张“正方形”纸片,如果极限的薄,我们可以认为是一个多边形(正方形),那么纸仍然会存在两面,纸的正反面。更具体一点,如果我们用同大小6张正方形的纸片围成一个正方体,那么正方体的任何一个面都是一个多边形,而且这个多边形是有正反面,朝外的你能看到的部分是正面(假设),那么朝内的看不到的那部分就是反面。同样的道理,OpenGL要区分多边形的正反面。那么到底怎么定义正面或者反面呢?
有一个函数来定义:
glFrontFace(GL_CCW);//设置点序列逆时针方向围成的多边形为正面
glFrontFace(GL_CW); //设置点序列顺时针方向围成的多边形为正面
设置这个的原因是,默认情况下,OpenGL绘制三维物体时两面都会绘制,而实际的时候很多面我们是看不到的,如物体朝内方向的多边形,还有一些物体间遮挡的情况导致有些多边形是不可见的,因此为了提高性能,我们需要剔除这些不必要的绘制。
glEnable(GL_CULL_FACE); //来启动剔除功能
glCullFace(); //参数可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK,表示剔除多边形的哪种面,设定后该类型的多边形不绘制
(3)绘制模式
常用的多边形绘制模式有: 填充式(默认) 、 轮廓线式 、 顶点式 和
镂空图案填充式 。
前三种都是使用glPolygonMode()函数来指定模式,最后一种比较特殊。
void glPolygonMode(GLenum face,GLenum mode);//该函数要求说明是对多边形哪一个面是定face设置模式
画一个三角形,设置不同的绘制模式,看一下效果:
void myDisplay(void)
//设置点的大小,以便容易观察
glPointSize(5);
//设置正面的绘制模式为:填充式,反面不设定则默认为填充式
glPolygonMode(GL_FRONT,GL_FILL);
glBegin(GL_POLYGON);
glVertex2f(0,0);
glVertex2f(0,0.3);
glVertex2f(-0.3,0.3);
glVertex2f(-0.3,0);
//设置正面的绘制模式为:轮廓线式
glPolygonMode(GL_FRONT,GL_LINE);
glBegin(GL_POLYGON);
glVertex2f(0.5,0);
glVertex2f(0.5,0.3);
glVertex2f(0.2,0.3);
glVertex2f(0.2,0);
//设置正面的绘制模式为:顶点式
glPolygonMode(GL_FRONT,GL_POINT);
glBegin(GL_POLYGON);
glVertex2f(0.9,0);
glVertex2f(0.9,0.3);
glVertex2f(0.6,0.3);
glVertex2f(0.6,0);
glFlush();
关于最后一种镂空图案样式,有点类似于线段中的虚线,这里只不过是针对多边形内部区域进行像素点的绘制与否,来做镂空效果。具体的细节还需查阅资料。
以上为基本图元的知识讲解,并给出了针对性的代码实例,在此基础之上会进一步学习更加复杂的图形绘制。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致下次自动登录
现在的位置:
& 综合 & 正文
OpenGL4.x学习之使用着色器、绑定VAO以及绘制最简单的图元——点
OpenGL4.x学习之使用着色器、绑定VAO以及绘制最简单的图元——点
OpenGL4.x是OpenGL系列最新的规范,它为此制定了很多的概念,包括6种着色器、以及诸多内存对象,让简单的三维显示变得不简单。我也是刚刚了解这些新的特性,所以有的地方阐述不正确还请高手们指出来。
原创,反对未声明的引用。原博客地址:
下载地址:
这次我将沿用,在此基础上添加着色器的载入和使用、创建和绑定VAO以及绘制最简单的图元——点。我使用的框架是Qt,而从Qt5.2起,对OpenGL的封装算是很全面了,因此程序可以使用Qt封装的C++风格的类进行实现。不过我打算使用裸的OpenGL的API,因为这更容易被那些使用其他框架开发的同行们理解。
下面是例子程序的核心:
/*---------------------------------------------------------------------------*/
// 这里存放了一些全局变量
GLuint g_VertexShader = 0;
GLuint g_FragmentShader = 0;
GLuint g_Program = 0;
GLuint g_VertexArray = 0;
/*---------------------------------------------------------------------------*/
inline QByteArray ShaderData( const QString& fileName )
QFile shaderFile( fileName );
if ( shaderFile.open( QIODevice::ReadOnly ) )
result = shaderFile.readAll( );
shaderFile.close( );
/*---------------------------------------------------------------------------*/
void GLWindow::InitGL( void )
// 初始化顶点着色器
QByteArray vsData = ShaderData( ":/Shader.vert" );
const char* vsPointer = vsData.constData( );
g_VertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( g_VertexShader,
// 着色器标识
// 着色器文本数目
&vsPointer,
// 着色器字符串指针
Q_NULLPTR );
// 字符串长度
glCompileShader( g_VertexShader );
// 初始化片断着色器
QByteArray fsData = ShaderData( ":/Shader.frag" );
const char* fsPointer = fsData.constData( );
g_FragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( g_FragmentShader,
// 着色器标识
// 着色器文本数目
&fsPointer,
// 着色器字符串
Q_NULLPTR );
// 字符串长度
glCompileShader( g_FragmentShader );
// 初始化着色器程序
g_Program = glCreateProgram( );
glAttachShader( g_Program, g_VertexShader );
glAttachShader( g_Program, g_FragmentShader );
glLinkProgram( g_Program );
// 删除着色器
glDeleteShader( g_VertexShader );
glDeleteShader( g_FragmentShader );
// 初始化顶点数组对象(VAO)
glGenVertexArrays( 1, &g_VertexArray );
glBindVertexArray( g_VertexArray );
glPointSize( 10.0f );
/*---------------------------------------------------------------------------*/
void GLWindow::ResizeGL( int width, int height )
glViewport( 0, 0, width, height );
/*---------------------------------------------------------------------------*/
void GLWindow::RenderGL( void )
static const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glClearBufferfv( GL_COLOR, 0, black );
glUseProgram( g_Program );
glDrawArrays( GL_POINTS, 0, 1 );
/*---------------------------------------------------------------------------*/
void GLWindow::ReleaseGL( void )
glDeleteVertexArrays( 1, &g_VertexArray );
glDeleteProgram( g_Program );
程序在InitGL()函数中创建了顶点着色器和片断着色器对象并且用着色器程序将其链接起来。最后初始化了顶点数组对象(Vertex Array Object,VAO),并且绑定之,以及设定了点的大小。而顶点着色器和片断着色器在本例中也非常的简单:
Shader.vert
#version 430 core
void main( void )
gl_Position = vec4( 0.0, 0.0, 0.0, 1.0 );
Shader.frag
#version 430 core
void main( void )
color = vec4( 1.0, 1.0, 1.0, 1.0 );
顶点着色器中指明了绘制图元的位置在三维点( 0, 0, 0 )上,片断着色器中表示绘制的颜色是不透明的白色。与OpenGL(ES) 2.x不同,着色器不再用varying来表示从某一着色器到另外一着色器传递数据,而是使用in表示传入数据,out表示数据传入下一阶段。以下是程序的演示效果:
&&&&推荐文章:
【上篇】【下篇】君,已阅读到文档的结尾了呢~~
计算机图形学_第六章&#x5..
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
计算机图形学_第六章_OpenGL基本图元的绘制
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 opengl绘制圆柱体 的文章

 

随机推荐