简述
TransformFeedback是OpenGL管线中,顶点处理(如果有几何着色器,那么就在几何着色器后)之后,图元装配之前的一个步骤。它可以重新捕获即将装配为图元(点,线段,三角形)的顶点,然后将部分或全部属性传递到缓存对象上来。每当一个顶点传递到图元装配阶段时,将所有需要捕获的属性记录到一个或多个缓存对象上,用户程序可以回读这些缓存对象的内容。
根据这个特性,它和顶点着色器可以组合成一个小的渲染管线,而不用后续的光栅化处理,这样就能利用GPU强大的计算能力做一些通用的计算。当然,如果当前OpenGL版本在OpenGL4.3及以上的话,可以使用了计算着色器。
transform feedback对象
transform feedback状态封装在一个transform feedback对象中,这个状态中包括所有记录顶点数据的缓存对象等,transform feedback对象的创建和其他的缓存对象类似,首先要创建一个对象名称,然后绑定到OpenGL环境中。
1创建对象名
GLuint glGenTransformFeedbacks(GLenum target, GLuint *id); 返回值:返回Uniforms的缓冲索引 参 数:program 着色器程序ID uniformBlockName Uniforms块名 |
2绑定到OpenGL环境
GLuint glBindTransformFeedback(GLenum target, GLuint id); 返回值:返回Uniforms的缓冲索引 参 数:program 着色器程序ID uniformBlockName Uniforms块名 |
3删除对象
GLuint glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids); 返回值:返回Uniforms的缓冲索引 参 数:program 着色器程序ID uniformBlockName Uniforms块名 |
transform feedback缓存
transform feedback对象主要用于管理将顶点捕捉到缓存对象的相关状态,这个状态中包含了链接到transform feedback缓存绑定点的缓存对象,transform feedback对象必须和一个缓存对象链接才能输出数据,它本身是不存储输出数据的(与帧缓存对线和附加到它上的纹理缓存类似)。
如果想要将整个缓存绑定到transform feedback上,可以使用函数glBindBufferBase()。
voidglBindBufferBase(GLenum target, GLint index, GLuint buffer) 功 能:将缓存绑定到transform feedback上 返回值:void 参 数:target 绑定目标必须设为GL_TRANSFORM_FEEDBACK_BUFFER index 缓存绑定点索引 buffer 绑定的缓存对象 |
如果想要将缓存的部分绑定到transform feedback上,可以使用函数glBindBufferRange()。
void glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) 功 能:将缓存绑定到transform feedback上 返回值:void 参 数:target 绑定目标必须设为GL_TRANSFORM_FEEDBACK_BUFFER index 缓存绑定点索引 buffer 绑定的缓存对象 offset 起始地址 size 绑定的缓存大小 |
transform feedback缓存初始化示例
//生成缓存对象
Gluint buffer;
glGenBuffers(1, &buffer);
//绑定到GL_TRANSFORM_FEEDBACK_BUFFER,创建缓存对象
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
//调用glBufferData并分配空间
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, //目标
1024 * 1024, //分配空间
NULL, //数据为空
GL_DYNAMIC_COPY); //用途
//绑定到带有索引的缓存绑定点
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, //目标
0, //索引为0
buffer, //缓存名称
0, //数据起始地址
512 * 1024); //缓存的前半部分
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, //目标
0,//索引为0
buffer,//缓存名称
512 * 1024),//数据起始地址
512 * 1024);//缓存的前半部分
配置transform feedback变量
再transform feedback过程中顶点着色器可能会输出多个变量。与transform feedback对象所绑定的缓存需要记录那些变量,这些都需要在应用程序中设置,我们需要调用函数glTransformFeedbackVaryings()来设定。
void glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar **varyings, GLenum bufferMode) 功 能:设置缓存记录的变量 返回值:void 参 数:program 着色器程序 count 变量的总数 varyings 变量名数组 bufferMode 捕获变量的模式,可以是分量模式(GL_SEPARATE_ATTRIBS) 或交叉模式(GL_INTERLEAVED_ATTRIBS) |
注意:函数glTransformFeedbackVaryings()所指定的变量,只有再一次链接的时候才会起效,换句话说,glTransformFeedbackVaryings()必须再着色器程序链接之前调用。
transform feedback变量设置的示例
//创建一个记录变量名称的数组
static const char *const vars[] =
{
"foo", "var", "vaz"
};
//调用函数glTransformFeedbackVaryings
glTransformFeedbackVaryings(program,
sizeof(vars)/sizeof(vars[0]),
vars,
GL_INTERLEAVED_ATTRIBS);
//现在(非常重要),需要链接程序对象
glLinkProgram(program);
transform feedback的启动和停止
transform feedback可以随时启动或停止,甚至暂停,如果启动transform feedback时,它并没有处于暂停的状态,它会重新开始将数据记录到当前绑定的ransform feedback缓存中,不过如果transform feedback正处于暂停的状态,那么再次启动它将会从之前暂停的位置开始记录。如果需要将厂家中的某些部分记录到transform feedback当中,这个特效是比较有用的。
启动
void glBeginTransformFeedback(GLenum primitiveMode);
暂停
void glPauseTransformFeedback(void);
如果当前的ransform feedback没有启用,或者处于暂停状态,
调用glPauseTransformFeedback会产生一个错误
重新启动
void glResumeTransformFeedback(void);
要重新启动一个暂停的ransform feedback,必须使用glResumeTransformFeedback。
如果使用glBeginTransformFeedback同样会产生一个错误。
停止
void glEndTransformFeedback(void);
如果已经完成了transform feedback图元的渲染,直接调用glEndTransformFeedback(),就可以重新切换到正常的渲染模式。
这章主要写了一些transform feedback的简要流程和API,不太容易理解和使用,可以参考下章
OPenGL--Transform feedback示例解析,有详细的示例。
参见:《OpenGL编程指南》第八版第5章