Hi all,
I have a Geometry shader that runs fine with Nvidia/Ati cards, but in Intel (integrated Iris Xe from an i5-11th Gen) it just does not draw anything… no errors are thrown as well, no emitters (particles) are being generated, is like the shader does not compile, but without throwing errors.
I have skipped many non-relevant parts of the shader, but basically it draws a “kind of” Lorenz attractor, the Geometry shader is the following one:
void main()
{
float Age = gs_in[0].Age + u_fDeltaTime; // Increment the age of the particle
vec3 DeltaV = u_v3Force * u_fDeltaTime; // vDelta = accel*tDetla
if (gs_in[0].Type == PARTICLE_TYPE_EMITTER) {
// If it's time to create a new particle shell...
if (Age >= u_fEmissionTime) {
o_Type = PARTICLE_TYPE_SHELL;
o_Position = u_fRamndomness*gs_in[0].Position;//GetRandomDir(gs_in[0].Position.x);//gs_in[0].Position;
o_Velocity = gs_in[0].Velocity;
o_Color = u_v3Color; //Apply the global color
//o_Color = gs_in[0].Color; //Apply the same color as the emitter
o_Age = 0.0;
EmitVertex();
EndPrimitive(); // Generate a new particle from the launcher position
Age = 0.0; // Set the age of the emitter to 0, so it can generate new particles later
}
// Draw the Emitter
o_Type = PARTICLE_TYPE_EMITTER;
o_Position = gs_in[0].Position;
o_Velocity = gs_in[0].Velocity;
o_Color = vec3(0,0,0); // Apply the global Color
o_Age = Age;
EmitVertex();
EndPrimitive(); // Generate the emitter
}
// If its a normal particle...
if (gs_in[0].Type == PARTICLE_TYPE_SHELL) {
// If the is still alive, we update the values...
if (Age < u_fParticleLifetime) {
// >>>>>>>> THIS IS THE PROBLEMATIC CODE
// Calculate position of the new particle
float x,y,z,dx,dy,dz,dx2,dy2,dz2;
vec3 attractorForce;
// Previous positions
x = gs_in[0].Position.x;
y = gs_in[0].Position.y;
z = gs_in[0].Position.z;
// Lorenz
dx = (a * (y - x)) * u_fDeltaTime;
dy = (x * (b-z) - y) * u_fDeltaTime;
dz = (x*y - c*z) * u_fDeltaTime;
// Lorenz 2
dx2 = (y- a2*x +b2*y*z) * u_fDeltaTime;
dy2 = (c2*y -x*z +z) * u_fDeltaTime;
dz2 = (d2*x*y - e2*z) * u_fDeltaTime;
// Add the new increments to the previous position
attractorForce = vec3(dx, dy, dz);
//attractorForce = vec3(dx2, dy2, dz2);
attractorForce = mix(vec3(dx, dy, dz), vec3(dx2, dy2, dz2), influence);
// >>>>>>>> END OF THE PROBLEMATIC CODE
o_Type = PARTICLE_TYPE_SHELL;
o_Position = gs_in[0].Position + attractorForce;
o_Velocity = gs_in[0].Velocity;
o_Color = gs_in[0].Color;
o_Age = Age;
EmitVertex();
EndPrimitive(); // Update the particle status and position
}
}
}
After some tests, I have seen that the shader can be fixed by moving out of the conditional if’s all the computations of the new particle position, so the fixed code (meaning, it is properly displayed on Intel cards) is:
void main()
{
float Age = gs_in[0].Age + u_fDeltaTime; // Increment the age of the particle
vec3 DeltaV = u_v3Force * u_fDeltaTime; // vDelta = accel*tDetla
if (gs_in[0].Type == PARTICLE_TYPE_EMITTER) {
// If it's time to create a new particle shell...
if (Age >= u_fEmissionTime) {
o_Type = PARTICLE_TYPE_SHELL;
o_Position = u_fRamndomness*gs_in[0].Position;//GetRandomDir(gs_in[0].Position.x);//gs_in[0].Position;
o_Velocity = gs_in[0].Velocity;
o_Color = u_v3Color; //Apply the global color
//o_Color = gs_in[0].Color; //Apply the same color as the emitter
o_Age = 0.0;
EmitVertex();
EndPrimitive(); // Generate a new particle from the launcher position
Age = 0.0; // Set the age of the emitter to 0, so it can generate new particles later
}
// Draw the Emitter
o_Type = PARTICLE_TYPE_EMITTER;
o_Position = gs_in[0].Position;
o_Velocity = gs_in[0].Velocity;
o_Color = vec3(0,0,0); // Apply the global Color
o_Age = Age;
EmitVertex();
EndPrimitive(); // Generate the emitter
}
// >>>>>>>> THIS IS THE PROBLEMATIC CODE
// Calculate position of the new particle
float x,y,z,dx,dy,dz,dx2,dy2,dz2;
vec3 attractorForce;
// Previous positions
x = gs_in[0].Position.x;
y = gs_in[0].Position.y;
z = gs_in[0].Position.z;
// Lorenz
dx = (a * (y - x)) * u_fDeltaTime;
dy = (x * (b-z) - y) * u_fDeltaTime;
dz = (x*y - c*z) * u_fDeltaTime;
// Lorenz 2
dx2 = (y- a2*x +b2*y*z) * u_fDeltaTime;
dy2 = (c2*y -x*z +z) * u_fDeltaTime;
dz2 = (d2*x*y - e2*z) * u_fDeltaTime;
// Add the new increments to the previous position
attractorForce = vec3(dx, dy, dz);
//attractorForce = vec3(dx2, dy2, dz2);
attractorForce = mix(vec3(dx, dy, dz), vec3(dx2, dy2, dz2), influence);
// >>>>>>>> END OF THE PROBLEMATIC CODE
// If its a normal particle...
if (gs_in[0].Type == PARTICLE_TYPE_SHELL) {
// If the is still alive, we update the values...
if (Age < u_fParticleLifetime) {
o_Type = PARTICLE_TYPE_SHELL;
o_Position = gs_in[0].Position + attractorForce;
o_Velocity = gs_in[0].Velocity;
o_Color = gs_in[0].Color;
o_Age = Age;
EmitVertex();
EndPrimitive(); // Update the particle status and position
}
}
}
Can anybody explain me why this limitations on intel cards? I have tested on an old Intel 620 graphics card and it shows the same behaviour.
They way I solved is OK? or is there any more “elegant/professional” way to solve this issues on Intel cards?
Thanks!!!