NV Register Combiners questions

Hi,

I will have to take a deep look into NVs Register Combiners, before I can start coding with them (and I don´t want to use NV parse at the beginning).

But before the whole learning process, I´ve got some questions.

  1. Is it possible to do a cube map normalisation + diffuse DOT3 Bump Mapping on GF2 with 2 general combiners and 2 texture units in 1 pass (I currently do this with GL_ARB_texture_env_combine, GL_ARB_texture_env_dot3 and 3 active texture units on my GF3 in 1 pass)?

  2. Is the quality / speed of the Register Combiners superior to the thing I´m currently doing?

  3. What´s the best solution for doing DOT3 Bump mapping on GF2 in one pass with RCs (only diffuse / diffuse + specular / diffuse + CM normalisation … etc.)?

Diapolo

1: Yes, but you can’t have a base texture (as that would require 3 texture units) at the same time.

2: Well, seeing as how nVidia probably implements the OpenGL TexEnv stuff in Register combiners, yes.

3: How many ways to do it are there? As far as I know, there’s only one way, and it works.

Korval:

  1. That was the question, is it possible with a base texture in one pass on a GeForce2? And your answer is NO, right?

  2. Could you give me a better hint, what you mean by your 2nd answer ?

  3. I dunno how many ways are there, I´m searching for the best way to do it in one pass?
    Should be base texture modulated with N.L i guess … but can I achieve some form of normalisation on GF2 with the 2 combiners I have and with the 2 texture units?
    Perhaps a way to add the specular component (for which I have to learn the math, currently I only know to do the diffuse part).

Diapolo

1: A GeForce 2 can only apply 2 textures. The bump-map and the renormalization map take up those two slots. So you will have to go to a second pass, or just not renormalize the interpolated normal (it doesn’t look that bad for a lot of things).

2: What I mean is that the actual hardware that does texture combining, that implements glTexEnv calls on the GeForce 2, is almost certainly the register combiner hardware. What the NV_register_combiner extension allows you to do is program that hardware directly, rather than use the normal OpenGL commands to get at that functionality. The actual hardware is significantly more powerful than what the glTexEnv calls let you get to.

3: I seem to recall a paper on nVidia’s web site about a way to approximate the renormalization of a normal without using a cubemap. However, that may have required more register combiner operations than a GeForce 2 has.

3: I seem to recall a paper on nVidia’s web site about a way to approximate the renormalization of a normal without using a cubemap. However, that may have required more register combiner operations than a GeForce 2 has.

Yes this was done using the register combiners but it takes 2 general combiners to normalize one vector, 3 gen combiners for 3 vectors and so on. So unless you have a geforce 3 or 4ti, you cant do it. Well i say you cant, you can but it will be in software and slow as hell. But they [nvidia] also said that using the register combiner normalizing technique is faster than using the cube map method (on the gf3 & 4ti of course).

-SirKnight

I see, so the “best” thing for DOT3 Bump Mapping on a GeForce 2 is N.L <modulate> base texture without any normalisation technique (1 pass).
I´m currently doing this via combine and dot3 extensions and I will try to convert that into register combiner code (like I said, I first have to read through the whole tech docs g).

But this whole stuff should be possible in 1 pass with diffuse AND specular, right (read that somewhere in the NV tech docs)?

But I still don´t understand how to do this (diffuse + specular).

The equation I currently use is:
final Color = diffuse Color * (N <dotprod> L)

I know how to compute L in tangent space and all that stuff.

But how can I get H (which is the half-angle vector?)?
And how should I set my secondaray color?

Diapolo

i have an application done wich does diffuse and specular in one pass, with different exponents and a glossmap, and a colormap… but its only a fake in fact… its cool to get the gf2 till the end of its power (using the two textures rgba and the two colors rgb and rgb… (i let out one alpha, yes )

it even does selfshadow the bumps, wich is an (imho) important grafical improvement for solid geometry (for water you can disable it)

registercombiners are nice powerfull, i can’t wait for my gf4 with 4 textures and much more general combiners (oh, and tex-shaders, too )

here is the demo: http://tyrannen.starcraft3d.net/PerPixelLighting

but i don’t have the source anymore…

OK, I read through the NV_register_combiners specs.
For now I´ve got only 2 questions (more to come? g):

  1. If I use glCombinerOutputNV without a GL_TRUE for DotProduct and muxSum, then the combiner does a AB multiply and a CD multiply?

  2. SPARE0_NV and SPARE1_NV are in some way a “temp storage register”, that don´t directly affect the final computed output color?

Diapolo

Btw.: How many general Combiners supports the GF4 (GF1/GF2: 2 - GF3: 8)?

[This message has been edited by Diapolo (edited 03-08-2002).]

  1. You can do a AB and a CD and a AB+CD but to do that you need to tell it where you want the computed value (output) to go. Yes you can set the last 3 to GL_FALSE at the same time.

  2. They are storage units, but spare 0 " is hardwired in the color sum unit" in the final combiner stage. Be careful with that.

  3. I see support for NV_register_combiners and NV_register_combiners2 at http://developer.nvidia.com/view.asp?IO=nvidia_opengl_specs
    so Im assuming it hasnt seen further development. Correct me if Im wrong please.

V-man

V-Man:

  1. If I set the last ones to GL_FALSE I will get an AB, CD multiply and a result for (AB)+(CD), right?

  2. You are right, Spare0 is hardwired to the Color sum unit.
    One question on that, what is the initial value of the secondary color if I didn´t set it?

  3. And I thought, that perhaps GF4 would have more general combiners, than GF3 has, even without NV_register_combiners3 . Not that I would be able to use all the 8 combiners I have on my GF3 g … I only wanted to know.

Diapolo

Originally posted by Diapolo:
[b]V-Man:

  1. If I set the last ones to GL_FALSE I will get an AB, CD multiply and a result for (AB)+(CD), right?
  1. You are right, Spare0 is hardwired to the Color sum unit.
    One question on that, what is the initial value of the secondary color if I didn´t set it?
  1. And I thought, that perhaps GF4 would have more general combiners, than GF3 has, even without NV_register_combiners3 . Not that I would be able to use all the 8 combiners I have on my GF3 g … I only wanted to know.

Diapolo[/b]

  1. Yes that case will work. If you do set some of those to GL_TRUE, it may not because of limitations. Something about upgrading the register combiners and limiting the number of adders and multipliers.

  2. Secondary color is a incoming value computed by some part of the geforce. If there is no specular (secondary color), it will be zero.

  3. For more functionality, they have to add a new extension so that we’ll know new registers are available. But! why should that stop us from upgrading!

V-man

Cool, I figured it out, how to do the simplest form of DOT3 Bump Mapping via the RCs … doesn´t seem too complicated to use, but I guess there are some pitfalls, that one has too look for.

Here is my current RC code:

    // UNIT 0 (Normal Map)
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glBindTexture(GL_TEXTURE_2D, TEXTURES.Return_TextureIDs(3));
    glEnable(GL_TEXTURE_2D);
    // UNIT 1 (Base Texture)
    glActiveTextureARB(GL_TEXTURE1_ARB);
    glBindTexture(GL_TEXTURE_2D, TEXTURES.Return_TextureIDs(2));
    glEnable(GL_TEXTURE_2D);

    // Register Combiner Setup Code

    glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 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_PRIMARY_COLOR_NV, GL_EXPAND_NORMAL_NV, GL_RGB);
    glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_SPARE0_NV, GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE);

    glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
    glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

    glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
    glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

I´ve got a question, on secondary color.
Do I have to use the GL_EXT_secondary_color to set a per-vertex secondary color, if I want to use this color in my RC code?

Diapolo

I´ve got a question, on secondary color.
Do I have to use the GL_EXT_secondary_color to set a per-vertex secondary color, if I want to use this color in my RC code?

I’m pretty sure you do. At least I have always used that extension for secondary colors, I’ve never seen it done any other way.

-SirKnight

Originally posted by SirKnight:
[b] I’m pretty sure you do. At least I have always used that extension for secondary colors, I’ve never seen it done any other way.

-SirKnight[/b]

You can do it withouth the extension
just use glVertexAttrib3dNV to put the 2nd color directly in the vertex program register
Am i right ?

I guess you are right McBain, but currently I don´t use Vertex Programs .

First I learn Register Combiners and do all my vertex math on the CPU (currently that works).
And after I know, how to do great-looking Bump Mapping and Per-Pixel Lighting, I´ll take a look at Vertex Programs and Texture Shaders .

By the way, what is a good code example / sample app, if I want to learn, how to do diffuse + specular DOT3 Bump Mapping with the RCs (I know about the diffuse part, but know not much about the specular part … mainly, how to compute the half angle vector H)?

Diapolo

That halfangle vector is just the view vector (negated) and the light vector (negated) added together. If you remember adding two vectors gives you the vector inbetween the two. So knowing that, you should be able to see why those two vectors should be negated. Try it on paper if you need to, thats what i did. Oh and remember when you dot N and H to raise it to some specular exponent. I use a function that makes it look like it was raised to the power of 16. It works quite well.

Also McBain is correct about the vertex attrib thing but if your not using vertex programs, looks like your stuck using the EXT_secondary_color extension. I totally forgot about the vertex attrib functions at the time, otherwise i would have also stated that.

-SirKnight

That leads me to the question, how to compute the view vector .

Light Vector is simply light position - vertex position.

View vector = camera position - vertex position?

Diapolo

Diapolo,

Yep, that’s right. And in eye space, the camera position is (0,0,0), so the (unnormalized) view vector is just (-vertex_position).

Thanks -
Cass

Thanks for that reply cass .

Correct me, if I´m wrong, the vertex position I have is in object space and 0.0f, 0.0f, 0.0f is the camera position in eye space.
So in order to compute the view vector in object space, I have to do a matrix multiply with cam pos in eye space and the inverse modelview matrix.
After that I get the cam pos in object space and can compute:

view vector_OS = cam pos_OS - vertex pos_OS

That is, because the light vector I compute is in object space, too and in order to get a correct half-angle vector I guess the 2 vectors have to be in the same space, or?

Diapolo

i’m not 100% percent sure if i read your post correctly… but one thing:
if you need to transform the eye-pos from eyespace (0,0,0 for the eyepos there ) into some other space by a matrix, just take the last row… why? beauce the 3x3-part of the matrix gets multiplied with the (0,0,0) vector… so don’t care about this
should help to find the correct vector faster…