Преобразование обратной связи работает только первый кадр
Преобразование обратной связи работает с первым кадром, но не после этого.
Это система частиц, основанная на примере "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;
Vertex Shader для преобразования шейдеров обратной связи (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.