[TOC]
5. Transform Feedback
变换反馈模式允许将顶点着色器的输出捕获到缓冲区对象中,然后,这些输出缓冲区对象可以作为后续绘图中顶点数据源。这种方法对很多在GPU上执行动画而无需CPU干预的技术很有用,例如粒子动画。
可以用如下方法来指定要捕获的顶点属性集合:
void glTransformFeedbackVaryings (GLuint program, GLsizei count, const char** varying, GLenum bufferMode)
- program : program对象
- count : 用于变换反馈的顶点输出变量的个数
- varyings : 一个含有count个字符串的数组,这些字符串表示顶点输出变量的名字
- bufferMode : 捕获顶点输出变量的模式,可取值为
GL_INTERLEAVED_ATTRIBS : 将顶点输出变量捕获到一个缓冲区中
GL_SEPARATE_ATTRIBS : 将每一个顶点输出变量捕获到它自己的缓冲区中
调用glTransformFeedbackVaryings之后,需要调用glLinkProgram来链接程序对象,例如:
const char * varyings[] = {"v_position", "v_color"};
glTransformFeedbackVaryings (programObj, 2, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram (programObj);
然后,我们通过GL_TRANSFORM_FEEDBACK_BUFFER参数调用glBindBuffer方法来绑定一个或多个缓冲对象作为变换反馈缓冲区,然后使用glBufferData来分配缓冲区,然后使用glBindBufferBase或者glBindBufferRange将缓冲区绑定到索引绑定点。
在绑定变换反馈缓冲区之后,我们可以通过如下命令来进入或退出变换反馈模式:
void glBeginTransformFeedback (GLenum primitiveMode)
void glEndTransformFeedback ()
- primitiveMode : 指定将要被捕获到缓冲对象的图元类型。变换反馈受限于非索引的GL_POINTS, GL_LINES, GL_TRIANGLES
在glBeginTransformFeedback和glEndTransformFeedback之间发生的所有绘制命令的顶点输出将会被捕捉到变换反馈缓冲区中,下表说明了根据变换反馈图元类型,所允许的绘制类型:
Primitive Mode | Allowed Draw Mode |
---|---|
GL_POINTS | GL_POINTS |
GL_LINES | GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP |
GL_TRIANGLES | GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN |
通过glGetQueryObjectuiv命令,我们可以检索成功写入到变换反馈缓冲区的图元数量,例如:
glBeginTransformFeedback (GL_POINTS);
glBeginQuery (GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, queryObject);
glDrawArrays (GL_POINTS, 0, 10);
glEndQuery (GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
glEndTransformFeedback();
glGetQueryObjectuiv (queryObject, GL_QUERY_RESULT, &numPoints);
在进行变换反馈时,我们可以通过GL_RASTERIZER_DISCARD参数调用glEnable和glDisable方法来关闭和开启光栅化阶段,当开启GL_RASTERIZER_DISCARD时(也就是关闭光栅化),不会执行片段shader。
6. Vertex Textures
OpenGL ES 3.0 支持顶点shader中的纹理查找操作,这在实现位移贴图等技术时是非常有用的,你可以根据顶点shader中的纹理查找值来沿着顶点法线移动顶点坐标。这种技术的典型应用就是渲染地形或者水面。
在顶点shader中使用纹理查找有一些限制:
- The level of detail is not implicitly computed
- The bias parameter in the texture lookup function is not accepted
- The base texture is used for mipmapped texture
可以通过GL_MAX_VERTEX_TEXTURE_UNITS参数调用glGetIntegerv来查询一个实现支持的纹理图像单元的最大数量。任何实现所支持的最小值是16。
Example 8-8:
#version 300 es
uniform mat4 u_mvpMatrix;
uniform sampler2D displacementMap;
layout (location = 0) in vec4 a_position;
layout (location = 1) in vec3 a_normal;
layout (location = 2) in vec2 a_texcoord;
layout (location = 3) in vec4 a_color;
out vec4 v_color;
void main()
{
v_color = a_color;
float displacement = texture (displacementMap, a_texcoord).a;
vec4 displaced_position = a_position + vec4(a_normal * displacement, 0.0);
gl_Position = u_mvpMatrix * displaced_position;
}
网友评论