トランスフォーム フィードバックは最初のフレームでは機能しますが、それ以降は機能しません。
これは「GLSL Cookbook」の例に基づいたパーティクル システムですが、OpenGL 3.3 に変換しています。
私のプログラムのセットアップ:
アトリビュートごとに 2 セットの頂点配列バッファーがあります (位置用に 2 つ、速度用に 2 つ、開始時間用に 2 つ)。2 つの VAO、最初の設定バッファーに対応する最初の VAO、およびバッファーの 2 番目のセットに対応する 2 番目の VAO。VAO は、頂点属性を対応するバッファーに設定します。
2 つのシェーダー プログラムがあり、1 つ目は変換フィードバックを実行し、2 つ目はレンダリングを実行します。
各フレームで、最初に変換フィードバック シェーダー プログラムと 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 コンテキストを使用しています。