vp performance

Hello,

do vertex programs and per pixel lightnig using NV register combiners cost any additonal performance compared to standard OpenGL vertex lighting? If rendering in a single pass? Are triangles drawn in a “simple” mode faster drawn than triangles that use register combiners and vertex programs, or is the hardware (GF 4/5) able to do this “on the fly” without additonal costs?

Thanks
Jan

Vertex programs are usually for free, since the chips are very fast.

And i think you get the register combiners for free, as long as you only use 2 combiner stages. If you use 3 or 4, that´s a BIG slowdown (but for PPL you don´t need that much).

However i am not so sure, if you really get the first 2 reg. combiner stages for free, so, if that´s not the case, than it´s a lot slower than vertex-lighting.

Additionally to that, for per-pixel lighting you need more textures (for the attentuation and maybe bumpmapping, etc), and that will slow you down even more.

I think in general it´s save to say, that vertex-lighting is much faster than PPL.

Jan.

do you know a good tutorial about register combiners (a tutorial that is step-by-step and understandable)? I managed bump mapping with ARB extensions, now would like to go on to register combiners but again do not find any really good tutorial (concerning the ARB extension, the one from paul’s projects finally helped me, really good ).

and what about GL_TEXTURE_SHADER_NV? another way to do ppl/bump mapping? I guess this is outdated?

or give me some code .

for example, very simple situation, diffuse bump mapping, texture unit 0 contains the normal map, tex unit 1 the normalization cube map and tex unit 2 the color map (simply decal, not modulate). assume that this is already set up, as well as the tangent space transformation. what is the combiner set up code for this?

thx

Jan

you should check nvidias developer site

there you find a lot of whitepapers and also demos/source code for their extensions. the CG sdk is also very interesting, beacause it contains also “the old demos” without cg

like following: http://developer.nvidia.com/object/Practical_Bumpmapping_Tech.html http://developer.nvidia.com/object/bumpmappingwithregistercombiners.html

If you have trouble understanding how the register combiners work, than check this paper out:
http://developer.nvidia.com/object/combiners.html

It is a very technical and very detailed description of the extension and makes it very easy to understand how to set up the stages to perform whatever you like.

It is my #1 reference when i work with the combiners.

Jan.

I know the nvidia developer site stuff, and the problem is that it is mainly technical descriptions on powerpoint charts with only a few lines of descriptions. It’s too abstract, I think. It’s not that I do not understand RC at all, but the gap from theoretical knowledge to being able to write some code to use it is stll quite large. So I would appreciate some lines of exampe code for the situation described above. In fact there’s one NVIDIA presentation for this, but the code is not OpenGL but for NVPARSE (I think), argh…

Jan

You are lucky, that i have a lot of time and nothing to do.

Since OpenGL.org´s code tags are crap, i put it into a seperate file:
http://www.artifactgames.de/IMAGES/example.cpp

I hope that will help you a bit.

Merry Christmas.
Jan.

great. thanks a LOT :-).

Jan

you added an attenuation map to tex unit 3. is this for point light/distance attenuation?

I copy&pasted your code into my program, removed the light attenuation map part, and… it works :-).

and it neglects fog, so I guess I have to continue learning about this.

I guess with register combiners I can do bump mapping with specular highlights in one pass (I know that you don’t like them, but in general it should be possible), and for that, the normalization cube map has to be bound to two texture units, one that takes the light vector as input, and one that takes the half vector as input. But in my application, I want to mask the specular highlights with a gloss map, so when needing two normalization cubemaps, I would need two passes, as the graphics hardware only has four texture units which are all in use already. Am I right?

And after all, I want the value stored in the gloss map in the alpha buffer after rendering (so that I can add reflections blended by destination_alpha). I guess that will not be a big problem? Turns out to be a register combiner setup quiz…

Thanks
Jan

I got the diffuse+specular stuff working… I am so happy that I have to post my code.

It still neglects fog, has no ligth color and no specular exponent, but it works!!

//unit 0: bumpmap
//unit 1: normalization cubemap for diffuse
//unit 2: base-texture
//unit 3: normalization cubemap for specular

glEnable (GL_REGISTER_COMBINERS_NV);
glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV,

float fColor0[4] = {1.0f, 1.0f, 1.0f, 1.0f};
glCombinerParameterfvNV (GL_CONSTANT_COLOR0_NV, (float*) fColor0);

//stage 1
glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_EXPAND_NORMAL_NV, GL_RGB);
glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_EXPAND_NORMAL_NV, GL_RGB);
glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE0_ARB, GL_EXPAND_NORMAL_NV, GL_RGB);
glCombinerInputNV (GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE3_ARB, GL_EXPAND_NORMAL_NV, GL_RGB);
glCombinerOutputNV (GL_COMBINER0_NV, GL_RGB, GL_SPARE0_NV, GL_SPARE1_NV, GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_TRUE, GL_FALSE);

// spare0: diffuse (tu0 dot tu1)
// spare1: specular (tu0 dot tu3)

//final stage
glFinalCombinerInputNV (GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV (GL_VARIABLE_B_NV, GL_TEXTURE2_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

glFinalCombinerInputNV (GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

glFinalCombinerInputNV (GL_VARIABLE_E_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV (GL_VARIABLE_F_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV (GL_VARIABLE_D_NV, GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

glFinalCombinerInputNV (GL_VARIABLE_G_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);//puts 1 into alpha

thanks again…

Jan

Yes, the attentuation-map is for a point-light. I use a 3D-texture at the moment, but if one had enough texture units (which is NOT the case on nVidia boards :frowning: ), then you could use a 2D and a 1D texture instead.

It´s absolutely normal, that you don´t get fog, since the pixel shaders replace a whole part of the pipeline, including fog-calculation.

And yes, you will need more than one pass to get good specular lighting results (gloss-mapping), as long as you only got 4 units. And i wouldn´t calculate the specular exponent in reg. combiners, because that looks very ugly (i tested it). Instead precalculate it and store it in a cubemap (you should be able to find some papers about that). Than you only need a reflection-vector into your cubemap and there the intensity is stored. That takes only ONE texture unit and gives good results, although you won´t get physically correct bumpmapped specular lighting.

In the final combiner stage the variable G gets written to the alpha-channel. So if you want your gloss-value to be stored in alpha, than you simply have to put the alpha (or blue, check out the pdf for more details) value of the gloss-map into the variable G in the final combiner stage. That´s really easy.

And you get your light-color, by simply putting it into fColor0! I stored (1,1,1,1) in it, but it is supposed to hold the color of the light.

Well then, have fun with it.

Jan.

The key to understanding register combiners is to draw a diagram of a single general combiner in it’s simplest form.

4 inputs, three outputs, scale/bias on each input and output.

Next inside the combiner draw two primary functional unit takes two of the inputs and sends out one output.

The two outputs from the primary functional units can then be sent to a secondary functional unit that generates an output.

The APIs let you set the operation on each functional unit (with limitations), the scale bias on each input and output (from a fixed set) and you can send the registers to any of the inputs and the outputs to any of the registers.

Simple, but draw it for best results. In addition imagine the combiners not as feeding into each other but as sitting on a bus of registers (wires). They take input from the registers and output to the registers. Just sit them in a row above the wires. (it’s not a bus I’m just talking about diagramatically here).

Once you draw this diagram with several general combiners sitting above the wires feeding ito a final combiner (that’s quite a bit different) will be forever endowed with register combiner insight.

[This message has been edited by dorbie (edited 12-22-2003).]

Turn this on it’s side and you have a general combiner.
http://www.tommti-systems.com/main-Dateien/previews/shaderlanguage/rcomb.gif

A row of them with the inputs tapped from a “bus” of registers completes the picture (minus the final combiner)

thanks a lot

I think I will try to get the fog and the light color and the gloss map working with RC in two pass rendering setup, and the that what the thread was originally supposed to be about comes into play, how to use these things when all geometry data is inside of display lists, I guess vertex programs are the right way to deal with this.

dorbie while messing with the register combiners, something like an image you mentioned started appearing in my mind, it’s really not that hard once you understand these things.

But as I said I there is still a lack of good step-by-step tutorials (as it is about a lot of OpenGL things), but I found the following to be useful:
http://www.beginthread.com/Article/Laeuchli/RegisterCombiners/

this together with the nv paper and the example from Jan makes a nearly perfect RC tutorial

I still do have a lot of questions but I think I will start a new thread when asking them as the thread’s name is rather misleading by now.

Frohes Fest

Jan