Is it possible to use OpenGL point sprites to simulate billboard sprites?
Here's how I make my poor man's approach to scaling the point size:
void render() {
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable(GL_POINT_SPRITE);
glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
/* Activate shader program here */
/* Send pointSize to shader program */
glBegin(GL_POINTS);
/* Render points here */
glVertex3f(...);
glEnd(GL_POINTS);
}
Vertex shader:
uniform float pointSize;
void main() {
gl_Position = ftransform();
gl_PointSize = pointSize / gl_Position.w;
}
You can do whatever you want in the fragment shader, but you'll have to compute the color, lighting and texturing yourself.
GLSL aside, doing what you want is pretty simple with distance attenuation. Seeing as how the projected size of things decreases quadratically with their distance in perspective projections, you only need to use the quadratic factor.
If you want to use the point size you manually set at a distance of, say, 150 units from the eye, just use 1/(150^2) as the quadratic factor (and zero for the constant and linear factors -- if anything, you may want to use some small number like 0.01 for the constant factor just to avoid potential divisions by zero).
In my experience point size attenuation isn't worth the trouble. You're much better off writing a very simple GLSL vertex shader that sets the point size manually according to some calculation you perform on your own. It took me about half a day to learn from scratch all the GLSL I needed to make this happen.
The GLSL code may be as simple as these few lines:
attribute float psize;
void main()
{
gl_FrontColor = gl_Color;
gl_PointSize = psize;
gl_Position = ftransform();
}
Where psize
is the point size parameter the user chooses.