OpenGL学习笔记 transform feedback缓存&粒子系统示例分析

来源:互联网 发布:潍坊网络招聘 编辑:程序博客网 时间:2024/06/01 10:50

http://blog.csdn.net/coderling/article/details/44742077


 transform feedback是OpenGL中比较酷炫的特性之一,他让客户端应用程序可以获取到渲染流水线上的顶点数据。基于这一特性实现了基于z-pass场景决策渲染技术,当然在此并没有去了解何为z-pass场景决策渲染技术,总之是一个可以有效减少渲染数据的输送。这里只是通过一个简单的例子系统,去了解transform feedback对象的使用方法。

 正文:

        1、transform feedback:        

             transform feedback是OpenGL渲染管线中,顶点处理阶段结束之后,图元装配和光栅化之前的一个步骤。transform feedback可以重新捕获即将装配为图元(点,线段,三角形)的顶点,然后你将他们的部分或者全部属性传递到缓存对象。每个顶点在传递到图元装配阶段时(之前),将所有需要捕获的属性数据记录到一个或者多个缓存对象当中(至于捕获那些数据,都是在我们控制之下的),程序可以通过缓存回读这些数据,或者将他们用于后续的渲染操作。
            tansform feedback所有状态通过一个transform feedback对象管理,这个状态包括所有用于记录顶点数据的缓存对象,用于标识缓存对象的计数器(名称glGen*系列函数返回),以及用于标识transform feedback当前是否启用的状态量。transform对象的创建绑定过程和一般的OpenGL对象相似:
                a. void glGenTransformFeedbacks( GLsizei n, GLuint* ids ) 为transform feedback对象生成n个名称,并且将生成的名称记录到数组ids中。0是保留名称,openGL默认tranform feedback,函数将永远不会返回0.
                b. void glBindTransformFeedback( GLenum target, GLuint id )    将一个id(glGen*返回的名称)绑定到指定的target(必须是GL_TRANSFORM_FEEDBACK)所指定的环境中。他做了三个工作:1、如果第一次绑定这个名称,将创建一个tranform feedback对象,使用默认状态值对他进行初始化,并设为当前transform feedback;2、否则单纯的帮该transform feedback激活为当前;3、如果id为0,则相当于重新回到默认的transform feedback对象上(解除所有值钱绑定的transform feedback对象)
                c. GLboolean glIsTransformFeedback( GLenum id )判断id是否为一个transform feedback对象。
                d.当绑定了一个transform feedback对象之后,所有可能会影响到transform feedback状态的命令都会作用于这个对象。不过并不需要为了使用transform feedback相关功能而去特别定义一个transform feedback对象想,因为系统会内置一个默认的transform feedback对象(名称为id = 0)
                e. void glDeleteTransformFeedbacks( GLsizei n, const GLuint* ids )删除n个transform feedback对象。在本次transform feedback结束之后才回去删除

        2.transform feedback缓存

                transform feedback主要用来管理将顶点捕捉到缓存对象的相关状态。这个状态中包含当前连接到的transform feedback缓存绑定点的缓存对象。可以同时给transform feedback绑定多个缓存,也可以绑定缓存对象的多个子块,甚至可以将同一个缓存对象不用子块绑定到不同的transform feedback缓存绑定点上。
绑定接口: void glBindBufferBase( GLenum target, GLuint index, GLuint buffer ) 其中target自然必须为GL_TRANSFORM_FEEDBACK_BUFFER,而index必须为当前绑定的transform feedback对象的缓存绑定点索引,绑定点最大数与设备实现有关可以通关GL_MAX_TRANSFORM_FEEDBACK_BUFFERS的值来查询。所有的OpenGL设备实现都可以至少支持64个绑定点。也可以将一个缓存对象的一部分绑定到某个transform feedback绑定点:void glBindBufferRange( GLenum GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size )    offset 和size单位都为字节,定义了buffer缓存的范围。需要特别注意的是亮点:1、保证一个缓存绑定到多个transform feedback绑定点时他们使用的区域不能重叠。2.、glBindBufferBase()和glBindBufferRange()都不会主动去创建缓存对象(这与glBindBuffer不同),而创建缓存对象的工作还是由glBindBuffer()来承担,数据操作还是由glBufferData(),glBufferSubData(),glGetBufferSubData()来完成。
(关于缓存绑定点的解释:在这里可能会问缓存绑定点指的是什么?其实就是一个点,也可以理解为一个名称,他有着最大限制,至少为64,是着色器访问缓存对象的一个桥梁(快速便捷的),略微搜了下,有个一个叫UBO(uniform Block Object)的应用,看了多少会对绑定点有所了解,遗憾的是并没有找到,transform feedback的关于这个桥梁保证准确找到数据的呢?现在也并不能很好的理解之,mark下一个地址:http://www.zwqxin.com/archives/opengl/talk-about-transform-feedback.html 讲述了transform feedback的高级应用
                初始化过程示例:
      //缓存名称
    GLuint buffer;
    glGenBuffers( 1, &buffer )
    
    //绑定到TRANSFORM_FEEDBACK创建缓存对象。
    glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, buffer )

    //glBufferData初始化数据,参数为NULL,申请空间保留使用
    glBufferData( GL_TRANFORM_FEEDBACK_BUFFER, 1024*1024, NULL, GL_DYNAMIC_COPY )

    //绑定到缓存绑定点,一般用于index = 1,一般用于index = 0
    glBindBufferRange( GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 512*1024 )
    glBindBufferRange( GL_TRANSFORM_FEEDBACK_BUFFER, 1, buffer, 512*1024, 512*1024 )

        3、transform feedback的变量配置

transform feedback所绑定的缓存是一个transform feedback对象关联在一起,顶点(或者几何)着色器的输出要记录在那些缓存当中,这些配置信息是保存在当前程序对象当中。openGL提供了相应的接口让我们配置那些变量应该被记录。
            void glTransformFeedbackVaryings( GLuint program, GLsizei count, const GLchar** varyings, GLenum bufferMode )
        参数varyings指定了一个变量数组,也就是那些需要被feedback的变量。program是对应的着色器程序,count表示varyings中字符串的数量,bufferMode指定了捕获变量的模式:a、分离模式(GL_SEPARATE_ATTRIBS):每个变量将会被记录到单独的缓存对象中;b、交叉模式(GL_INTERLEAVED_ATTRIBS):那么所有的变量是一个接着一个记录到绑定到当前transform feedback对象的第一个绑定点的缓存对象里!
        openGL还提供了一些内置变量来帮助 我们更灵活的控制捕获的数据在缓存中的对齐方式:gl_SkipComponents1、gl_SkipComponents2、gl_SkipComponents3、gl_SkipComponents4、gl_NextBuffer。对于gl_SkipComponents*,OpenGL会留出指定数量的空隙(1,2,3,4)。当捕获模式为交叉模式这些才可以使用这些gl_SkipComponents*内置变量;而对于gl_NextBuffer,OpenGL会把变量传递到当前绑定点的下一个transform feedback缓存中,这样在GL_INTERLEAVED_ATTRIBS模式下也可以将变量保存在单独的缓存当中,如果捕获模式为GL_SEPARATE_ATTRIBS是遇到gl_NextBuffer,或者在GL_INTERLEAVED_ATTRIBS下连续遇到gl_NextBuffer(两个而上)那么将跳过当前绑定点,并在当前绑定的缓存中不会记录任何数据。在这里似乎可以回答之前括号里面关于绑定点的疑惑:首先每个绑定点对应于一个缓存或一部分缓存,他总是独立享有指定的缓存,不能与其他绑定点交叉。对于顶点着色器和几何着色器而言绑定点似乎可以理解为地址。在捕获数据是总是先从索引为当前transform feedback对象的第一个绑定点索引开始(索引值最小那个)输出数据,并根据glTransformFeedbackVaryings()  varyings 参数指定的对齐方式存放在缓存当中。

       4、transform feedback捕获启动与停止、

             transform feedback 可以随时启动和停止,甚至暂停。一些控制transform启动停止的api:
               void glBeginTransformFeedback( GLenum primitiveMode ):开始并设置transform feedback将要记录的图元类型,primitiveMode必须是:GL_POINTS, GL_LINES、GL_TRIANGLES三个之一。在之后的绘制命令中团员类型需要与之相符,或则几何着色器中输出类型需要与之相符。、
                void glPuaseTransformFeedback():暂停transform feedback对变量的记录,但transform feedback还是处于启动状态。如果transform feedback没有启动则OpenGL产生错误。
                void glResumeTransformFeedback():重新开启一个之前通过glPuaseTransformFeedback()暂停的feedback过程,如果transform feedback没有启动,或者没有被处于活动状态,则产生OpenGL错误。
                void glEndTransformFeedback()结束transform feedback过程。

       5、基于transform feedback的粒子系统分析


                程序分为两个处理过程,创建了2个着色器分别管理这两个过程。第一个负责渲染模型对象,第二个负责渲染粒子和实现粒子与模型对象的碰撞检测。在碰撞检测过程中用到的模型顶点数据就是将是通过transform feedback获取,而由于需要记录粒子的位置速度信息需要保留给当前渲染使用,单一缓冲无法对新数据进行记录,所以采用了双缓冲区,同样使用transform feedback来记录本次粒子渲染结果,给下一帧使用。
            粒子系统渲染顶点着色器分析:
#version 410
 
  uniform mat4 model_matrix;
  uniform mat4 projection_matrix;
  uniform int triangle_count;//模型的,在绘制更新粒子前赋值三角形数量
 
//输入
  layout (location = 0) in vec4 position;
  layout (location = 1) in vec3 velocity;
 //输出
  out vec4 position_out;
  out vec3 velocity_out;

//在transform feedback记录的数据,使用纹理查找tbo获取三角形平面
  uniform samplerBuffer geometry_tbo;
  uniform float time_step = 0.02;//更新时间步长

//线段与三角形平面相交测试
  bool intersect(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, out vec3 point)
  {
      vec3 u, v, n;
      vec3 w0, w;
      float r, a, b;

     u = (v1 - v0);
      v = (v2 - v0);
      n = cross(u, v);
      if (length(n) < 0.1)
        return false;

      w0 = origin - v0;
      a = -dot(n, w0);
      b = dot(n, direction);
      if (abs(b) < 0.1)
        return false;
 
      r = a / b;
      if (r < 0.0 || r > 1.0)
          return false;
 
      point = origin + r * direction;

      float uu, uv, vv, wu, wv, D;

      uu = dot(u, u);
      uv = dot(u, v);
      vv = dot(v, v);
      w = point - v0;
      wu = dot(w, u);
      wv = dot(w, v);
      D = uv * uv - uu * vv;

      float s, t;

      s = (uv * wv - vv * wu) / D;
      if (s < 0.0 || s > 1.0)
          return false;
      t = (uv * wu - uu * wv) / D;
      if (t < 0.0 || (s + t) > 1.0)
          return false;
  
      return true;
    }  

//碰撞后反射向量计算
  vec3 reflect_vector(vec3 v, vec3 n)
  {
      return v - 2.0 * dot(v, n) * n;
  }
 
  void main(void)
  {
      vec3 accelleration = vec3(0.0, -0.3, 0.0);
      vec3 new_velocity = velocity + accelleration * time_step;
      vec4 new_position = position + vec4(new_velocity * time_step, 0.0);//计算粒子新的速度和位置
      vec3 v0, v1, v2;
      vec3 point;
      int i;
     for (i = 0; i < triangle_count; i++)
      {
            //利用纹理查找tbo获取模型的三角形平面。做相交测试,如果相交在交点处计算反弹之后的新速度向量和位置
          v0 = texelFetch(geometry_tbo, i * 3).xyz
          v1 = texelFetch(geometry_tbo, i * 3 + 1).xyz;
          v2 = texelFetch(geometry_tbo, i * 3 + 2).xyz;
          if (intersect(position.xyz, position.xyz - new_position.xyz, v0, v1, v2, point))
          {
              vec3 n = normalize(cross(v1 - v0, v2 - v0));
              new_position = vec4(point + reflect_vector(new_position.xyz - point, n), 1.0);
              new_velocity = 0.8 * reflect_vector(new_velocity, n);
          }
      }

        //超出一定范围,回归。
      if (new_position.y < -80.0)
      {
          new_position = vec4(-new_position.x * 0.3, position.y + 200.0, 0.0, 1.0);
          new_velocity *= vec3(0.2, 0.1, -0.3);
      }
      velocity_out = new_velocity * 0.9999;//几乎无衰减的速度
      position_out = new_position;
      gl_Position = projection_matrix * (model_matrix * position);
  }

粒子系统片元着色器:非常简单,只是设置了粒子的颜色为白色。
#version 410

  layout (location = 0) out vec4 color;\

  void main(void)
  {
     color = vec4(1.0);
  }

模型渲染的顶点着色器和片元着色器和之前的例子没什么区别。可以再代码里面看到。或者在之前的文章中看到相关详细注释

5.粒子实例运行截图



粒子从模型头顶落下



粒子撞击模型时被弹开



Then End~~~
(牢骚:愈发无聊的生活,愈发没有激情的工作,青春只是在流逝,没有痕迹)

被遗忘的代码(15.3.31)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "transform_fb.h"  
  2. #include "vbm_xfb.h"  
  3. #include "vutils.h"  
  4. #include "vmath.h"  
  5.   
  6. namespace transform  
  7. {  
  8.     float aspect = 800.0/600.0;  
  9.     GLuint update_prog;  
  10.     GLuint vao[2];  
  11.     GLuint vbo[2];  
  12.     GLuint xfb;  
  13.   
  14.     GLuint render_prog;  
  15.     GLuint geometry_vbo;  
  16.     GLuint render_vao;  
  17.     GLint render_model_matrix_loc;  
  18.     GLint render_projection_matrix_loc;  
  19.   
  20.     GLuint geometry_tex;  
  21.   
  22.     GLuint geometry_xfb;  
  23.     GLuint particle_xfb;  
  24.   
  25.     GLint model_matrix_loc;  
  26.     GLint projection_matrix_loc;  
  27.     GLint triangle_count_loc;  
  28.     GLint time_step_loc;  
  29.   
  30.     VBObject object;  
  31.   
  32.     const int point_count = 5000;  
  33.     static unsigned int seed = 0x13371337;  
  34. };  
  35.   
  36. using namespace transform;  
  37.   
  38. static inline float random_float()  
  39. {  
  40.     float res;  
  41.     unsigned int tmp;  
  42.   
  43.     seed *= 16807;  
  44.   
  45.     tmp = seed ^ (seed >> 4) ^ (seed << 15);  
  46.   
  47.     *((unsigned int *)&res) = (tmp >> 9) | 0x3F800000;  
  48.   
  49.     return (res - 1.0f);  
  50. }  
  51.   
  52. static vmath::vec3 random_vector(float minmag = 0.0f, float maxmag = 1.0f)  
  53. {  
  54.     vmath::vec3 randomvec(random_float() * 2.0f - 1.0f, random_float() * 2.0f - 1.0f, random_float() * 2.0f - 1.0f);  
  55.     randomvec = normalize(randomvec);  
  56.     randomvec *= (random_float() * (maxmag - minmag) + minmag);  
  57.   
  58.     return randomvec;  
  59. }  
  60.   
  61. static inline int min(int a, int b)  
  62. {  
  63.     return a < b ? a : b;  
  64. }  
  65.   
  66. void transformFBInit()  
  67. {  
  68.     int i, j;  
  69.     update_prog = glCreateProgram();  
  70.   
  71.     static const char update_vs_source[] =  
  72.         "#version 410\n"  
  73.         "\n"  
  74.         "uniform mat4 model_matrix;\n"  
  75.         "uniform mat4 projection_matrix;\n"  
  76.         "uniform int triangle_count;\n"  
  77.         "\n"  
  78.         "layout (location = 0) in vec4 position;\n"  
  79.         "layout (location = 1) in vec3 velocity;\n"  
  80.         "\n"  
  81.         "out vec4 position_out;\n"  
  82.         "out vec3 velocity_out;\n"  
  83.         "\n"  
  84.         "uniform samplerBuffer geometry_tbo;\n"  
  85.         "uniform float time_step = 0.02;\n"  
  86.         "\n"  
  87.         "bool intersect(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, out vec3 point)\n"  
  88.         "{\n"  
  89.         "    vec3 u, v, n;\n"  
  90.         "    vec3 w0, w;\n"  
  91.         "    float r, a, b;\n"  
  92.         "\n"  
  93.         "    u = (v1 - v0);\n"  
  94.         "    v = (v2 - v0);\n"  
  95.         "    n = cross(u, v);\n"  
  96.         // "    if (length(n) < 0.1)\n"  
  97.         // "        return false;\n"  
  98.         "\n"  
  99.         "    w0 = origin - v0;\n"  
  100.         "    a = -dot(n, w0);\n"  
  101.         "    b = dot(n, direction);\n"  
  102.         //"    if (abs(b) < 0.1)\n"  
  103.         //"        return false;\n"  
  104.         "\n"  
  105.         "    r = a / b;\n"  
  106.         "    if (r < 0.0 || r > 1.0)\n"  
  107.         "        return false;\n"  
  108.         "\n"  
  109.         "    point = origin + r * direction;\n"  
  110.         "\n"  
  111.         "    float uu, uv, vv, wu, wv, D;\n"  
  112.         "\n"  
  113.         "    uu = dot(u, u);\n"  
  114.         "    uv = dot(u, v);\n"  
  115.         "    vv = dot(v, v);\n"  
  116.         "    w = point - v0;\n"  
  117.         "    wu = dot(w, u);\n"  
  118.         "    wv = dot(w, v);\n"  
  119.         "    D = uv * uv - uu * vv;\n"  
  120.         "\n"  
  121.         "    float s, t;\n"  
  122.         "\n"  
  123.         "    s = (uv * wv - vv * wu) / D;\n"  
  124.         "    if (s < 0.0 || s > 1.0)\n"  
  125.         "        return false;\n"  
  126.         "    t = (uv * wu - uu * wv) / D;\n"  
  127.         "    if (t < 0.0 || (s + t) > 1.0)\n"  
  128.         "        return false;\n"  
  129.         "\n"  
  130.         "    return true;\n"  
  131.         "}\n"  
  132.         "\n"  
  133.         "vec3 reflect_vector(vec3 v, vec3 n)\n"  
  134.         "{\n"  
  135.         "    return v - 2.0 * dot(v, n) * n;\n"  
  136.         "}\n"  
  137.         "\n"  
  138.         "void main(void)\n"  
  139.         "{\n"  
  140.         "    vec3 accelleration = vec3(0.0, -0.3, 0.0);\n"  
  141.         "    vec3 new_velocity = velocity + accelleration * time_step;\n"  
  142.         "    vec4 new_position = position + vec4(new_velocity * time_step, 0.0);\n"  
  143.         "    vec3 v0, v1, v2;\n"  
  144.         "    vec3 point;\n"  
  145.         "    int i;\n"  
  146.         "    for (i = 0; i < triangle_count; i++)\n"  
  147.         "    {\n"  
  148.         "        v0 = texelFetch(geometry_tbo, i * 3).xyz;\n"  
  149.         "        v1 = texelFetch(geometry_tbo, i * 3 + 1).xyz;\n"  
  150.         "        v2 = texelFetch(geometry_tbo, i * 3 + 2).xyz;\n"  
  151.         "        if (intersect(position.xyz, position.xyz - new_position.xyz, v0, v1, v2, point))\n"  
  152.         "        {\n"  
  153.         "            vec3 n = normalize(cross(v1 - v0, v2 - v0));\n"  
  154.         "            new_position = vec4(point + reflect_vector(new_position.xyz - point, n), 1.0);\n"  
  155.         "            new_velocity = 0.8 * reflect_vector(new_velocity, n);\n"  
  156.         "        }\n"  
  157.         "    }\n"  
  158.         "    if (new_position.y < -80.0)\n"  
  159.         "    {\n"  
  160.         "        new_position = vec4(-new_position.x * 0.3, position.y + 200.0, 0.0, 1.0);\n"  
  161.         "        new_velocity *= vec3(0.2, 0.1, -0.3);\n"  
  162.         "    }\n"  
  163.         "    velocity_out = new_velocity * 0.9999;\n"  
  164.         "    position_out = new_position;\n"  
  165.         "    gl_Position = projection_matrix * (model_matrix * position);\n"  
  166.         "}\n";  
  167.   
  168.     static const char white_fs[] =  
  169.         "#version 410\n"  
  170.         "\n"  
  171.         "layout (location = 0) out vec4 color;\n"  
  172.         "\n"  
  173.         "void main(void)\n"  
  174.         "{\n"  
  175.         "    color = vec4(1.0);\n"  
  176.         "}\n";  
  177.   
  178.     vglAttachShaderSource(update_prog, GL_VERTEX_SHADER, update_vs_source);  
  179.     vglAttachShaderSource(update_prog, GL_FRAGMENT_SHADER, white_fs);  
  180.   
  181.     static const char* varyings[] =  
  182.     {  
  183.         "position_out""velocity_out"  
  184.     };  
  185.   
  186.     glTransformFeedbackVaryings( update_prog, 2, varyings, GL_INTERLEAVED_ATTRIBS );  
  187.       
  188.     glLinkProgram( update_prog );  
  189.     glUseProgram( update_prog );  
  190.   
  191.     model_matrix_loc = glGetUniformLocation( update_prog, "model_matrix" );  
  192.     projection_matrix_loc = glGetUniformLocation( update_prog, "projection_matrix" );  
  193.     triangle_count_loc = glGetUniformLocation( update_prog, "triangle_count" );  
  194.     time_step_loc = glGetUniformLocation( update_prog, "time_step" );  
  195.   
  196.     //  
  197.     render_prog = glCreateProgram();  
  198.   
  199.     static const char render_vs[] =  
  200.         "#version 410\n"  
  201.         "\n"  
  202.         "uniform mat4 model_matrix;\n"  
  203.         "uniform mat4 projection_matrix;\n"  
  204.         "\n"  
  205.         "layout (location = 0) in vec4 position;\n"  
  206.         "layout (location = 1) in vec3 normal;\n"  
  207.         "\n"  
  208.         "out vec4 world_space_position;\n"  
  209.         "\n"  
  210.         "out vec3 vs_fs_normal;\n"  
  211.         "\n"  
  212.         "void main(void)\n"  
  213.         "{\n"  
  214.         "    vec4 pos = (model_matrix * (position * vec4(1.0, 1.0, 1.0, 1.0)));\n"  
  215.         "    world_space_position = pos;\n"  
  216.         "    vs_fs_normal = normalize((model_matrix * vec4(normal, 0.0)).xyz);\n"  
  217.         "    gl_Position = projection_matrix * pos;\n"  
  218.         "}\n";  
  219.   
  220.     static const char blue_fs[] =  
  221.         "#version 410\n"  
  222.         "\n"  
  223.         "layout (location = 0) out vec4 color;\n"  
  224.         "\n"  
  225.         "in vec3 vs_fs_normal;\n"  
  226.         "\n"  
  227.         "void main(void)\n"  
  228.         "{\n"  
  229.         "    color = vec4(0.0, 0.2, 0.0, 1.0) + vec4(0.2, 0.5, 0.4, 1.0) * abs(vs_fs_normal.z) + vec4(0.8, 0.9, 0.7, 1.0) * pow(abs(vs_fs_normal.z), 70.0);\n"  
  230.         "}\n";  
  231.   
  232.     vglAttachShaderSource( render_prog, GL_VERTEX_SHADER, render_vs );  
  233.     vglAttachShaderSource(render_prog, GL_FRAGMENT_SHADER, blue_fs);  
  234.   
  235.     static const char* varyings2[] =  
  236.     {  
  237.         "world_space_position"  
  238.     };  
  239.   
  240.     glTransformFeedbackVaryings( render_prog, 1, varyings2, GL_INTERLEAVED_ATTRIBS );  
  241.   
  242.     glLinkProgram( render_prog );  
  243.     glUseProgram( render_prog );  
  244.   
  245.     render_model_matrix_loc = glGetUniformLocation( render_prog, "model_matrix" );  
  246.     render_projection_matrix_loc = glGetUniformLocation( render_prog, "projection_matrix" );  
  247.   
  248.     glGenVertexArrays( 2, vao );  
  249.     glGenBuffers( 2, vbo );  
  250.   
  251.     for (i = 0; i < 2; i++)  
  252.     {  
  253.         glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, vbo[i] );  
  254.         glBufferData( GL_TRANSFORM_FEEDBACK_BUFFER, point_count * (sizeof(vmath::vec4) + sizeof(vmath::vec3) ), NULL, GL_DYNAMIC_COPY );  
  255.         GLenum errCode = glGetError();  
  256.           
  257.         if (0 == i)  
  258.         {  
  259.             struct buffer_t  
  260.             {  
  261.                 vmath::vec4 position;  
  262.                 vmath::vec3 velocity;  
  263.             };  
  264.             buffer_t* buffer = (buffer_t*)glMapBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, GL_WRITE_ONLY );  
  265.             for (j = 0; j < point_count; j++)  
  266.             {  
  267.                 buffer[j].velocity = random_vector();  
  268.                 buffer[j].position = vmath::vec4(buffer[j].velocity + vmath::vec3(-0.5f, 120.0f, 0.0f), 1.0f);  
  269.                 buffer[j].velocity = vmath::vec3(buffer[j].velocity[0], buffer[j].velocity[1] * 0.3f, buffer[j].velocity[2] * 0.3f);  
  270.             }  
  271.   
  272.             glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);  
  273.         }  
  274.         glBindVertexArray(vao[i]);  
  275.         glBindBuffer( GL_ARRAY_BUFFER, vbo[i] );  
  276.         glVertexAttribPointer( 0, 4, GL_FLOAT, GL_FALSE, sizeof(vmath::vec4) + sizeof(vmath::vec3), NULL);  
  277.         glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof(vmath::vec4) + sizeof(vmath::vec3), (GLvoid*)sizeof(vmath::vec4));  
  278.         glEnableVertexAttribArray(0);  
  279.         glEnableVertexAttribArray(1);  
  280.     }  
  281.   
  282.     glGenBuffers( 1, &geometry_vbo );  
  283.     glGenTextures( 1, &geometry_tex ); //geometry_tex没有使用到  
  284.     glBindBuffer( GL_TEXTURE_BUFFER, geometry_vbo );  
  285.     glBufferData( GL_TEXTURE_BUFFER, 1024 * 1024 * sizeof(vmath::vec4), NULL, GL_DYNAMIC_COPY );  
  286.     glBindTexture( GL_TEXTURE_BUFFER, geometry_tex ); //作者好像并没有详细检查代码QAQ,这里根本就写错了  
  287.     glTexBuffer( GL_TEXTURE_BUFFER, GL_RGBA32F, geometry_vbo );  
  288.   
  289.     //感觉后面这个render_vao根本没意义呀,render_prog只需要渲染object对象,而object有自身的vao。况且geometry_vbo没有数据!  
  290.     //在渲染了模型对象才会transform feedback捕获到数据.display过程完全用不到这个render_vao  
  291.     /*glGenVertexArrays( 1, &render_vao ); 
  292.     glBindVertexArray( render_vao ); 
  293.     glBindBuffer( GL_ARRAY_BUFFER, geometry_vbo ); 
  294.     glVertexAttribPointer( 0, 4, GL_FLOAT, GL_FALSE, 0, NULL ); 
  295.     glEnableVertexAttribArray(0);*/  
  296.   
  297.     glClearColor( 0.0f, 0.0f, 0.0f, 1.0f);  
  298.     glClearDepth( 1.0f );  
  299.   
  300.     object.LoadFromVBM("../8edlib/media/armadillo_low.vbm", 0, 1, 2);  
  301.       
  302. }  
  303.   
  304. void transformFBDisplay()  
  305. {  
  306.     static int frame_count = 0;  
  307.     float t = float(GetTickCount() & 0x3FFFF) / float(0x3FFFF);  
  308.     static float q = 0.0f;  
  309.     static const vmath::vec3 X( 1.0f, 0.0f, 0.0f );  
  310.     static const vmath::vec3 Y( 0.0f, 1.0f, 0.0f );  
  311.     static const vmath::vec3 Z( 0.0f, 0.0f, 1.0f );  
  312.   
  313.     vmath::mat4 projection_matrix(vmath::frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 5000.0f) * vmath::translate(0.0f, 0.0f, -100.0f));  
  314.     vmath::mat4 model_matrix(vmath::scale(0.3f) *  
  315.         vmath::rotate(t * 360.0f, 0.0f, 1.0f, 0.0f) *  
  316.         vmath::rotate(t * 360.0f * 3.0f, 0.0f, 0.0f, 1.0f));  
  317.   
  318.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
  319.   
  320.     glEnable( GL_CULL_FACE );  
  321.     glEnable( GL_DEPTH_TEST );  
  322.     glDepthFunc( GL_LEQUAL );  
  323.   
  324.     glUseProgram( render_prog );  
  325.     glUniformMatrix4fv( render_model_matrix_loc, 1, GL_FALSE, model_matrix );  
  326.     glUniformMatrix4fv( render_projection_matrix_loc, 1, GL_FALSE, projection_matrix );  
  327.   
  328.     glBindVertexArray( render_vao );  
  329.   
  330.     glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, geometry_vbo );  
  331.   
  332.     glBeginTransformFeedback( GL_TRIANGLES );  
  333.     object.Render();  
  334.     glEndTransformFeedback();  
  335.   
  336.     glUseProgram( update_prog );  
  337.     model_matrix = vmath::mat4::identity();  
  338.     glUniformMatrix4fv( model_matrix_loc, 1, GL_FALSE, model_matrix );  
  339.     glUniformMatrix4fv( projection_matrix_loc, 1, GL_FALSE, projection_matrix );  
  340.     glUniform1i( triangle_count_loc, object.GetVertexCount()/3 );  
  341.   
  342.     if (t > q)  
  343.     {  
  344.         glUniform1f(time_step_loc, 0.2f);  
  345.         //glUniform1f( time_step_loc, (t-q)*2000.0f );  
  346.         static TCHAR debugStr[4096] = L"";  
  347.         swprintf_s(debugStr, L" FrameCount = %.3f\n", t);  
  348.         OutputDebugString(debugStr);  
  349.     }  
  350.     q = t;  
  351.     if ((frame_count & 1) != 0)  
  352.     {  
  353.         glBindVertexArray( vao[1] );  
  354.         glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo[0] );  
  355.     }  
  356.     else  
  357.     {  
  358.         glBindVertexArray( vao[0] );  
  359.         glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo[1] );  
  360.     }  
  361.   
  362.     glBeginTransformFeedback( GL_POINTS );  
  363.     glDrawArrays(GL_POINTS, 0, point_count/*min(point_count, frame_count >> 2 )*/);  
  364.     glEndTransformFeedback();  
  365.   
  366.     glBindVertexArray(0);  
  367.       
  368.       
  369.     frame_count++;  
  370.       
  371. }  
  372.   
  373. void transformFBUpdate(float delta)  
  374. {  
  375.   
  376. }  


0 0