`
mmdev
  • 浏览: 12937521 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

【OpenGL4.0】GLSL渲染语言入门与VBO、VAO使用:绘制一个三角形

 
阅读更多

以前都是用Cg的,现在改用GLSL,又要重新学,不过两种语言很多都是相通的。


下面的例子是实现绘制一个三角形的简单程序。采用了VBO(veretx buffer object)、VAO(vertex array object)等OpenGL的一些新特性。越往后发展,可编程管线肯定是大势所趋,OpenGL里原来的一些固定管线的内容肯定会被废弃掉。所以从现在开始写程序就要养成使用新特性、采用可编程管线技术的好习惯。


一、VAO、VBO介绍

随着OpenGL状态和固定管线模式的移除,我们不在用任何glEnable函数调用,而且也不会有glVertex、glColor等函数调用。这就意味着我们需要一种新的方式来将数据传输到图形卡以渲染图形。我们可以采用VBO,或者是在OpenGL3以上版本引入的新的特性,叫做VAO。通过它,我们可以把顶点数据和颜色存储在不同的VBO中,但是在同一个VAO中。对于法线数据或者其他的顶点信息也是一样。

VAO,是这样一种方式:把对象信息直接存储在图形卡中,而不是在当我们需要的时候传输到图形卡。这就是Direct3D所采用得方式,而在OpenGL中只有OpenGL3.X以上的版本中采用。这就意味着我们的应用程序不用将数据传输到图形卡或者是从图形卡输出,这样也就获得了额外的性能提升。

使用VAO并不难。我们不需要大量的glVertex调用,而是把顶点数据存储在数组中,然后放进VBO,最后放入VAO。OpenGL会在后台为我们完成其他的功能。

使用VAO的步骤:

1、产生VAO

void glGenVertexArrays( GLsizei n,
GLuint *arrays);

n:要产生的VAO对象的数量。

arrays:存放产生的VAO对象的名称。

2、绑定VAO

void glBindVertexArray(GLuint array);

array:要绑定的顶点数组的名字。

3、产生VBOs

void glGenBuffers( GLsizei n,
GLuint * buffers);

产生缓冲区对象的名称。

参数含义和glGenVertexArrays类似。

4、绑定VBOs

void glBindBuffer( GLenum target,
GLuint buffer);

绑定一个缓冲区对象。

target可能取值是:GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER, or GL_PIXEL_UNPACK_BUFFER.

当进行绑定之后,以前的绑定就失效了。

5、给VBO分配数据:

void glBufferData( GLenum target,

GLsizeiptr size,

const GLvoid * data,

GLenum usage);

target可能取值为:GL_ARRAY_BUFFER(表示顶点数据), GL_ELEMENT_ARRAY_BUFFER(表示索引数据),GL_PIXEL_PACK_BUFFER(表示从OpenGL获取的的像素数据), or GL_PIXEL_UNPACK_BUFFER(表示传递给OpenGL的像素数据).

参数含义:

size:缓冲区对象字节数

data:指针:指向用于拷贝到缓冲区对象的数据。或者是NULL,表示暂时不分配数据。

6、定义存放顶点属性数据的数组:

首先需要启用VAO中对应的顶点属性数组:

void glEnableVertexAttribArray( GLuint index);

index:指定了需要启用的顶点属性数组的索引

注意:它只在OpenGL2.0及其以上版本才有。

7、给对应的顶点属性数组指定数据:

void glVertexAttribPointer( GLuint index,

GLint size,

GLenum type,

GLboolean normalized,

GLsizei stride,

const GLvoid * pointer);

index:要指定数据的顶点属性数组的索引。

size:每个顶点属性的数据个数。可能的取值是1、2、3或者4.初始值是4.

type:数组中每个数据的类型。可能的取值是:GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, or GL_DOUBLE。初始值是GL_FLOAT。

normalized:指定顶点数在被访问的时候是否需要被归一化。

注意:如果有个非零的缓冲对象绑定到GL_ARRAY_BUFFER,那么pointer就是对应的缓冲区对象的偏移量。

stride:两个连续顶点的属性之间的偏移量。

pointer:指向数组中的第一个顶点属性的第一个数据。

8、然后在进行渲染的时候,只需要绑定对应的VAO即可,操作起来十分方便。

glBindVertexArray(vaoHandle);

9、使用完毕之后需要清除绑定。

glBindVertexArray(0);


VAO参考资料:

VAO wiki

关于VAO的一篇博客

VAO

事实上,在这个简单的程序中,不用VAO,只用VBO也一样可以实现。只是采用VAO可以进一步提升性能,而且在较新版本的OpenGL中不用VAO的方式会被逐渐废弃。


二、GLSL入门

关于GLSL,可以参考红宝书的附录,上面介绍了GLSL的入门知识。

这里也有一个很好的入门教程,英文的:

GLSL入门tutorial



三、程序实例

下面贴出源代码(OpenGL,GLSL实现):

basic.vert:

basic.frag:

主文件:

main.cpp:


读取shader文件的程序:

textfile.h:

textfile.cpp:

运行结果:


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics