使用OpenGL的变换反馈(transform feedback)构造粒子系统

粒子系统是三维计算机图形学中用来模拟火,爆炸,雾,雪,流行尾迹或者发光轨迹等视觉效果的技术。粒子系统模拟这些现象的步奏简单的分为以下两步:

1. 更新每个粒子的属性,如粒子的颜色、速度,位置等。

2. 渲染粒子。采用billboard和纹理渲染粒子对象。

粒子系统负责管理粒子的个数和属性,当粒子结束生命周期时,如粒子的位置变换到特定的位置后,粒子系统负责将粒子设置为初始状态并开始新的旅程。但粒子系统有如下两个问题:

1. 粒子系统是在CPU中更新粒子的状态。每次更新状态后都需要将数据从cpu端拷贝到GPU端,假设粒子状态每帧都更新,那么数据的传递将对渲染的效率产生很大的影响。

2. 粒子系统中对粒子状态的更新都是用的同一个方法,GPU正好适合处理这样的运算。

我们可以只往GPU中传递一次粒子的初始属性,然后在GPU中维护粒子的属性并进行渲染。过程如下:

1. 使用两个shaderprogram,其中一个shader负责更新粒子的属性,另一个shader负责渲染渲染。

2. 利用变换反馈(transform feedback)将两组顶点缓冲区轮流作为渲染用的顶点数据,和保存更新后的顶点数据。变换反馈位于几何图形着色器和顶点装配阶段之间。因为几何着色器是可选的,如果不使用几何着色器,这些数据实际上是来自顶点着色器。变换反馈允许将一个顶点找色器或者几何着色器的结果保存到一个缓冲区中,这个缓冲区中保存的更新后的数据作为下一步的渲染使用。OPenGL中使用变化反馈的示例如下:

const char *tf_varying[]= {"out_position","out_color"};     glTransformFeedbackVaryings(update_program,2,tf_varying,GL_SEPARATE_ATTRIBS);

这两句话指明负责更新粒子状态的shader中的输出变量"out_position"和"out_color"将被被保存到变换反馈缓冲区中,需要在shader链接之前指定。然而变换反馈并没有真正的缓冲区,它只是一个绑定点,需要将真正的缓冲区绑定到该绑定点:

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,render_positionBuffer);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,1,render_colorBuffer);

第二个参数0和1就代表了变换反馈的绑定点,这个值可以通过glGenTransformFeedbacks(2,tid)函数来获取,但变换反馈的绑定点个数有限制。

程序的主渲染函数为render函数,首先使用更新粒子状态的shader,该shader轮流使用两组缓冲区,最开始粒子的初始状态是保存在A组缓冲区中的,B组缓冲区中的数据没有初始化。第一次进入render函数的时候,frame_index & 1为真,变换反馈绑定到B组,所以A组中的数据变换更新后被保存到了B组,渲染着色器使用的是B组的数据;第二次进入render函数时,使用B组的数据进行更新,并将新的粒子属性保存到A组,渲染的时候使用A组数据,如此反复进行。

void render(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glUseProgram(update_program);

if (frame_index & 1)

{

glBindVertexArray(vaoA);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,positionBufferB);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,1,colorBufferB);

}

else

{

glBindVertexArray(vaoB);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,0,positionBufferA);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,1,colorBufferA);

}

//查询变换反馈的结果

GLuint q;

GLint vertices_to_render;

glGenQueries(1,&q);

glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,q);

glEnable(GL_RASTERIZER_DISCARD);//禁止栅格化,几何着色器之后的阶段被删掉

glBeginTransformFeedback(GL_POINTS);

glDrawArrays(GL_POINTS, 0, 3);

glEndTransformFeedback();

glDisable(GL_RASTERIZER_DISCARD);

glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);

glGetQueryObjectiv(q,GL_QUERY_RESULT,&vertices_to_render);

glUseProgram(render_program);

if (frame_index & 1)

{

glBindVertexArray(vaoB);

}

else

{

glBindVertexArray(vaoA);

}

glDrawArrays(GL_POINTS, 0, 3);

++frame_index;

glutSwapBuffers();

}

以上程序渲染的时候使用的是glDrawArrays(GL_POINTS, 0, 3)命令,还需要使用几何着色器利用单个顶点生成四边形进行纹理贴图,以达到BillBoard的效果。一个简单几何着色器如下:

#version 400

layout(points) in;

layout(triangle_strip,max_vertices = 4) out;

uniform float size; //矩形的半径

out vec2 texcoord;

out vec4 color;

//const float size =0.5;

void main()

{

gl_Position = gl_in[0].gl_Position +vec4(-size, -size, 0.0, 0.0);

texcoord = vec2(0.0, 0.0);

color = vec4(1.0, 0.0, 0.0, 1.0);

EmitVertex();

gl_Position = gl_in[0].gl_Position +vec4(size, -size, 0.0, 0.0);

texcoord = vec2(1.0, 0.0);

color = vec4(1.0, 0.0, 0.0, 1.0);

EmitVertex();

gl_Position = gl_in[0].gl_Position +vec4(size, size, 0.0, 0.0);

texcoord = vec2(1.0, 1.0);

color = vec4(0.0, 0.0, 1.0, 1.0);

EmitVertex();

gl_Position = gl_in[0].gl_Position + vec4(0.0,size, 0.0, 0.0);

texcoord = vec2(0.0, 1.0);

color = vec4(0.0, 0.0, 1.0, 1.0);

EmitVertex();

EndPrimitive();

}

该几何着色器生成三角形的方法很粗陋,在实际使用中为达到billboard的效果,需要传入相机参数,并根据相机的参数来生成三角形顶点的位置,使三角形始终面向观察方向。此外,为达到更好的效果,纹理坐标需要动态更改。

OpenGL Partical System by Transform Feedback相关推荐

  1. OpenGL Transform Feedback转换反馈的实例

    OpenGL Transform Feedback转换反馈 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include "vapp.h" ...

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

    http://blog.csdn.net/coderling/article/details/44742077 transform feedback是OpenGL中比较酷炫的特性之一,他让客户端应用程 ...

  3. NDK OpenGL ES 3.0 开发(七):Transform Feedback

    该原创文章首发于微信公众号:字节流动 什么是 Transform Feedback Transform Feedback(变换反馈)是在 OpenGLES3.0 渲染管线中,顶点处理阶段结束之后,图元 ...

  4. OpenGL ES之变换反馈Transform Feedback的使用流程

    一.什么是 Transform Feedback ? Transform Feedback(变换反馈)是在 OpenGL ES 3.0 渲染管线中,顶点处理阶段结束之后,图元装配和光栅化之前的一个步骤 ...

  5. OpenGL Transform Feedback

    官网链接 使用TransFrom Feedback捕获图元数据,必须注意的几点: 必须在链接着色器之前设置要捕获的输出变量:glTransformFeedbackVaryings 顶点着色器.细分着色 ...

  6. Partical System

    创建"粒子系统物体"(点击菜单GameObject -> Create Other -> Particle System) 添加"粒子系统组件"(点 ...

  7. Unity ProjectSettings发布设置 - Player篇(未完待续)

    目录 一.Player 二.Icon 三.Resolution and Presentation(分辨率和显示) Resoulution Standalone Player Options 四.Spl ...

  8. OpenGL编程指南8-Transform Feedback例子理解

    transform feedback 是,OpenGL管线中,的,顶点处理阶段结束之后,图元装配和光栅化之前的一个步骤.transform feedback,可以重新捕获即将装配为图元(点.线段.三角 ...

  9. opengl版本发展史及各种概念的厘清

    1.版本发展 1 opengl的版本区别 1.1 opengl1.1        1995年,SGI推出了更为完善的OpenGL 1.1版本.OpenGL 1.1的性能比1.0版提高甚多.其中包括改 ...

最新文章

  1. 无法启动 MS DTC 事务管理器。LogInit 返回错误 0x2. 怎么办?
  2. b站电脑客户端_如何将B站的flv格式的视频转换成mp4格式
  3. FreeBSD长模式不兼容
  4. gorm利用钩子函数BeforeUpdate更新某个字段
  5. AchartEngine的柱状图属性设置
  6. PowerDesigner中Table视图同时显示Code和Name
  7. 内容分发网络(CDN)关键技术、架构与应用(一)
  8. 基于spring boot的Java开源商城系统(附完整版源码)
  9. lrc歌词编辑器 android,Lrc歌词编辑器(LRC速配歌词)
  10. 把 14 亿人拉到一个微信群,如何实现?
  11. Java打印直角三角形
  12. C语言中的free函数
  13. 多少开发人员 饿了么_做个美团(饿了么)网站需要多少钱?
  14. docker编配和服务发现
  15. firefox插件使用:hackbar
  16. linux查看nas剩余大小,老徐玩NAS 篇二:我的群晖储存空间哪儿去了——100%破案的教程...
  17. 如何设置Ubuntu 自动待机时间
  18. 3.6 51单片机-动态数码管
  19. 今天来个好玩儿的 “ 反射 ”
  20. 下列哪项不是python中对文件的读取操作-Python—文件读写操作

热门文章

  1. tryParse的用法。
  2. 中石油oj 奥运会跳水比赛 C++ sort函数对结构体的排序
  3. prometheus(普罗米修斯监控)部署、主机监控及docker容器监控
  4. 海思视频开发常见概念解析
  5. 2月8日机构调研以及涨停板高度最新状况
  6. Codesys冗余配置(基础)
  7. App Store上架App时遇到的的一些小问题及解决方案
  8. 阿里云内存平衡增强型r6e云服务器配置性能详解
  9. 解决VUE自定义拖拽指令时 onmouseup 与 click事件冲突
  10. 奥运门票第三阶段销售5月5日开始 不销售团体票