opengl 教程(2) 在窗口画点

      原文地址:http://ogldev.atspace.co.uk/www/tutorial02/tutorial02.html

      通常在写OpenGL程序时候,我们都需要glew库,该库包装了OpenGL的各种扩展,便于我们使用。 我们可以在main函数中调用glew初始化函数,之后就可以查询OpenGL各种扩展能否使用了,对于能够使用的函数,可以动态的加载。

      在这篇教程中,我们首先了解一下顶点缓冲对象(VBO,vertex buffer object)的用法。在计算机图形学的3D世界中,三维物体对象都是由一系列顶点组成的,比如武士模型、城堡模型等等(注意下面两副图),这些顶点相连接,组成mesh(三角形)。

      顾名思义,顶点缓冲就是保存顶点的内存对象,通常VBO是GPU显存中的一块区域,使用VBO可以加速顶点的读取速度。

 

     在本篇教程和下一篇教程中,我们仅使用OpenGL中固定管线(相对固定管线的是可编程管线)的编程方法分别来画一个点和一个三角形。我们并没有对所渲染的物体(就是一个点或一个三角形)进行平移、缩放、旋转等操作,实际上我们只是在归一化的裁剪空间中来安排我们的物体,可以把归一化的裁剪空间看成一个正方体,坐标原点在正方形的中心,x, y,z坐标的范围都是[-1.0,1.0],我们把物体映射到屏幕空间(可以看作立方体中的物体先投影到z=-1的面上,然后该面的四边形映射到屏幕空间),比如屏幕空间是1024*768,则x坐标-1,映射到0,+1映射到1023,x和y等于0的点,则被映射到屏幕中心,最终根据draw函数中指定的体元语义,通过光栅化操作,把物体在屏幕空间画出来。

    下面我们看下程序的部分源代码实现:

#include <GL/glew.h>

首先我们要包含glew头文件,注意我们要把这个头文件放在freee_glut.h的前面,否则的话,程序编译有可能出错。

#include "math_3d.h"

在这篇教程中,我们画一个顶点,顶点结构在math_3d.h中定义。

GLenum res = glewInit();
if (res != GLEW_OK)
{
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}

上面是glew初始化的代码,如果初始化失败,则会输出错误信息,注意:glew初始化代码必须在glut初始化之后。

Vector3f Vertices[1];
Vertices[0] = Vector3f(0.0f, 0.0f, 0.0f);

我们创建了一个顶点数组,该数组只有一个元素,其顶点坐标X,Y,Z都为0,后面我们将会看到这个点在屏幕中心位置显示。

GLuint VBO;

我们定义一个GLuint类型的全局变量VBO来表示顶点缓冲,通常情况下,OpenGL对象都是用一个GLuint类型的变量表示。

glGenBuffers(1, &VBO);

     在OpenGL中,都是通过glGen*类型的函数产生各种各样的对象,这类函数有2个参数,第一个参数指定你要创建对象的数量,第二个参数是一个GLuint类型数组的地址,该地址中存放着driver分配给你的各种对象句柄。driver会保证将来再调用该函数时不会产生相同的对象句柄,除非你调用函数glDeleteBuffers显示删除对象句柄。

glBindBuffer(GL_ARRAY_BUFFER, VBO);

     在OpenGL中,通常把一个对象绑定到一个target name,比如把VBO对象绑定到GL_ARRAY_BUFFER(表示缓冲是顶点数组,另一个常用的target name是GL_ELEMENT_ARRAY_BUFFER,表示索引数组),然后在这个target name上执行命令,这些命令将会一直影响绑定的对象,除非我们把该target name绑定到一个新的对象,此时,在target name上执行命令,将会影响新绑定的对象。

glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

      绑定对象后,我们开始准备顶点缓冲数据,上面的函数中,我们用Vertices中的数据填充顶点缓冲,其中GL_STATIC_DRAW表示,这些顶点数据渲染过程中不会改变,相对应的是GL_DYNAMIC_DRAW,driver会根据这些状态对程序进行一定的优化。

glEnableVertexAttribArray(0);

     在后面的shader程序中,我们将看到更详细的顶点属性介绍,在本教程的例子中,我们没有使用shader,但是我们在顶点缓冲中装入了顶点位置,位置属性就作为顶点属性的index 0(注意:由于没有shader,我们此时用的是固定管线渲染),所以必须打开它,否则不能使用,因为所有的顶点属性在使用前都必须打开。

glBindBuffer(GL_ARRAY_BUFFER, VBO);

     再一次绑定顶点缓冲,当然也可以不绑定,因为我们只有一个缓冲,前面已经绑定过了,但是在大型3D程序中,可能有很多顶点缓冲,就需要在渲染前,根据实际需要,切换绑定不同的顶点缓冲对象。

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

     这个函数告诉管线,怎么解释顶点缓冲中的数据。第一个参数指定属性的索引,第二个参数是属性的数量(3,表示,x,y,z),第三个参数是属性的数据类型,第四个参数是属性是否是归一化的,第五个参数是stride,表示两个连续属性实例之间的字节数目,如果值为0,那么顶点属性会被理解为:它们是紧密排列在一起的。最后一个参数offset,就是该属性从第几个字节开始,如果有2个属性,那么对于第一个属性,该值为0,没有偏移,对于第二个属性为12,因为第一个属性有12byte,偏移12byte后的位置即为第二个属性。

OpenGL函数。
void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,const GLvoid * pointer);
参数:
index
指定要修改的顶点属性的索引值
size
指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
type
指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。
normalized
指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。
stride
指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
pointer
指定第一个组件在数组的第一个顶点属性中的偏移量。该数组与GL_ARRAY_BUFFER绑定,储存于缓冲区中。初始值为0;

glDrawArrays(GL_POINTS, 0, 1);

      最后,我们调用draw函数,该函数是GPU开始工作的起始点,GPU将绑定draw函数的参数以及状态等数据,然后通过driver传递到GPU。OpenGL有几种形式的draw函数,通常它们可以划分为ordered draws和indexed draws。ordered draw函数就是把指定的顶点按语义顺序画一遍,比如你指定GL_TRIANGLES ,则0-2顶点为第一个三角形,3-5顶点为第二个三角形等等。而Index draws要通过索引缓冲来索引顶点数据(实际上,在硬件层次,没有无索引的draw实现,如果没有指定索引缓冲,硬件会按照顶点的顺序,生成一个和顶点顺序对应的索引),这样可以重复利用顶点数据,比如我们可以用四个点来表示一个四边形(2个三角形组成),其中2个点是2个三角形共享的,索引缓冲中的数据为顶点在顶点缓冲中的位置。

    我们调用DrawArrays函数画一个点,第一个参数指定体元语义,画的是点,第二个参数是第一个顶点的索引位置,第三个参数是要渲染的顶点的数量。

glDisableVertexAttribArray(0);

不使用顶点属性的时候,记得要关闭它,以免引起未知的一些错误。

 

程序执行后,界面如下,在窗口中心,有一个小的几乎看不见的白点。

我们也可以加入下面的代码,设置点的大小以及设置点为圆点。

//下面四行代码,设置点的大小,以及启动alpha blend以及多采样,这样可以画圆形的点

glEnable( GL_POINT_SMOOTH );

glEnable( GL_BLEND );

glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

glPointSize(8.0f);

时间: 2024-10-02 20:13:04

opengl 教程(2) 在窗口画点的相关文章

opengl 教程(3) 在窗口画三角形

    原文地址:http://ogldev.atspace.co.uk/www/tutorial03/tutorial03.html       本教程内容很少,主要是在教程2基础上渲染一个三角形.    在前面一个教程中,我们在归一化的裁剪空间中定义一个顶点,这样就省去一些坐标变化操作,但不能省去的操作是视口变化.我们从z轴正方向向负方向看去,裁剪空间类似下图的样子,裁剪空间盒子中的三维物体先投影到该平面上,然后通过视口变化映射到屏幕空间,点(-1.0,1.0)被映射到屏幕的左上角,(-1.

opengl 教程(1) 创建窗口

本章教程内容主要来自:http://ogldev.atspace.co.uk/www/tutorial01/tutorial01.html 使用OpenGL之前,请先安装和设置好FreeGlut和glew, 下载地址: http://freeglut.sourceforge.net/ http://glew.sourceforge.net/   原教程源码下载地址:http://ogldev.atspace.co.uk/ogldev_win.zip          OpenGL做为3D图形接口

NeHe的OpenGL教程1(Bang翻译Delphi版)-如何绘制OpenGL窗口

NeHe的OpenGL教程1(Bang翻译Delphi版)-如何绘制OpenGL窗口 在这个教程里,我将教你在Windows环境中创建OpenGL程序.它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出.它是我们以后应用程序的框架.如下图: program lesson1a; {    OpenGL DelphiXE    出处:根据NeHe代码翻译而来(http://nehe.gamedev.net/)    作者:帅宏军 shuaihj@163.com} uses 

NeHe的OpenGL教程6(Bang翻译Delphi版)-如何用图片进行纹理映射

NeHe的OpenGL教程6(Bang翻译Delphi版)-如何用图片进行纹理映射 在这一课里,我将教会你如何把纹理映射到立方体的六个面,如下图: 将下图放在应用程序data目录下,起名NeHe.bmp program lesson6a; {    OpenGL DelphiXE    出处:根据NeHe代码翻译而来(http://nehe.gamedev.net/)    作者:帅宏军 shuaihj@163.com     注:本单元用到了glaux.dll和glaux.pas,下载地址为:

NeHe的OpenGL教程2(Bang翻译Delphi版)-如何绘制平面图形

NeHe的OpenGL教程2(Bang翻译Delphi版)-如何绘制平面图形 这一课中,我将教您如何创建三角形和四边形.如下图: program lesson2a; {    OpenGL DelphiXE    出处:根据NeHe代码翻译而来(http://nehe.gamedev.net/)    作者:帅宏军 shuaihj@163.com} uses  Windows,  Messages,  OpenGL; // 全局变量var  h_Rc: HGLRC;               

NeHe的OpenGL教程5(Bang翻译Delphi版)-如何绘制立方体

NeHe的OpenGL教程5(Bang翻译Delphi版)-如何绘制立方体 在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体,如下图: program lesson5a; {    OpenGL DelphiXE    出处:根据NeHe代码翻译而来(http://nehe.gamedev.net/)    作者:帅宏军 shuaihj@163.com} uses  Windows,  Messages,  OpenGL; // 全局变量var  h_Rc: HGLRC;    

NeHe的OpenGL教程4(Bang翻译Delphi版)-如何让图形旋转

NeHe的OpenGL教程4(Bang翻译Delphi版)-如何让图形旋转 在这一课里,我将教会你如何旋转三角形和四边形.左图中的三角形沿Y轴旋转,四边形沿着X轴旋转.如下图 program lesson4a; {    OpenGL DelphiXE    出处:根据NeHe代码翻译而来(http://nehe.gamedev.net/)    作者:帅宏军 shuaihj@163.com} uses  Windows,  Messages,  OpenGL; // 全局变量var  h_Rc

NeHe的OpenGL教程7(Bang翻译Delphi版)-如何使用光源

NeHe的OpenGL教程7(Bang翻译Delphi版)-如何使用光源        在这一课里,我将教会你如何用光源照亮立方体的六个面,如下图: 将下图放在应用程序data目录下,起名NeHe.bmp program lesson7a; {    OpenGL DelphiXE    出处:根据NeHe代码翻译而来(http://nehe.gamedev.net/)    作者:帅宏军 shuaihj@163.com     在这一课里,我将教会你如何用光源照亮立方体的六个面     注:本

请教 安卓 opengl es 如何能后画出带有渐变色的线段。。

问题描述 请教 安卓 opengl es 如何能后画出带有渐变色的线段.. 网上看到了画线段了例子但是都不知道,把那段代码放在项目的什么地方... 网上看到的代码贴出来... float vertexArray[] = { -0.8f, -0.4f * 1.732f, 0.0f, -0.4f, 0.4f * 1.732f, 0.0f, 0.0f, -0.4f * 1.732f, 0.0f, 0.4f, 0.4f * 1.732f, 0.0f, }; public void DrawScene(G