views:

2466

answers:

2

I was trying to set point sprites in OpenGL to change size with distance just as a billboarded sprite would, but I can't get the values in GL_POINT_DISTANCE_ATTENUATION_ARB to do anything useful. Is there a correlation of values to this that would match a given projection? Is what I'm trying to do even possible?

Render code being used:

    glPointParameterfARB  = (PFNGLPOINTPARAMETERFARBPROC)wglGetProcAddress("glPointParameterfARB");
    glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)wglGetProcAddress("glPointParameterfvARB");

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluPerspective(100.0, 800.0/600.0, 0.1, 10.0);

float quadratic[] =  { 5.0f, 0.1f, 10.0f };
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );

float maxSize = 0.0f;
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
if( maxSize > 100.0f )  maxSize = 100.0f;
glPointSize( maxSize );

glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 0.1f );
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.1f );
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );

glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );

glEnable( GL_POINT_SPRITE_ARB );

glScalef(0.75,1,1);
glTranslatef(0.00,0.0,-1.0);
glScalef(0.5,0.5,0.5);
glRotatef(counter*0.1+0.5,1.0,1.0,0.0);

glBegin( GL_POINTS );

    for( int i = 0; i < 100; ++i )
    {
        glColor4f( i%10*0.1, i/10*0.1, 0.5, 1.0f );

        glVertex3f( i%10*0.2-1.0,i/10*0.2-1.0,
            ((i%10-5)*(i%10-5)+(i/10-5)*(i/10-5))*0.01 );
    }

glEnd();

glDisable( GL_POINT_SPRITE_ARB );
+1  A: 

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.

shoosh
+3  A: 

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.

Eric