# Stripping unnecessary data from C++ data structures before sending to GPU

I've recently been working on a particle system in my renderer and I've encountered a situation where my particle class on the C++ side has data I need to maintain my particle on that end, but that I don't need in my shader (velocity, acceleration, life span, start colour, end colour, gravity toggle, etc.).

So presently I've created a second class that just contains my necessary rendering data and I have a function that will copy the needed data from my "full" particle to my "rendering" particle.

class HParticle {
public:
vec3 m_pos = vec3(0, 0, 0);
float m_life = 0; // Remaining life of the particle. if < 0 : dead and unused.
vec4 m_color = vec4(1, 1, 1, 1); // Color
float m_texture = -1;
float m_scale = 1;
vec3 m_orientation;
float m_featureValue = 0;
float m_featureSelected = 0;
float m_emission = 0;
float m_scaleRate = 0;
vec4 m_startColor = vec4(1, 1, 1, 1);
vec4 m_endColor = vec4(1, 1, 1, 1);
vec3 m_velocity = vec3(0, 0, 0);
vec3 m_acceleration = vec3(0, 0, 0);
float m_featureValueRateOfChange = 0;
float m_totalLife = 0;
float m_colorLife = 0;
}

struct HStrippedParticle {
mat4 m_transform;
vec4 m_color = vec4(1, 1, 1, 1); // Color
float m_texture = -1;
float m_featureValue = 0;
float m_featureSelected = 0;
float m_emission = 0;
};


I know I'm speaking specifically to particles here but I've encountered this situation a couple of times before and I'm wondering if there's a better general approach than maintaining two lists. One for C++ and one for my shader. And having to update the shader one every time I go to render (I know I could be cleverer and avoid updating data that hasn't changed but still). Maybe something fancy with C++ memory to copy desired chunks from the full class to the stripped class?

• You would think the shaderwiter would be happy to have all the data? But yeah two lists should work Sep 11 at 18:55

I typically like to define a "GPUData" struct containing the fields that are going to the shader, and keep the GPUDatas for all the particles in an array. Then, when it's time to update the GPU buffer, you can just memcpy out of that array to your mapped buffer (or you can pass the array to glBufferSubData, etc).

For the CPU state, rather than duplicating the fields that are already in the GPUData, you can just keep the non-GPU fields there. Then your particle simulation code just reads and write the GPUData fields directly.

Pseudocode example:

struct ParticleGPUData
{
mat4 m_transform;
vec4 m_color;
// ...
};
std::vector<ParticleGPUData> particleGPUData;

struct ParticleCPUData
{
float m_life;
vec3 m_velocity;
vec3 m_acceleration;
// ...
};
std::vector<ParticleCPUData> particleCPUData;

for (int i = 0; i < countParticles; ++i)
{
ParticleCPUData* cpuData = &particleCPUData[i];
ParticleGPUData* gpuData = &particleGPUData[i];

// update the particle...
cpuData->m_velocity += cpuData->m_acceleration * dT;
gpuData->m_color = CalculateColor(cpuData);
// ... etc.
}

// When you go to update the buffer to render
glBufferSubData(