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

OpenGL学习笔记 transform feedback缓存粒子系统示例分析相关推荐

  1. OpenGL学习笔记:矩阵变换

    文章目录 缩放 glm矩阵表示 glm缩放矩阵实现 位移 齐次坐标 glm位移矩阵实现 旋转 沿x轴旋转 沿y轴旋转 沿z轴旋转 沿任意轴旋转 glm旋转矩阵实现 矩阵的组合 glm矩阵组合使用 接上 ...

  2. 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】

    ✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...

  3. OPENGL学习笔记之八

    OPENGL学习笔记之八 2017/11/15 阅读材料来自learnopengl.com以及learnopengl-cn.github.io 我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将 ...

  4. OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7888 ...

  5. OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7919 ...

  6. OpenGL学习笔记(一)绘制点线面及多面体

    OpenGL学习笔记(一)绘制点线面及多面体 绘制点线面 #include <iostream> #include <GL/GLUT.h> #define PI 3.14159 ...

  7. OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...

  8. 炼数成金Tensorflow学习笔记之2.4_Tensorflow简单示例

    炼数成金Tensorflow学习笔记之2.4_Tensorflow简单示例 代码及分析 代码及分析 # -*- coding: utf-8 -*- """ Created ...

  9. Adams学习笔记 第二讲 Adams入门示例

    Adams学习笔记 第二讲 Adams入门示例 Falling Stone石头坠落 问题描述 使用步骤 结论与分析 软件环境:Adams2018(官方文档使用的开发环境为2013.2) 声明:本讲内容 ...

最新文章

  1. Day 14 保护环境的建议
  2. @TransactionalEventListener与@Async实现事务提交后异步处理事件
  3. Google Map App 问题集锦
  4. 两种方式:mysql查看正在执行的sql语句
  5. mysql 优化配置 大批量数据插入_[译] MySQL 最佳实践 —— 高效插入数据
  6. java怎么实现两个对象内容的交换
  7. Sublime Text3搭建go运行环境
  8. greensock下载_GreenSock动画平台初学者指南
  9. 百度云满速下载原理与方法
  10. 大学时私藏了哪些工具、网站?在这里共享出来了
  11. 聊天软件开发_3_数据库表设计
  12. c语言aps审核,APS考官最讨厌的几类人
  13. 日拱一卒,“功不唐捐
  14. Linux 之旅 8:初识 BASH
  15. TEM TE TM模的区别和电磁波模式
  16. C - Factors of Factorial(数学)
  17. 网络游戏软件销售渠道模式举例及分析
  18. linux进程与服务管理,linux基础之进程管理与服务
  19. incident用法_incident与_accident区别
  20. 六种比较常用的SEM方法

热门文章

  1. python怎么设置回文数_python如何写一个函数判断回文数?
  2. Excel的导入与导出
  3. pcm5102a解码芯片音质评测_一台可换芯片的解码机评测--对比PCM1794和CS4398芯片(下)...
  4. 海信电视root工具_中国企业的远见:用一项自主技术,打败日韩电视,成为行业引领者...
  5. 比较好的电脑系统_效果好的筛分移动破碎站有优惠吗?
  6. vim python 代码提示_linux下vim python代码自动补全
  7. java面向服务架构_面向服务的体系架构 SOA(一) --- 基于TCP、HTTP协议的RPC
  8. 对一个可进行带括号 加减乘除运算类的分析
  9. Hibernate中配置C3P0连接池
  10. MongoDB入门示例及介绍