目录
- 常规绘制
- glDrawArrays(GLenum mode,GLint first,GLsizei count )
- glDrawElements(GLenum mode,GLsizei count,GLenum type,consr GLvoid *indices)
- glDrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,count GLvoid* indices,GLint basevertex)
- glDrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid* indices)
- glDrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid*indice,GLint basevertex)
- 参数从GL_DRAW_INDIRECT_BUFFER缓存 间接绘制缓存中获取的结构体数据
- 绘制多组几何图元集
- glMultiDrawArrays(GLenum mode,consr GLint* first,const GLint* count,GLsizei primcount)(绘制多个图元)
- glMultiDrawElements(GLenum mode,const GLint* count,GLenum type,const GLvoid* const*indices,GLsizei primcount)
- glMultiDrawElementsBaseVertex(GLenum mode,const GLint* count,GLenum type,const GLvoid* const*indices,GLsizei primcount,consr GLint* baseVertex)
- glMultiDrawArraysIndirect(GLenum mode,const GLvoid* indirext,GLsizei drawcount,GLsizei stride)
- glMultiDrawElementsIndirect(GLenum mode,GLenum type,const GLvoid* indirext,GLsizei drawcount,GLsizei stride)
- 图元重启动
- 多实例渲染
- glDrawArraysInstanced(GLenum mode,GLint first,GLsizei count,GLsizei primCount)
- glDrawElementsInstanced(GLenum mode,GLsizei count,GLenum type,count void*indices,GLsizei primCount)
- DrawElementsIndtancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const void* indices,GLsizei instanceCount,GLuint baseVertex);
- glDrawArraysInstancedBaseInstance(GLenum mode,Glint first,GLsizei count,GLsizei instanceCount,Gluint baseInstance)
- glDrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,GLenum type,count GLvoid* indices,GLsizei instanceCount,GLuint baseInstance)
- glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count ,GLenum type,const GLvoid*indices,GLsizei instanceCount,GLuint baseInstance)
- 多实例的顶点属性
常规绘制
glDrawArrays(GLenum mode,GLint first,GLsizei count )
mode的类型有:
不能调用GL_POLYGON 改为了void glPolygonMode(GLenum face, GLenum mode);
起始位置为first 借宿位置为firsr+count-1
glDrawElements(GLenum mode,GLsizei count,GLenum type,consr GLvoid *indices)
使用count个元素来定义一系列几何图元 差不多就是多少个点形成一个图元
indices 定义了元素数组缓存中的偏移地址 也就是索引开始的位置
type必须时GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT中的一个 表示的是索引数据的类型
glDrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,count GLvoid* indices,GLint basevertex)
实际上就是在basevertex个元素之后开始绘制 也就是 indices[i]+basevertex
glDrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid* indices)
是glDrawElements的一种严格形式 元素数组缓存中包含的任何一个索引值都会落入到start和end所定义的范围当中
glDrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid*indice,GLint basevertex)
实际上就是有basevertex和elements和range的结合
参数从GL_DRAW_INDIRECT_BUFFER缓存 间接绘制缓存中获取的结构体数据
glDrawArraysIndirect(GLenum mode, const GLvoid* indirect)
和glDrawArraysInstanced()完全一致 绘制命令的参数是从绑定到GL_DRAW_INDIRECT_BUFFER的缓存中获取的具体数据
indirect记录间接绘制缓存中的偏移地址 mode必须是glDrawArrays()所支持的某个图元类型
DrawArraysIndirectCommand结构体的声明
typedef struct DrawArraysIndirectCommand_t
{
GLuint count;
GLuint primCount;
GLuint firsr;
GLuint baseInstance;
}DrawArraysIndirectCommand;
这个结构体的所有域成员都会作为glDrawArrayInstanced的参数进行解析 first和count会被直接传递到内部函数中
primCount表示多实例的个数
baseInstance表示多实例顶点属性的偏移
glDrawElementsIndirect(GLenum mode, GLenum type,const GLvoid* indirect)(glDrawElements()的间接版本)
indirect记录了间接绘制缓存中的偏移地址 type指定了绘制命令调用时元素数组缓存中索引值的类型
glDrawArraysIndirect()的参数也来自于元素数组缓存中indirect偏移地址所存储的结构体
typedef struct DrawElementsIndirectCommand_t
{
GLuint count;
GLuint primCount;
GLuint firsrIndex;
GLuint baseVertex;
GLuint baseInstance;
}DrawElementsIndirectCommand;
其他的和上面那个函数一样 firsrIndex可以与type参数所定义的索引数据大小相结合 计算传递到glDrawElementsInstancedBaseVertex()的索引数据结果
baseInstace用来表示结果绘制命令中所有多实例顶点属性的实例偏移值
绘制多组几何图元集
说白了 这里就是自己把顶点数组规整好 可以绘制不同图元出来 类似于
vertex[]{
0.0,0.0,0.0,
1.0,0.0,0.0,
1.0,1.0,0.0,
2.0,0.0,0.0,
3.0,0.0,0.0,
3.0,1.0,0.0,
2.0,1.0,0.0}
first[]{
0.0,
1.0
}
count[]{
3.0,
4.0}
大概就是这样可以绘制一个三角形 一个正方形
说实话也可以自行拼接图形了
也就是并不一定要用三角形带画四边形
glMultiDrawArrays(GLenum mode,consr GLint* first,const GLint* count,GLsizei primcount)(绘制多个图元)
在一个OpenGL函数调用过程中绘制多组集合图元集
first和count都是数组的形式
glMultiDrawArrays(GLenum mode,consr GLint* first,const GLint* count,GLsizei primcount)
{
GLsizei i;
for(i = 0;i<primcount ; i++)
{
glDrawArrays(mode,first[i],count[i])
}
}
glMultiDrawElements(GLenum mode,const GLint* count,GLenum type,const GLvoid* const*indices,GLsizei primcount)
等价于
for(int i = 0;i<primcount;i++)
{
glDrawElements(mode,count[i],type,indices[i])
}
glMultiDrawElementsBaseVertex(GLenum mode,const GLint* count,GLenum type,const GLvoid* constindices,GLsizei primcount,consr GLint baseVertex)
基本一样 就是baseVertex[]也是数组
glMultiDrawArraysIndirect(GLenum mode,const GLvoid* indirext,GLsizei drawcount,GLsizei stride)
可以分发总共drawcount个独立的绘制命令
每个DrawArraysIndirectCommand结构体之间的间隔都是stride个字节
glMultiDrawElementsIndirect(GLenum mode,GLenum type,const GLvoid* indirext,GLsizei drawcount,GLsizei stride)
结构体是DrawElementsIndirectCommand
图元重启动
glPrimitiveRestartInde(GLuint index)
这个函数要和索引绘制配合使用
也就是在索引绘制的使用如果碰到了 index索引则跳过该索引 终止当前图元绘制 从下一个顶点索引重新开始渲染同一类型的图元集合
例如
static const GLushort index[]{
1,2,3,0xFFFF,3,1,2}
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
glDrawElements(GL_TRIANGLE_STRIP,7,GL_UNSIGNED_SHORT,NULL)
要不然就要使用两个glDrawElements()绘制了
7 包含了0xFFFF
通过管理Enable(GL_PRIMITIVE_RESTART)和Disable(GL_PRIMITIVE_RESTART)
默认重启索引是0
多实例渲染
是一种连续执行多条相同渲染命令的方法 并且每个渲染命令所产生的结果都会有轻微的差异
我觉得这个相对于多组集合图元集来说 这个是使用一组顶点 在多个地方绘制出来
glDrawArraysInstanced(GLenum mode,GLint first,GLsizei count,GLsizei primCount)
前面参数都一样 绘制它的primCount个实例 每个实例内置变量gl_InstanceID都会依次递增
当OpenGL执行这个函数的适合 他实际上会执行glDrawArrays的primVount次拷贝 其他类似函数也一样
glDrawElementsInstanced(GLenum mode,GLsizei count,GLenum type,count void*indices,GLsizei primCount)
DrawElementsIndtancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const void* indices,GLsizei instanceCount,GLuint baseVertex);
类似于glDrawElementsInstancedBaseVertex()函数所需的独立函数
glDrawArraysInstancedBaseInstance(GLenum mode,Glint first,GLsizei count,GLsizei instanceCount,Gluint baseInstance)
对于每个实例 内置变量gl_InstanceID都会依次递增 baseInstance的值用来对实例化的顶点属性设置一个索引的偏移值 从而改变OpenGL取出索引的位置
glDrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,GLenum type,count GLvoid* indices,GLsizei instanceCount,GLuint baseInstance)
glDrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count ,GLenum type,const GLvoid*indices,GLsizei instanceCount,GLuint baseInstance)
多实例的顶点属性
(控制顶点属性更新频率)glVertexAttribDivisor(GLuint index,GLuint divisor)
例子:如果设置了顶点颜色的索引位置为1 则可以
glVertexAttribDivisor(1,1);则代表颜色值在每更新一个实例时分配一个新的属性值
index表示设置多实例特性的顶点属性的索引位置
如果divisor值为0 则该属性的多实例特性将被禁用 其他的值则表示顶点着色器 每divisor个实例都会分配一个新的属性值 //这里没看懂 应该就是跟没设置一样
如果非0则顶点属性将启用多实例的特性 OpenGL从属性数组中每隔divisor个实例都会读取一个新的值(而不是之前的每个顶点)
instance表示当前的实例数目
divisor表示当前属性的更新频率值
每个实例中的所有顶点都会共享同一个属性值
如果divisor为2 则每两个实例会共享同一个属性值
如果某个顶点属性被设置了divisor则每个实例都会有一个独立的值 而实例当中所有顶点都会使用这一个值
纹理运用
将一系列纹理打包到一个2D纹理数组中 然后将数组的序号通过实例化的顶点属性传递给每个实例 这样就可以使用不同的纹理来选软不同的几何体实例
gl_InstanceID
总是在顶点着色器中 变量是一个整型 从-开始计数 每当一个实例被渲染之后 这个值就会加一
gl_InstanceID的值可以作为uniform数组的索引使用 也可以作为纹理查找的参数使用 或者作为某个分析函数的输入
多实例模型矩阵配置
/*这里是将model矩阵传进着色器 方便多实例绘制的使用*/
/*模型矩阵 因为是mat4类型的数据 */
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(vertices)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4) + sizeof(vertices)));
glEnableVertexAttribArray(4);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2*sizeof(glm::vec4) + sizeof(vertices)));
glEnableVertexAttribArray(5);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3*sizeof(glm::vec4) + sizeof(vertices)));
glEnableVertexAttribArray(6);
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);