Pass/use additional data VBO in shader

Hi.

I am using a vertex shader and a pixel shader to draw an array of points to appear as spheres. Each point should have a different color and a different radius. Right now I have this working but have to set the radius of each sphere with the following call


int prloc = gl.GetAttribLocationARB((int)m_program, "pointRadius");
gl.VertexAttrib2fARB(prloc, (float)0.5f, 0.0f);

I am now trying to get this to work using Vertex Buffer Objects (VBO). I am able to pass the vertex locations of each point and the color of each point with VBOs but have not been able to figure out how to pass a unique radius for each point. I tried passing the radius as the w coordinate of the vertex but this causes a run time error. Is there another buffer that could be passed to the shader that I could populate a radius in? Any other suggestions or references on how to do this would be appreciated.

Regards,

Andrew

The code for the shaders I am using are as follows:


        // vertex shader
        string vertexShader =
            @"attribute vec2 pointRadius;  // point size in world space
uniform float pointScale;   // scale to calculate size in pixels
uniform float densityScale;
uniform float densityOffset;
void main()
{
    // calculate window-space point size
    vec3 posEye = vec3(gl_ModelViewMatrix * vec4(gl_Vertex.xyz, 1.0));
    float dist = length(posEye);
    gl_PointSize = pointRadius.x * (pointScale / dist);
 //   gl_PointSize = gl_Vertex.w * (pointScale / dist); // This did not work
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0);

    gl_FrontColor = gl_Color;
}";

        // pixel shader for rendering points as shaded spheres
        string spherePixelShader =
        @"void main()
{
    const vec3 lightDir = vec3(0.577, 0.577, 0.577);

    // calculate normal from texture coordinates
    vec3 N;
    N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
    float mag = dot(N.xy, N.xy);
    if (mag > 1.0) discard;   // kill pixels outside circle
    N.z = sqrt(1.0-mag);

    // calculate lighting
    float diffuse = max(0.0, dot(lightDir, N));

    gl_FragColor = gl_Color * diffuse;
}";
    }

and the code to draw the points/spheres using VBO´s



            // Bind the arry for the vertices
            gl.BindBufferARB(gl.ARRAY_BUFFER_ARB, buffers[0]);
            gl.EnableClientState(gl.VERTEX_ARRAY);
            gl.VertexPointer(4, gl.FLOAT, 0, 0);

            // Bind the array for the colors
            gl.BindBufferARB(gl.ARRAY_BUFFER_ARB, buffers[1]);
            gl.EnableClientState(gl.COLOR_ARRAY);
            gl.ColorPointer(4, gl.FLOAT, 0, 0);

            // Shader program
            gl.Enable(gl.POINT_SPRITE_ARB);
            gl.TexEnvi(gl.POINT_SPRITE_ARB, gl.COORD_REPLACE_ARB, gl.TRUE);
            gl.Enable(gl.VERTEX_PROGRAM_POINT_SIZE_NV);
            gl.DepthMask(true);
            gl.Enable(gl.DEPTH_TEST);

            // set particle radius // This is what I would like to move into the shader so each point has its own radius!
            int prloc = gl.GetAttribLocationARB((int)m_program, "pointRadius");
            gl.VertexAttrib2fARB(prloc, (float)0.5f, 0.0f);

            gl.UseProgram(m_program);

            gl.DrawArrays(gl.POINTS, 0, numpoints);     
       
            // End shader program
            gl.UseProgram(0);
            gl.Disable(gl.POINT_SPRITE_ARB);

            // Release the VBO
            gl.BindBufferARB(gl.ARRAY_BUFFER_ARB, 0);
            gl.DisableClientState(gl.VERTEX_ARRAY);
            gl.DisableClientState(gl.COLOR_ARRAY);

There are two way: look into gl_MultiTexCoord[] or do the right thing: stop using the built in (i.e. fixed function pipeline) attributes and make your own.

Made some progress.

I have changed
attribute vec2 pointRadius;
to
attirbute float pointRadius;

in the shader and added the following code before the gl.DrawArrays()


            // Bind the array for the radius
            int radiusLocation = gl.GetAttribLocationARB((int)m_program, "pointRadius");
            gl.BindBufferARB(radiusLocation, buffers[2]);
            gl.VertexAttribPointerARB(radiusLocation, 1, gl.FLOAT, false, 0, (IntPtr)0); // the last 0 is an offset?
            gl.EnableVertexAttribArrayARB(radiusLocation);

This sorta/kinda works. It compiles, runs, but draws points of all kinds of intersting sizes. I think the last argument, (IntPtr)0, in the call to VertexAttribPointerARB is incorrect.

When using VBO arrays what pointer do I use here and how do I get it?

Would you also stop using the Color built in attribute?

Appreciate any help.

Andrew

The guilty call is this:


gl.BindBufferARB(radiusLocation, buffers[2]);

it should be:


gl.BindBufferARB(GL_ARRAY_BUFFER, buffers[2]);

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