OpenGL 03 绘制命令

来源:互联网 发布:ubuntu怎么上传lrzsz包 编辑:程序博客网 时间:2024/05/01 04:00

注:本文为OpenGL红宝书第八版阅读笔记

OpenGL的绘制分为索引形式和非索引形式,其实一个是全部按顺序绘制,一个是指定索引来绘制,但是如果是按照指定索引来绘制的话,则其索引数组其实是来自于到绑定 GL_ELEMENT_ARRAY_BUFFER 的缓存对象。

下面依次来介绍索引和非索引形式的绘制,首先是非索引的绘制,最基本的命令是glDrawArrays(),

void glDrawArrays(GLenum mode, GLint first, GLsizei count);

这个其实是最基本的,表明的意思是从数组中的first开始,绘制count个,mode则表明是绘制图元的类型。

而非索引绘制的命令则是glDrawElements()

void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);

OpenGL所有负责的绘制都是基于这两个函数来实现的,当然也衍生了很多类似的函数,如下:

void glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, constGLvoid* indices, GLint basevertex);

这个函数和glDrawElements是一样的,只不过对访问的点做了偏移,是它的第 i 个元素在传入绘制命令时,实
际上读取的是各个顶点属性数组中的第 indices[i] + basevertex 个元素。这个函数的功能是当要绘制多个实体的时候,就可以用同一个索引数据绘制不同的实体。

glDrawRangeElements()则是更严格的glDrawElements()版本,

void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,GLenum type, const GLvoid* indices);

其实这里就是加了一个保护,indices必须要在start和end的区间中。

当然还有一些组合实现的更为高级的命令,这里就不做阐述了。

最后再来介绍一下几个间接绘制函数,这里的绘制的参数不是从程序中获得的,而是从缓存对象中获得的,但是如果要这样使用的话,则必须要将缓存对象绑定到 GL_DRAW_INDIRECT_BUFFER 目标上。

glDrawArrays() 的间接版本叫做 glDrawArraysIndirect()。

void glDrawArraysIndirect(GLenum mode, const GLvoid* indirect);

这个绘制命令和之前的glDrawArrays是一样的,不过绘制的参数是从缓存对象中获取的,我们从缓存中获取的其实是一个结构体数据,indirect 记录间接绘制缓存中的偏移地址。下面来看一下这个结构体,

typedef struct DrawArraysIndirectCommand_t{GLuint count;GLuint primCount;GLuint first;GLuint baseInstance;} DrawArraysIndirectCommand;

glDrawElements() 的间接版本叫做 glDrawElementsIndirect(),

void glDrawElementsIndirect(GLenum mode, GLenum type, const GLvoid* indirect);

从缓存对象中获取的则是一个结构体,定义为:

typedef struct DrawElementsIndirectCommand_t{GLuint count;GLuint primCount;GLuint firstIndex;GLuint baseVertex;GLuint baseInstance;} DrawElementsIndirectCommand;

接下来我们继续了解一下绘制命令的变形形式:

void glMultiDrawArrays(GLenum mode, const GLint* first, const GLint* count,GLsizei primcount);

相当于:

void glMultiDrawArrays(GLenum mode,const GLint * first,const GLint * count,GLsizei primcount){    GLsizei i;    for (i = 0; i < primcount; i++)    {        glDrawArrays(mode, first[i], count[i]);    }}

同理,glDrawElements() 的多变量版本就是 glMultiDrawElements()

void glMultiDrawElements(GLenum mode, const GLint* count, GLenum type, const GLvoid* const* indices, GLsizei primcount);

这里的意思其实和上面的一样的道理。

图元重启动的功能:
glMultiDraw*() 形式的函数,但是这样需要额外去管理图元的起始索引位置和长度的数组。所以需要有行图元重启动的功能。此时需要指定一个特殊的值,叫做图元重启动索引。
这里的意思是如果绘制的过程中遇到了重启动索引,那就从这个点开始重新绘制。图元重启动索引的定义是通过 glPrimitiveRestartIndex() 函数来完成的。

void glPrimitiveRestartIndex(GLuint index);

设置一个顶点数组元素的索引值,这样在绘制过程中,如果遇到的话,则会终止当前的图元绘制,并从下一个点开始重新绘制。如果我们要使用这个功能的话,则需要开启这个功能,方法:通过 glEnable() 和 glDisable() 函数来完成,调用的参数为 GL_PRIMITIVE_RESTART。

继续来看多实例渲染的部分:

多实例渲染其实就是连续执行多条相同的渲染命令的方法,并且每个渲染命令所产生的结果都会有轻微的差异。

glDrawArrays的多实例绘制命令为glDrawArraysInstanced,即:

void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizeiprimCount);

primCount表示的意思就是绘制实例的个数。其他 OpenGL 的绘制命令也有对应的 *Instanced 版本

原创粉丝点击