Particle effect positioned with a projectionmatrix

I have been learning opengl es from the opengl es 2.0 programming guide. They have a particle effect that looks like an explosion. I am trying to enhance their example code by adding a mat4 projection matrix to the vertex shader, the shader compiles and works, but I am having problems getting the effect to position taking the projection into account. The vertex shader code I have is as follows

const char* ParticleExplosionVertexShader = STRINGIFY (

uniform float u_time;
uniform vec3 u_centerPosition;
uniform mat4 Projection;
attribute float a_lifetime;
attribute vec3 a_startPosition;
attribute vec3 a_endPosition;
varying float v_lifetime;

void main()
{
if ( u_time <= a_lifetime )
{
gl_Position.xyz = a_startPosition + (u_time * a_endPosition);
gl_Position.xyz += u_centerPosition;
gl_Position.w = 1.0;
}
else
gl_Position = vec4( -1000, -1000, 0, 0 );
v_lifetime = 1.0 - ( u_time / a_lifetime );
v_lifetime = clamp ( v_lifetime, 0.0, 1.0 );
gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0;
}

);

I have tried this sort of thing to add in the projection matrix

gl_Position = Projection * vec4(a_startPosition + (u_time * a_endPosition), 1.0);
gl_Position += Projection * vec4(u_centerPosition, 1.0);
gl_Position.w = 1.0;

I haven’t been able to get it to work as I want it to, ie placing it into the scene correctly, it always just sits in the middle on the same plane.

Am I doing something obviously wrong? If someone could help or point me in the right direction that would be great as I have run out of ideas. I think the problem is that I just don’t get GLSL enough yet.

Please post back if you need any more information from me

Hi,
Let me brief you on what the vertex shader is defined for. The vertex shader is responsible for transforming the vertices to clip space. Usually the vertex positions are given in object space. These positions are multiplied by the modelview matrix to bring the vertex positions from object space to eye space and then the eye space positions are multiplied by the projection matrix to bring the positions into clip space.

Usually the modelview and projection matrices are passed in to the shader as a combined modelview projection matrix which directly brings the vertex positions from object space to clipspace.

For your case, you are directly multiplying the projection matrix to the object space vertex positions which will project the vertices probably at the origin at Z=0 plane going from -1 to 1 on X,Y Axes.

To get the correct positions, either

  1. pass in the modelview matrix along with the projection matrix and then multiply the positions first with the modelview matrix and then with the projection matrix. Something like this,

in vec3 a_startPosition, u_centerPosition;
uniform mat4 MV, //modelview matrix
             P;  //projection matrix

void main() {
   vec3 pos =  a_startPosition + (u_time * a_endPosition);
   gl_Position = P*(MV * vec4(pos + u_centerPosition, 1.0));
}

  1. directly pass in the combined modelview projection matrix from the CPU to the shader and then multiply the input vertices with it. Something along these lines should work.

in vec3 a_startPosition, u_centerPosition;
uniform mat4 MVP;  //combined modelview pojection matrix

void main() {
   vec3 pos =  a_startPosition + (u_time * a_endPosition);
   gl_Position = MVP * vec4(pos + u_centerPosition, 1.0);
}

A side note: Please use [ code][ /code] tags when pasting in code snippets.

I hope it is clear now. See if this helps.

Hi Mobeen

Thanks for the good answer, is definitely helps. You’ve explained object space, eye space, and clip space very well for me, which I had been meaning to read up on again.

It was behaving just as you described on the x and y axis.

Can I ask for a little more help please?

I have went with the first approach you described, though I think once I get it working I will change it to the second way you described.

const char* ParticleExplosionVertexShader = STRINGIFY (

uniform float u_time;
uniform vec3 u_centerPosition;
uniform mat4 Projection;
uniform mat4 Modelview;
attribute float a_lifetime;
attribute vec3 a_startPosition;
attribute vec3 a_endPosition;
varying float v_lifetime;

void main()
{
    if ( u_time <= a_lifetime )
    {   
        vec3 pos =  a_startPosition + (u_time * a_endPosition);
        gl_Position = Projection *(Modelview * vec4(pos + u_centerPosition, 1.0));
        gl_Position.w = 1.0;
    }
    else
        gl_Position = Projection * Modelview * vec4( -1000, -1000, 0, 0 );
    v_lifetime = 1.0 - ( u_time / a_lifetime );
    v_lifetime = clamp ( v_lifetime, 0.0, 1.0 );
    gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0;
}

);

The problem I have is it just seems to position in the centre of the screen, and rather than behaving like an explosion it seems to show as a circle and get smaller, rather than exploding in an outwards expanding direction as it was doing before. Is this likely to something I am doing here or with the values Im passing in? I could post more details if it would help

Thanks

Hi,
Could u show us how you are calculating the positions?

Hi

Yes I certainly can. I haven’t changed the code from the book very much yet as I wanted to get it working first. The below code is done during initialisation

// Fill in particle data array
    int i;
    srand ( 0 );
    for ( i = 0; i < NUM_PARTICLES; i++ )
    {
        float *particleData = &userData.particleData[i * PARTICLE_SIZE];
        
        // Lifetime of particle
        (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
        
        // End position of particle
        (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
        (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
        (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
        
        // Start position of particle
        (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
        (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
        (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
        
    }

Then later in the Render method if it helps I am setting u_centerPosition to 0, 0, 0

and I am settings the modelview by doing

mat4 translation = mat4::Translate(2, 2, -5);
    mat4 scale = mat4::Scale(1);
    mat4 modelViewMatrix = scale * translation;
    glUniformMatrix4fv(userData.Modelview, 1, 0, modelViewMatrix.Pointer());

Thanks for your help, please let me know if more details will be helpful

Hi,
I am not sure but is this formula correct?


vec3 pos =  a_startPosition + (u_time * a_endPosition);

shouldn’t it be


vec3 pos =  a_startPosition + (u_time * (a_endPosition-startPosition) );

I’m not to sure, but I will give it a try when I get home tonight I’ll post back to let you know how I get on

Thanks

Hi

I tried your suggestion, but unfortunately the behaviour didn’t change, and it still shows a circle that appears to get smaller until it disappears. It looks like the particles are moving in the wrong direction

If I change the code back to this then the explosion works fine

gl_Position.xyz = a_startPosition + (u_time * a_endPosition);
gl_Position.xyz += u_centerPosition;
gl_Position.w = 1.0;

when I change to this below it stops working and does the shrinking circle thing

vec3 pos =  a_startPosition + (u_time * a_endPosition);
gl_Position = Projection *(Modelview * vec4(pos + u_centerPosition, 1.0));
gl_Position.w = 1.0;

I have also tried this that I found at http://androgeek.info/?p=331

gl_Position.xyz = a_startPosition + (u_time * a_endPosition);
gl_Position=Projection *(Modelview * gl_Position);

But again it gives the circle that gets smaller rather than an explosion.

I didn’t get much time to look at it yesterday night, but will investigate it more tonight and report back

It might be worth mentioning that when I try to position it with setting the modelview, no matter what I change it to it is always in the centre (0,0) of the screen where it see the shrinking circle.

Would it suggest that since it always appears in the centre of the screen there is something wrong with my projection matrix or modelview matrix? If it is Im not sure what it could be because I am using them the same as I do when I render other objects such as squares and they look and position fine

Thanks

Yeah I think it has something to do with your matrix library. Could you try glm instead and see if you get the right result.

Thanks I will give it a try. The one I have been using is the one that is used in the example that come with the book iPhone 3D programming. Looks like there are quite a few more files in the glm one, so perhaps makes it better. I will try it out tonight

Thanks

Hi Mobeen

Thanks for all your help, I have got it working now, well late last night I did. I am a little short of time at the moment but will post up details of what I changed to get it working. I am using glm, but Im not sure if that was the fix or if I changed something else, I will do further testing and post back what fixed it later tonight. I like the glm library so think I am gonna upgrade my project to use it throughout

Thanks again

Hi

I just wanted to post back to the forum with what it was that fixed the bug I was having, incase someone comes across a similar issue. It appears that it wasn’t the math library, and it was because I wasn’t setting the projection matrix on each render loop, I’m not really sure why its required to set it on each render loop, but it works, and I like it. Probably gonna stick with the glm library too anyway as it looks good.

Cheers

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.