【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以上。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值