美文网首页
Transform Feedback

Transform Feedback

作者: 爱毯子的小狮子 | 来源:发表于2021-06-09 15:53 被阅读0次

    此部分内容参考自另一份教程https://open.gl/introduction
    该教程内容没有learnOpenGL丰富,但是有自己独特的内容,比如使用glew,transform feedback,以及提到了如何使用OpenGL做和画图不相关的通用编程。

    一、基本用法

    transform feedback有点通用编程的意思了,它的作用是读取shader处理后的vertex数据而和fragment无关。如果有geometry shader那么读取的vertex就是geometry输出的结果;如果没有就是vertex shader输出的结果。由于和fragment没有关系,为了节约不必要的计算步骤,我们使用glEnable(GL_RASTERIZER_DISCARD);来取消栅格化及之后的pipeline。
    transform feedback使用简单。首先要准备一个array buffer object,用于存储接受的值。我们要给该vbo开辟好足够的显存空间。

    GLuint tbo;
    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLint) * 20, nullptr, GL_STATIC_READ);  // nullptr, only for space
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    

    不需要初始化。然后正常准备输入vertex。
    其次一个要点就是要制定接受shader输出的哪些数据。我们在相应的shader里面要规定输出,但还需要指定哪些输出需要被捕捉(也包含捕捉顺序)。我们使用char **,即字符串的数列来指定要捕获变量的名字,比如有3个,分别是GLchar * varyingNames[] = {"aaa", "bbb", "ccc"}。然后使用

    glTransformFeedbackVaryings(program, 3, varyingNames, GL_INTERLEAVED_ATTRIBS);
    

    来具体指定。这一步必须在shader Link之前,创建之后,否则无效(pangolin使用的NV版本的可以在之后,好用许多)。
    最后一个要点是绑定接收的Buffer

    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
    

    然后激活transform feedback模式,画图,然后关掉模式:

    glBeginTransformFeedback(GL_POINTS);  // model is same with vertex output
    glDrawArrays(GL_POINTS, 0, 20);  // same with vertex input
    glEndTransformFeedback();
    

    最后,我们可以拿tbo继续当做输入去画图,也可以读取到内存:

    GLint feedback[20];
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
    glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(feedback), feedback);
    

    二、Feedback Buffer Mode

    目前我们可以把一个或几个attribute按照interleaved方式写入一个vbo当中,那么如何改变输出的格式呢?接下来的内容参考https://zhuanlan.zhihu.com/p/91533547并经过了实验验证。

    1. 不同attribute进入不同Buffer

    还是比如我们有三个attribute,shader Link时候的方法都一样,但是模式要选择separate attribute:

    glTransformFeedbackVaryings(program, 3, varyingNames, GL_SEPARATE_ATTRIBS);
    

    当画图前绑定Buffer的时候要依次绑定到目标不同的节点上:

    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, tbo1);
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, tbo2);
    

    其中第一个参数是目标target,第二个是节点(有最大限制),最后一个是我们创建的Buffer。然后激活-画图-终止激活。这样就得到了三个Buffer分别存储不同的attribute。

    2. 多个Interleaved Buffer

    如果有更高的要求,比如前俩个attribute以interleaved方式存储在一个Buffer里,最后一个放在里一个里面,可以选用占位字符串帮助我们转换Buffer。这时mode必须仍然是GL_INTERLEAVED_ATTRIBS,但是varingNames[] = {"aaa", "bbb", "gl_NextBuffer", "ccc"}。那个"gl_NextBuffer"是告诉shader往下一个Buffer里面写。

    3. attribute之间有间隔

    和2一样,但是占位字符串变成varingNames[] = {"aaa", "bbb", "gl_SkipComponents1", "ccc"}。其中最后的数字取1,2,3,4,代表跳过的单位数(我猜是byte,没试过)

    【为什么没有vao就不行?为什么绑定fid会崩溃?】
    第一个这个问题,https://learnopengl.com/Getting-started/Hello-Triangle有说明:在Core版本里,绑定vao已经是必须选项。pangolin会有各种乱七八糟版本。
    第二个因为版本不对,生成fid的函数是4.0之后才有的,把版本(glfwWindowHint)一改就可以了,不过在这里好像没什么用。

    相关文章

      网友评论

          本文标题:Transform Feedback

          本文链接:https://www.haomeiwen.com/subject/ztfjjltx.html