101 Things to do in Vertex Shader :)

Ok, here’s my best attempt at it. In order to get a vertex program to do billboarding, it needs to get a quad of the appropriate size and the position of the center of the quad.

Before it got the center coordinates from a glTranslate(). If, instead, you want to send the center position as part of the vertex data, you can use color (or whatever). Here is the slightly modified vertex program that will do billboarding if the center of the billboard is given as the color.

    
    "!!VP1.0"
 
    // Apply inverse modelview rotation to all vertices
    "DP3 R0.x, v[OPOS], c[0];"
    "DP3 R0.y, v[OPOS], c[1];"
    "DP3 R0.z, v[OPOS], c[2];"
    "MOV R0.w, v[OPOS];"
 
    // Use color as transformation
    "ADD R0, R0, v[COL0];"
 
    // Transform vertices into clip space via modelview-projection matrix
    "DP4 o[HPOS].x, R0, c[4];"
    "DP4 o[HPOS].y, R0, c[5];"
    "DP4 o[HPOS].z, R0, c[6];"
    "DP4 o[HPOS].w, R0, c[7];"
 
    // Send the color through unchanged
    "MOV o[COL0], v[COL0];"
 
    // End Vertex program
    "END"

This way, if you pack the position of your particles into a color array and the quads into another, you can do billboarded particles without having the CPU touch each one.

I think that one could gain a lot of speed (or at least free up a lot of CPU cycles) by using this method.

Thoughts?

– Zeno

great work zeno!

but can’t you set-up OpenGl/DX to pass arbitrary data to the vertex shader?

It would be nice to keep the colour info - for instance if you need it for colouring your billboard clouds dependant of position in sky,sun position, cloud thinkness etc etc.

You can pass upto 16 vectors per vertex (registers v0 to v15)- I beleive it’s just a matter of using glVertexAttrib*** to set it up, under OpenGl of course

Rob J.

16 vectors per vertex?

Negatory. 16 input registers, in vector format. These aren’t restricted to a single vertex array. These 16 registers can hold incoming vertex data from multiple streams, essential for keyframe lerps and such.

OGL/DX can’t pass arbitrary data to a shader (unless you set up some noise algo to generate an array of vertex data). As per the spec, a vertex shader can’t create or destroy any vertices. FIFO.

And, relating to Zeno’s post, I’d make use of a couple of the 96 constant registers to pass any additional information to the shader, that couln’t be encoded in the input registers. They are pretty handy for holding any kind of data, not just tracking matrices.

Glossifah

Glossifah -

As I understand it, you get 16 vertex attribute registers, each one is a 4-component vector.

Each vertex is passed through the vertex shader in turn with all of the regular per-vertex info. In addition I thought it was possible to specify extra per-vertex data to pass along with vertex coords, normal, colour etc ?? You can stick whatever you want in that extra data ???

Rob.

Rob,

From the nVidia Vertex Shaders document found here:
Vertex Shaders Intro

These float-vectors represent a combination of positional data
(xyzw), texture coordinates (uvwq), colors (rgba), or simply a collection of four scalars
(abcd).

So, as long as you let the shader know that those registers contain data, you can place whatever you like in there. That information, in turn, could be used to build the billboarded particle.

The
application declares to a vertex shader which per-vertex registers are available and of
what type these data are. Thus, the runtime generates an error if a vertex shader refers to
an undeclared per-vertex vector-register.

To my original post, I’d stick with putting whatever additional description of the particle in the constant registers.

Regards,

Glossifah

Rob -

Yea, I could/should have used a glVertexAttrib() instead of color, but then I’d have to go and get the function pointer…way too much work .

Glossifah -

I don’t think it’s a good idea to change the constant registers for each particle just to send the coords of the particle’s center (which is all the info you need to billboard). It would require you to make 1 extra function call per particle and you couldn’t use vertex arrays like you can if you just send the center as a vertex attribute. This is all assuming that glProgramParameterNV is really fast. Otherwise, it’ll be worse.

– Zeno

– Zeno

So now you’re sending twice as much data to the graphics card; for each vertex, both a center and a delta. This means that for each billboard, you have to write four copies of the “center” data into the vertex array. Granted, writing four copies of the same data uses less calculation on the host CPU than writing four different copies based on the center data, but the transfer overhead to the card may (or may not) mask that. Writing to memory is much more expensive than multiplying/adding.

Now, if your CPU is about as fast as molasses, using this multi-stream vertex shader will be faster than doing it the old-fashioned way. It still doesn’t appear to do correct perspective, though. I’d be interested in seeing actual performance measurements going one way or the other.

You’re right, it does double the amount of info you send to the card, but ONLY if you have the most general possible case of billboards.

If any of the following are true:

A) You don’t move your billboards (i.e. center position doesn’t change)
B) You don’t resize your billboards
C) You neither move nor resize your billboards

Then can’t you use either lock arrays (in the case of A or B) or display lists ( in the case of C) to send either the same or less, respectively, data over the bus than you would have to by doing everything on the CPU?

disclaimer: I haven’t yet used lock arrays / cva’s, so I might not know what I’m talking about there.

– Zeno

P.S. Another thing I just thought of: As far as vertices, you might only need to store ONE QUAD and an array of centers. Send this over and over (or keep it on the card somehow) for every one of your particles/billboards. You’ve even got an “extra” fourth slot free, so along with center position you could send a particle radius to the graphics card each frame, without having to do another glVertexAttrib() call . That way the billboards could have different sizes and positions while reusing the same 4 quad vertices.

[This message has been edited by Zeno (edited 05-30-2001).]