Hi
while playing a little bit with point sprites I found a simple way to texture points using vertex and fragment programs (should be interesting especially for the Radeon people without a point sprite extension )
I thought somebody might find it useful, so here it is:
Actually the vertex program calculates the points distance attenuation and the window space position of the lower left corner of the point. Then this value is passed to the fragment program. With the fragment position and the lower left corners position its quite simple to get the texture coordinate and to sample the texture.
vertex program setup:
GLfloat viewport[4];
GLfloat viewport_scale[4] = {0.0f,0.0f,0.0f,0.0f};
GLfloat viewport_offset[4]= {0.0f,0.0f,0.0f,0.0f};glGetFloatv(GL_VIEWPORT,viewport);
viewport_scale[0] = viewport[2] / 2.0f;
viewport_scale[1] = viewport[3] / 2.0f;viewport_offset[0] = viewport[0] + viewport[2] / 2.0f;
viewport_offset[1] = viewport[1] + viewport[3] / 2.0f;
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB,0,viewport_scale);
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB,1,viewport_offset);
the vertex program
!!ARBvp1.0
ATTRIB pos = vertex.position;PARAM mvp[4] = { state.matrix.mvp } ;
PARAM mv[4] = { state.matrix.modelview } ;
PARAM pSize = state.point.size;
PARAM pAtt = state.point.attenuation;PARAM vp_scale = program.local[0];
PARAM vp_offset= program.local[1];
PARAM eye= { 0.0, 0.0, 0.0, 1.0};
TEMP dist;
TEMP dist_sqr;
TEMP transformed;
TEMP finalsize;MOV finalsize,{ 0,0,0,0 };
vertex in eye space
DP4 transformed.x, mv[0], pos;
DP4 transformed.y, mv[1], pos;
DP4 transformed.z, mv[2], pos;
DP4 transformed.w, mv[3], pos;distance to eye ( 0,0,0,1)
SUB dist_sqr, transformed, eye;
DP3 dist_sqr, dist_sqr, dist_sqr;
RSQ dist, dist_sqr.w;
RCP dist, dist.w;calc attenuation
pointsize = size * sqrt( 1/ ( a+ bd + cd^2))
MAD finalsize, pAtt.y, dist, pAtt.x;
MAD finalsize, pAtt.z, dist_sqr, finalsize;
RSQ finalsize.w, finalsize.w;
MUL finalsize.w,pSize.x, finalsize.w;
clamp and out
MAX finalsize.w, pSize.y,finalsize.w;
MIN finalsize.w,pSize.z,finalsize.w;
MOV result.pointsize, finalsize.w;
MOV result.color, vertex.color;
1 / pointsize for fp
RCP result.texcoord[1].x, finalsize.w;
project vertex
DP4 transformed.x, mvp[0], pos;
DP4 transformed.y, mvp[1], pos;
DP4 transformed.z, mvp[2], pos;
DP4 transformed.w, mvp[3], pos;
MOV result.position, transformed;homogenous divide
RCP transformed.w, transformed.w;
MUL transformed.xyz,transformed, transformed.w;viewport transformation
MAD transformed, transformed, vp_scale, vp_offset;
left bottom corner of point, offset center by {-pointsize/2,-pointsize/2}
MUL finalsize.w, finalsize.w, {0.5,0.5,0.5,0.5};
SUB result.texcoord, transformed,finalsize.w;
END
the fragment porgram
!!ARBfp1.0
ATTRIB point_origin = fragment.texcoord[0];
ATTRIB one_over_point_size = fragment.texcoord[1];
ATTRIB pos = fragment.position;TEMP texcoord;
dinstance to lower left corner
SUB texcoord, pos, point_origin;
normalize s,t texturcoordinates [0, pointsize] → [0,1]
MUL texcoord, texcoord,one_over_point_size.x;
1-texcoord.y , so results are the same as NV_point_sprite
SUB texcoord.y,{1.0,1.0,1.0,1.0},texcoord;
TEX result.color, texcoord, texture[0], 2D;
END
If you see ways to improve (apart from usage of less vp/fp temporaries…) or have other ideas, please feel free to tell
Bye
ScottManDeath