【发布时间】:2014-02-22 22:11:12
【问题描述】:
我正在使用 OpenGL 开发一个简单的粒子系统,我需要在 GPU 上生成粒子。通常我将粒子表示为GL_POINTS,并且一开始只使用一个粒子生成点。
我所做的是创建两个顶点缓冲区对象 (VBO) 并根据 最大粒子数 在 GPU 上分配内存。然后创建两个变换反馈缓冲区 (TFB),每个都绑定到一个 VBO 的输出。第一个 TFB 代表第二个 VBO 的输入,反之亦然(交换缓冲区)。
然后我在几何着色器上生成新的顶点(= 点、粒子)。
几何着色器代码:
#version 330 compatibility
#extension GL_ARB_geometry_shader4 : enable
layout(points) in;
layout(points, max_vertices = 3) out;
in block{
vec4 v_WorldPosition;
vec3 f_Position;
vec3 f_Color;
} In[];
out block{
vec4 v_WorldPosition;
vec4 v_Color;
} Out;
out feedback{
vec3 f_Position;
vec3 f_Color;
} feedOut;
const int i = 0; // No need for loop (points. In.length() == 1)
void main()
{
feedOut.f_Position = In[i].f_Position;
feedOut.f_Color = In[i].f_Color;
if(In[i].f_Color.g == 1){
feedOut.f_Color.g = 0;
}
Out.v_Color = vec4(feedOut.f_Color, 1);
gl_Position = In[i].v_WorldPosition;
EmitVertex();
EndPrimitive();
if(In[i].f_Color.g == 1){
// create new particle
feedOut.f_Position = In[i].f_Position;
feedOut.f_Color = vec3(1,0,0);
Out.v_Color = vec4(feedOut.f_Color, 1);
gl_Position = In[i].v_WorldPosition;
EmitVertex();
EndPrimitive();
}
}
}
暂时我使用绿色信息来确定粒子是否应该分成两个。根据某些计时器,此信息会定期添加到顶点着色器中。只有块 feedback 被存储到 TBF 中(从上面的代码中删除了不相关的属性变量)。
这很好用,但问题是当我发出比缓冲区大小更多的顶点时。我预计在这种情况下不会再创建顶点,但似乎新创建的顶点会覆盖旧的顶点。
如何通过变换反馈存储额外发射的顶点?(我无法在任何规范中找到)。它似乎也以第一个粒子是唯一稳定的粒子而结束,所有其他粒子逐渐被推出缓冲区并被第一个粒子创建的粒子所取代。
在最终的程序中,我希望能够从管道中删除顶点并根据一些时间变量等添加新顶点 - 所以我没有任何指定的缓冲区数据结构。
有没有办法防止覆盖?我需要在缓冲区已满的情况下实际上不创建新粒子,并且仅当从缓冲区中删除(=未发射)粒子时 - 新粒子可以被创建。这是标准行为吗?
注意: 在 GeForce GT 630M 和 GeForce GTX 260 (Windows 7 x64) 上试用。
【问题讨论】:
-
我不确定这是否回答了您的问题,但根据opengl.org/wiki/Transform_Feedback“如果您的绑定缓冲区范围不足以容纳记录的数据,则会导致未定义的行为。”
-
谢谢,这很有帮助。