openGL之API学习(五十九)Transform Feedback变换反馈

OpenGL ES 3.0、openGL 4.x新增的功能

我们总是将顶点数据发送到图形处理器,并且只在帧缓存中生成绘制的像素。如果我们想要在经过顶点着色器或几何着色器之后捕获这些顶点呢?在这一章中,我们将探讨一种方法,即transform feedback。TransformFeedback是OpenGL管线中,顶点处理(如果有几何着色器,那么就在几何着色器后)之后,图元装配之前的一个步骤。

我们已经使用了VBO(顶点缓冲区对象)来存储用于绘制操作的顶点。Transform feedback 允许着色器把顶点写回这些。

例如,您可以构建一个顶点着色器,它模拟重力并将更新后的顶点位置写回缓冲区。这样,您就不必将这些数据从图形内存传输到主内存。最重要的是,你可以从如今GPU的巨大的并行处理能力中获益。

这个特性可以用来简化像粒子模拟这样的效果

让我们从一个简单的顶点着色器开始。

const GLchar* vertexShaderSrc = R"glsl(

in float inValue;

out float outValue;


void main()

{

outValue = sqrt(inValue);

}

)glsl";

 

这个顶点着色器似乎没有多大意义。它没有设置一个gl_position,它只接受一个任意的浮点数作为输入。幸运的是,我们可以使用Transform feedback来捕获结果,我们马上就会看到。

GLuint shader = glCreateShader(GL_VERTEX_SHADER);

glShaderSource(shader, 1, &vertexShaderSrc, nullptr);

glCompileShader(shader);


GLuint program = glCreateProgram();

glAttachShader(program, shader);

 编译着色器,创建一个程序并附加着色器,但是不要调用glLinkProgram()!在链接程序之前,我们必须告诉OpenGL,我们想要捕获到一个缓冲区中的输出属性。

const GLchar* feedbackVaryings[] = { "outValue" };

glTransformFeedbackVaryings(program, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);

 Transform Feedback的使用过程

1、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块名

2、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  缓存绑定点索引,绑定点最大数与设备实现有关可以通关GL_MAX_TRANSFORM_FEEDBACK_BUFFERS的值来查询。所有的OpenGL设备实现都可以至少支持64个绑定点。

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   绑定的缓存大小

3、配置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()必须再着色器程序链接之前调用。

4、启动和停止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(),就可以重新切换到正常的渲染模式。

5、从Transform Feedback取数据

GLfloat feedback[5];
glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(feedback), feedback);
printf("%f %f %f %f %f\n", feedback[0], feedback[1], feedback[2], feedback[3], feedback[4]);

6、绘制Transform Feedback的内容

void glDrawTransformFeedback(     GLenum mode,GLuint id);

参  数:mode 绘制模式

id  Transform Feedback的标识

 

 

 

 

你可能感兴趣的:(opengl,图形学,着色器,GLSL,openGL之API学习)