OpenGL 编程指南 (4)
1、OpenGL用户裁剪需要使用一个vertex shader的内置变量gl_ClipDistance,它是一个声明的时没有指定大小的数组,因此需要重新声明它的大小或者将它作为一个编译时的常量使用。
gl_ClipDistance每一个元素对应一个平面,平面数目有限通常为8个,可以通过gl_MaxClipDistances获取平台支持的最大值。这个数组大小包括了已经启用的其它裁剪面,vertex shader必须写入所有已经启用裁剪面的距离,否则表现不可预测,通过裁剪的片元可以读取裁剪面插值后的结果。
2、transform feedback 是顶点处理结束之后,图元装配和光栅化之前的步骤,它能够重获获取顶点数据后选择性地部分或全部传递到缓冲对象中。
void glGenTransformFeedbacks(GLsizei n, GLuint* ids)
void glBindTransformFeedback(GLenum target, GLuint id)//target 必须是 GL_TRANSFORM_FEEDBACK
系统有一个默认的transform feedback对象,id为0。可以同时给transform feedback对象绑定多个缓冲,也可以绑定缓冲对象的多个子块,甚至可以将统一个缓冲对象的不同子块同时绑定到不用的transform feedback缓冲绑定点上,也能够只是绑定一部分。
void glBindBufferBase(GLenum target, GLuint index, GLuint buffer)//target 必须是 GL_TRANSFORM_FEEDBACK_BUFFER,index应小于GL_MAX_TRANSFORM_FEEDBACK_BUFFERS(最小64)
void glBindBufferRange(Glenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
分配空间后需要告诉它目标数据,这些数据来自vertex shader 或者 geometry shader的输出
void glTransformFeedbackVaryings(Gluint program, GLsizei count, const GLchar** varyings, GLenum bufferMode)//bufferMode获取变量的模式,有分离模式(GL_SEPARATE_ATTRIBS,每个变量输出到一个单独的缓冲对象中)与交叉模式(GL_INTERLEAVED_ATTRIBS,所有变量一个接一个地记录到第一个绑定对象中)
static const char* const vars[] = {"first", "second", "third"};
glTransformFeedbackVaryings(program, sizeof(vars)/sizeof(vars[0]), vars, GL_SEPARATE_ATTRIBS);
glTransformFeedbackVaryings(program, sizeof(vars)/sizeof(vars[0]), vars, GL_INTERVLEAVED_ATTRIBS);
glLinkProgram(program);//设置了这些东西需要重新链接着色器程序使其生效,不进行这一步不会产生错误但是此次设置transform feedback信息不会生效
交叉模式(左)与分离模式(右)下的内存数据结构如下:
有没有觉得这种数据获取方式就像个憨憨,当获取模式为GL_INTERLEAVED_ATTRIBS时,可以在连续存储的变量间保留空隙或者在不同的buffer中来回跳动。shader的内置变量gl_SkipComponents1......gl_SkipComponents4 与 gl_NextBuffer能够实现这些需求。当时需要注意的是,跳过的分量(空隙)依然被记入获取数据量的总数,也需要适当的使用动静分离。
static const char* const vars[] =
{
"foo",//从绑定点0开始写入数据
"gl_SkipCompents1",//一个浮点数空隙
"bar",
"gl_SkipCompents2",//两个浮点数空隙
"gl_NextBuffer",//移动到下一个绑定点1
"gl_SkipCompents4",
"baz",
"gl_SkipCompents2",
"gl_NextBuffer",
"gl_NextBuffer",//移动到了绑定点3
"iron",
"gl_SkipCompents3",
"copper"
};
glTransformFeedbackVaryings(program, sizeof(vars)/sizeof(vars[0]), vars, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(program);
3、transform feedback 的启用与停止
void glBeginTransformFeedback(GLenum primitiveMode)//参数必须是GL_POINTS、GL_LINES、GL_TRIANGLES中一种,要记录的绘制内容绘制图元需要一样活着geometry shader的输出图元与之一样
void glPauseTransformFeedback()
void glResumeTransformFeedback()//恢复记录是数据的填充会从停止的地方开始
void glEndTransformFeedback()