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);