Hmm… just to understand where exactly I am going wrong, I had added a new varying and used two independent attributes to store the color values related to the two different images. I will post the chunks from the current state of the code to pin point the problem (Apologies in advance for the length of the content dump)
So, the local particle construct looks like this:
struct Particle
{
vec3 pos;
vec3 ppos;
vec3 home;
vec3 base;
ColorA color;
ColorA colorActive;
ColorA colorInactive;
float damping;
};
The particles and shader initializaton function:
// Mark as static since we only write from the CPU once.
mParticleBuffer[mSourceIndex] = gl::Vbo::create(GL_ARRAY_BUFFER, mParticles.size() * sizeof(Particle), mParticles.data(), GL_STATIC_DRAW);
mParticleBuffer[mDestinationIndex] = gl::Vbo::create(GL_ARRAY_BUFFER, mParticles.size() * sizeof(Particle), nullptr, GL_STATIC_DRAW);
for (int i = 0; i < 2; ++i)
{
// Describe the particle layout for OpenGL.
mAttributes[i] = gl::Vao::create();
gl::ScopedVao vao(mAttributes[i]);
// Define attributes as offsets into the bound particle buffer
gl::ScopedBuffer buffer(mParticleBuffer[i]);
gl::enableVertexAttribArray(0);
gl::enableVertexAttribArray(1);
gl::enableVertexAttribArray(2);
gl::enableVertexAttribArray(3);
gl::enableVertexAttribArray(4);
gl::enableVertexAttribArray(5);
gl::enableVertexAttribArray(6);
gl::enableVertexAttribArray(7);
gl::vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, pos));
gl::vertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, colorActive));
gl::vertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, colorInactive));
gl::vertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, ppos));
gl::vertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, home));
gl::vertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, base));
gl::vertexAttribPointer(6, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, damping));
gl::vertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)offsetof(Particle, color));
}
// Load our update program.
// Match up our attribute locations with the description we gave.
mRenderProg = gl::getStockShader(gl::ShaderDef().color());
mUpdateProg = gl::GlslProg::create(gl::GlslProg::Format().vertex(loadAsset("particleUpdate.vs"))
.feedbackFormat(GL_INTERLEAVED_ATTRIBS)
.feedbackVaryings({ "position", "pposition", "home", "base", "colorActive", "colorInactive", "color", "damping" })
.attribLocation("iPosition", 0)
.attribLocation("iColor", 1)
.attribLocation("iOColor", 2)
.attribLocation("iPPosition", 3)
.attribLocation("iHome", 4)
.attribLocation("iBase", 5)
.attribLocation("iDamping", 6)
.attribLocation("iCurrColor", 7)
);
The update function:
// Update particles on the GPU
gl::ScopedGlslProg prog(mUpdateProg);
gl::ScopedState rasterizer(GL_RASTERIZER_DISCARD, true); // turn off fragment stage
mUpdateProg->uniform("uActive", activeFlag);
// Bind the source data (Attributes refer to specific buffers).
gl::ScopedVao source(mAttributes[mSourceIndex]);
// Bind destination as buffer base.
gl::bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mParticleBuffer[mDestinationIndex]);
gl::beginTransformFeedback(GL_POINTS);
// Draw source into destination, performing our vertex transformations.
gl::drawArrays(GL_POINTS, 0, mNumParticles);
gl::endTransformFeedback();
// Swap source and destination for next loop
std::swap(mSourceIndex, mDestinationIndex);
The draw function:
gl::ScopedGlslProg render(mRenderProg);
gl::ScopedVao vao(mAttributes[mSourceIndex]);
gl::context()->setDefaultShaderVars();
gl::drawArrays(GL_POINTS, 0, mNumParticles);
The external .vs
chunk:
#version 150 core
uniform float uActive;
in vec3 iPosition;
in vec3 iPPostion;
in vec3 iHome;
in vec3 iBase;
in float iDamping;
in vec4 iColor;
in vec4 iOColor;
in vec4 iCurrColor;
in vec4 ciColor;
out vec3 position;
out vec3 pposition;
out vec3 home;
out vec3 base;
out float damping;
out vec4 color;
out vec4 colorInactive;
out vec4 colorActive;
const float dt2 = 1.0 / (60.0 * 60.0);
const float force = 100.0;
void main()
{
position = iPosition;
pposition = iPPostion;
damping = iDamping;
home = iHome;
base = iBase;
colorInactive = iOColor;
colorActive = iColor;
color = iCurrColor;
if(uActive > 0.0)
{
vec3 dir = base - position;
float d2 = length( dir );
d2 *= d2;
float currForce = d2 < 20 ? 0 : (d2 < 40 ? force/8.0 : (d2 < 75 ? force/4.0 : (d2 < 120 ? force/2.0 : force )));
position += currForce * dir / d2;
vec3 vel = (position - pposition) * damping;
pposition = position;
vec3 acc = (base - position) * 32.0f;
position += vel + acc * dt2;
}
else
{
vec3 vel = (position - pposition) * (damping + 0.05f);
pposition = position;
vec3 acc = (home - position) * 32.0f;
position += vel + acc * dt2;
}
color = vec4(((length(position - home)*(colorInactive.r - colorActive.r)/length(base - home)) + colorActive.r), ((length(position - home)*(colorInactive.g - colorActive.g)/length(base - home)) + colorActive.g), ((length(position - home)*(colorInactive.b - colorActive.b)/length(base - home)) + colorActive.b), 1);
}
The strange thing is that it does set the color to a mixed one (somewhere midway between the two color values) during the initial animation but then the color simply stays the same no matter where the particles are moving, which results in a hybrid of the two images which I am trying to display.