转换反馈在第一帧起作用,但在那之后就不行了。
这是基于“GLSL Cookbook”示例的粒子系统,尽管我将其转换为 OpenGL 3.3。
我的程序设置:
对于每个属性,我有两组顶点数组缓冲区(2 个用于位置,2 个用于速度,2 个用于 startTime)。2个VAO,第一个对应第一组缓存,第二个VAO对应第二组缓存。VAO 为相应的缓冲区设置顶点属性。
有两个着色器程序,第一个执行变换反馈,第二个渲染。
在每一帧上,首先使用变换反馈着色器程序和 VAO 执行变换反馈,然后使用其他 VAO 渲染渲染着色器。在每个连续的帧上,VAO 被交换。
如果我使用查询,GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
我可以看到只有第一次写入所有原语,之后写入的原语值为0
. 我还可以通过看到屏幕上的点闪烁(在点的起始位置和它们在第一帧中变换的位置之间闪烁)来直观地看到第一遍的工作。
我只在 Mac OS X 上看到这个问题(它在 Linux 和 Windows 上完美运行)。我知道 Mac 在某些 OpenGL 功能方面有点落后,但我找不到任何表明在这种情况下会出现问题的东西。
此外,我在渲染时检查了 OpenGL 错误,但没有。
在链接变换反馈着色器之前:
const char * outputNames[] = { "position", "velocity", "startTime" };
glTransformFeedbackVaryings(
m_transformShader.programId(),
3,
outputNames,
GL_SEPARATE_ATTRIBS);
这是我正在使用的渲染功能代码:
// ************** Transform feedback pass
m_transformShader.bind();
glEnable(GL_RASTERIZER_DISCARD);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, positionBuffer[drawBuf]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, velocityBuffer[drawBuf]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, startTimeBuffer[drawBuf]);
m_vao[1-m_drawBuf].bind();
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, numParticles);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);
// ************** Render pass
m_renderShader.bind();
glClear( GL_COLOR_BUFFER_BIT );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
m_renderShader.setUniformValue("texSampler", 0);
m_vao[m_drawBuf].bind();
glDrawArrays(GL_POINTS, 0, numParticles);
m_vao[m_drawBuf].release();
m_renderShader.release();
m_drawBuf = 1 - m_drawBuf;
变换反馈着色器的顶点着色器 ( m_transformShader
):
#version 330
layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec3 vertexVelocity;
layout (location = 2) in float vertexStartTime;
layout (location = 3) in vec3 vertexInitialVelocity;
out vec3 position;
out vec3 velocity;
out float startTime;
uniform float time;
uniform float H;
uniform vec3 accel;
uniform float lifespan;
void main()
{
position = vertexPosition;
velocity = vertexVelocity;
startTime = vertexStartTime;
if ( time >= startTime )
{
float age = time - startTime;
if ( age > lifespan )
{
position = vec3(0.0);
velocity = vertexInitialVelocity;
startTime = time;
}
else
{
position += velocity * H;
velocity += accel * H;
}
}
}
渲染顶点着色器:
#version 330
layout (location = 0) in vec3 vPosition;
layout (location = 2) in float vStartTime;
out float alpha;
uniform mat4 MVP;
uniform float time;
uniform float lifespan;
void main()
{
gl_PointSize = 10.0;
float age = time - vStartTime;
alpha = 1.0 - age / lifespan;
gl_Position = MVP * vec4(vPosition, 1.0);
}
我正在使用 OpenGL 3.3 上下文。