宝书】Chapter 7. Vertex Processing and Drawing Commands"/>
【OpenGL蓝宝书】Chapter 7. Vertex Processing and Drawing Commands
一、VAO再谈
OpenGL 3.x时代,一般使用
glGenVertexArrays(1, &vao);
glBindVertexAttay(vao);
glVertexAttribPointer(attribIndex, ...);
glEnableVertexAttribArray(attribIndex)glBindBuffer(..., buffer);
所有data都放在一个buffer。
OpenGL 4.3引入了另一种写法,其好处是可将不同的data通过不同buffer灌进去。
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);glVertexAttribFormat(attribIndex, ...);
glBindVertexBuffer(bufferBindingpoint, buffer, ...);
glVertexAttribBinding(attribIndex, bufferBindingpoint);
glEnableVertexAttribArray(attribIndex);
以上两种都需要使用glGenVertexArrays()之后,立即使用glBindVertexArray(),还记得之前说过的吗?Gen()只是生成名字,需要Bind之后才会生成object。
OpenGL 4.5引入了Create(),它在造名字的同时就生成了object。这就不需要先Bind()。相对应的,VAO这里也引入了直接对名字进行设置,就像Namedbuffer的设置一样。
glCreateVertexArrays(1, &vao);glVertexArrayAttribFormat(vao, attribIndex, ...);
glVertexArrayVertexBuffer(vao, bufferBindingpoint, buffer, ...);
glVertexArrayAttribBinding(vao, attribIndex, bufferBindingpoint);
glEnableVertexArrayAttrib(vao, attribIndex);glBindVertexArray(vao); // bind可放最后
二、Drawing Commands
1 indexed drawing command
1.1 glDrawElementsBaseVertex():将EBO中的index取出之后,加上basevertex,再用加完了的index去vertex buffer中取点。
glDrawElements();glDrawElementsBaseVertex(..., basevertex);
1.2 GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_LINE_STRIP, GL_LINE_LOOP中间断点,重新绘制。(必须使用glDrawElements(),否则glPrimitiveRestartIndex会被无视)。
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(index);
2 Instancing
有些数据我希望每一个instance更新一次,而不是每一个顶点更新一次,这时候就可以使用:
glVertexAttribDivisor(index, divisor);
设置vao的index号attribute每divisor次更新一次。
2.1 若每种attribute想各自跳过前n个,则使用
glDraw...InstancedBaseInstance(..., baseinstance)
对于DrawElement,还可以
glDrawElementsInstancedBaseVertex()
glDrawElementsInstancedBaseVertexBaseInstance()
BaseVertex之功能如1.1所述。
3. Indirect
与instancing类似,只是把除了mode之外的参数整合到一个struct中。
glDrawArraysIndirect(mode, *indirect)
glDrawElementsIndirect(mode, type, *indirect)glMultiDrawArraysIndirect()
glMultiDrawElementsIndirect()
drawArrays和drawElements的indirect结构体去reference查。
引入Indirect draw的目的在于multi draw。可以将不同的draw command 存到一个indirect struct 列表,将该列表存到GL_DRAW_INDIRECT_BUFFER。并且glMultiDrawArraysIndirect(),glMultiDrawElementsIndirect()两个函数调用时的indirect置nullptr。它们就会去GL_DRAW_INDIRECT_BUFFER取command。
三、Transformed Vertices
使用glTransformFeedbackVaryings()指定哪些shader的输出需要存回GL_TRANSFORM_FEEDBACK_BUFFER。
需要在linkProgram()前使用。
P.S. 一共有4个buffer,它们有自己的binding point,分别是
GL_TRANSFORM_FEEDBACK_BUFFER、GL_UNIFORM_BUFFER、GL_ATOMIC_COUNTER_BUFFER、GL_SHADER_STORAGE_BUFFER。
四、用户自定义裁剪
1. gl_ClipDistance[]
在vertex shader中,有个内置变量float数组gl_clipdistance[]。它是per_vertex的。对于一个vertex来说,gl_clipdistance[]数组中,只要有一个为负数,则该点被clip。
为了启用gl_clipdistance[],需要在cpp中显式启用:
glEnable(GL_CLIP_DISTANCEi);
这样就激活了gl_clipdistance[]数组的第i个数据。
顾名思义:clipdistance就是该vertex到裁剪面的距离。距离为正,则没有超过裁剪面;距离为负,则超过裁剪面。
注意:对于一个primitive来说(以三角形举例),一个点被clip,另外两个没被clip,则这个primitive会被部分clip。
2. gl_CullDistance[]
与gl_clipdistance[]一样,只不过只要有一个点被clip,则整个primitive被cull。
不需要显示启用任何东西。
gl_culldistance[]需要glsl4.5以上。
更多推荐
【OpenGL蓝宝书】Chapter 7. Vertex Processing and Drawing Commands
发布评论