normal maps, DUDV maps, GLSL & too few texture units

Sage
Posts: 1,199
Joined: 2004.10
Post: #1
So, I'm following a GLSL tutorial to do water (http://bonzaisoftware.com/water_tut.html), with fresnel perturbation, reflections, etc. The tut requires a normalmap and dudv map, and the app generates the refraction map, depth map, reflection.

Now, here's the problem. My 5200 only supports 4 texture units, but the code requires 5 ( reflection, refraction, depth, normalmap, dudvmap ).

So, I did some research on DUDV maps, and with some googling, I found a link that describes how to make one from a normal map in photoshop, without any of the Windows-only NVIDIA plugins. The page says you -- basically -- just invert the image and raise the contrast. The result is all yellow, red and green, which makes sense, since the blue channel is mostly white on a normal map anyway. My inference is that a DUDV map is just the red/green channel of a normal map that's been raised to some arbitrary power.

I'm guessing, then, that I can dispose of the DUDV map in my code and instead generate one as needed by querying the red and green values of the normal map and -- optionally -- raise them to some power.

Is this a valid assumption?

Thanks,
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #2
Sounds about right. If you also check the update notes for that tutorial, it mentions that the fifth unit wasn't really used, so you might want to scroll to the bottom and see if that helps you. Smile
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #3
The up date only says the fifth unit's texture coords weren't used; the texture itself is sampled, using generated coords.

But, so long as it's relatively reasonable to generate my DUDV by taking the red/green from the normal map I'm happy. Hell, it doesn't even need to be mathematically correct, so long as it looks reasonable.

I am using the GLSL version, btw.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #4
You don't have to do all the features represented in the book. I haven't tried this yet, but I was planning on having water with a reflection of what's above it, refraction of what's below it, based on a single normal map. Essentially, I was going to apply the sphere mapping formula to the normal map. (for the refraction, it would be more of the inverse of the sphere mapping) Assuming this looks good, it would only require 3 texture units. (don't expect any results soon, though, since I wasn't going to try it until I am done with my current project at the least)
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #5
akb825 Wrote:You don't have to do all the features represented in the book.,

Which book? Well, I'm getting the Orange Book in the mail any day now ( ordered friday, got shipping notice yesterday ) and for what it's worth I do plan on doing most of its chapter examples.

akb825 Wrote:I haven't tried this yet, but I was planning on having water with a reflection of what's above it, refraction of what's below it, based on a single normal map. Essentially, I was going to apply the sphere mapping formula to the normal map. (for the refraction, it would be more of the inverse of the sphere mapping) Assuming this looks good, it would only require 3 texture units. (don't expect any results soon, though, since I wasn't going to try it until I am done with my current project at the least)

Admittedly, I'm just following the tutorial, but it looks promising in that it will do depth-based opacity, distortion of the solid geometry that's under water, and reflections too.

Probably this is a bad idea -- considering this is my first non hello-world for GLSL -- but I made some changes such as using RECT textures for the refraction and depth ( to save an extra drawing pass ) and FBO to render the reflection. I'm going to use mipmap LOD biasing to "blur" the reflection, since there's no way in hell my 5200 can run a -- say -- 9x9 gaussian blur on each reflection fragment lookup. I've done 9x9 on my 5200 in arb 1.0 asm and it was slow as molasses.

So far my infrastructure is good. I've got the solid geometry successfully as a texture, the depth buffer and reflection textures, etc all working. The actual water shader is just drawing black right now, however. I'm going to tear it apart and re-assemble it bit by bit to figure out how to make it work. ( and yes, I am using texture2DRect and sampler2DRect for my GL_RECTANGLE_EXT refraction and depth textures, and I am scaling the lookup to the screensize from [0,1] )

I might post some questions, but I'm hoping I can figure this out by myself.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
This is like jumping into the middle of the ocean for your first swimming lesson. It's made somewhat easier since you're following it step by step, but it's still a huge leap.

I was just going to do a fog for my underwater rendering. You could also use a shader with the render and the depth buffer to create an intermediate texture if you wanted to do something more complex for your underwater stuff, while cutting down on a texture unit.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #7
I agree wholehartedly that it's a big jump.

On the other hand, the math makes 100% sense to me, so mainly it's like a new API, not so bad, really.

Regarding getting it working, I do actually plan to make a simple one with just per-pixel opacity and specular ( using the normal map ) since I don't expect the full quality version to run real time on my 5200. The learning/debugging process will be to tear down the whole version to make the simple, and then building it back up for better video cards.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #8
There is a difference between "texture units", "texture coordinate units" and "texture image units". Your 5200 has only four "texture units", but eight "texture coordinate units" (go figure) and sixteen "texture image units"; you should be able to run the shader just fine.

Remember that GLSL ignores the Enable state of the texture units, and that enabling a texture unit that your card doesn't support will generate an OpenGL error.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #9
OneSadCookie Wrote:There is a difference between "texture units", "texture coordinate units" and "texture image units". Your 5200 has only four "texture units", but eight "texture coordinate units" (go figure) and sixteen "texture image units"; you should be able to run the shader just fine.

Wacko

What is a "texture image unit"? I grok the distinction between the texture unit and texture coordinate, but what's the third mean?

The sample code has me binding the 5 textures across GL_TEXTURE{0,1,2,3,4}, which when run did nothing ( plus it gave me gl errors ). I queried GL_MAX_TEXTURE_UNITS and got "4". Given that, does that mean that I can run a sampler2D in GLSL without calling glBindTexture? I know I have to map the texture name to a uniform sampler, so is that a workaround?

OneSadCookie Wrote:Remember that GLSL ignores the Enable state of the texture units, and that enabling a texture unit that your card doesn't support will generate an OpenGL error.

That's what I find interesting about GLSL. Like being able to alias lights which aren't enabled. Not that that's useful to me -- at the moment -- but interesting.

I'm learning as I go, here.

That said, my original question remains... can I just access the red and green components of a normal map to "fake" a dudv map?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
"texture units" affect the fixed-function and ARB_texture_env_combine pipeline. They comprise both a "texture coordinate unit" and a "texture image unit", effectively.

"texture coordinate units" affect the programmable vertex pipeline, and define how many independent sets of texture coordinates you can send.

"texture image units" affect the programmable fragment pipeline, and affect how many different textures you can have bound simultaneously.

So, if GL_MAX_TEXTURE_UNITS is 4 and GL_MAX_TEXTURE_IMAGE_UNITS_ARB is 16, glActiveTextureARB(GL_TEXTURE4_ARB); glBindTexture(GL_TEXTURE_2D, id) is legal, and will be accessible by the fragment shader, but glActiveTextureARB(GL_TEXTURE4_ARB); glEnable(GL_TEXTURE_2D) is not.

You can always shrink a vec4 in GLSL; you can refer to the components as "rgba", "stpq" or "xyzw":

Code:
vec4 temp;

vec2 rg = temp.rg;
vec3 xyz = temp.xyz;
vec3 zyx = temp.zyx;
vec2 qs = temp.qs;
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #11
This is a FAQ.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #12
Good news!

I took a short break while I waited for my copy of _The Orange Book_ to arrive, but as of today I have the shader working, with RECT refraction and depth textures.

Now, it's slow as hell, running on my 5200: 5fps! Cry

But, having read the shader source there's some stuff I figured out ( such as using gl_FragCoord instead of some inline perspective divide calculations ) which ought to speed it up a little, and I'm willing to make a lighter fallback shader for cards like mine which doesn't draw the reflection. Anyway, the important part is I'm ready to roll, now.

Also, yes, swizzling the normal map makes a perfectly functional dudv map -- I tested it and lo t works great. What I don't get is why the author used a dudv map at all... perhaps I'm not getting something. Or perhaps he's silly, I don't know.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #13
Somewhat happily, I have to report that I get ~60fps on a GeForce 6600. Thank god.
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #14
Screenshots!
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #15
Fenris Wrote:Screenshots!

Eh... not yet. The reflection mapping code is atrocious -- I'm not certain what the dude who wrote the tutorial was thinking -- it fails if the camera has any "roll". I'm fixing it by rewriting it to use gl_FragCoord instead of some reverse projectiony stuff.

However, doing this has taught me a *lot*, both in terms of fixed function gl and GLSL ( since I got the orange book last week ) and I've been able to revive my full-screen filter stack code, which allows me to stack "effects" to run on the output of my engine. I've implemented a few basic effects, like bloom, gloom, per-pixel distortion ( using a flattened normalmap as a dudv map, as per the title of the thread ). Here's some screenshots for that:

Here I am, unerwater, with per-pixel rippling:
[Image: Screenshots-2006-06-20-05.png]

Here's the game paused -- which uses "gloom" ( gaussian blur + greyscale, mixed with original image by 75% )
[Image: Screenshots-2006-06-20-07.png]

And finally, to show that effects can be stacked, here's both together:
[Image: Screenshots-2006-06-20-04.png]

And... here's a screenshot of the water anyway, even though the reflection and refraction mapping are screwy:

[Image: crap_water.png]

You'll notice that not only is the reflection screwy, but the lighting for the reflected scene is all messed up. Now that I've got my full-screen effect stack code working ( which taught me a lost of basic GLSL ), I'm getting back onto the water.

And another shot, for reference. You can see the per-pixel rippling of what's beneath the water:
[Image: crap_water_2.png]
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Normal Mapping Precision on iOS OptimisticMonkey 6 33,921 Apr 13, 2011 11:35 PM
Last Post: OptimisticMonkey
  Getting the Normal for a polygon. Jaden 3 5,955 May 1, 2009 01:47 PM
Last Post: Nosredna
  Vector (Normal) Map blending operations? kelvin 10 6,838 Mar 16, 2007 04:31 PM
Last Post: OneSadCookie
  drawing or displaying vertex normal shru_ani 3 3,749 Oct 29, 2006 06:04 AM
Last Post: shru_ani
  Gouraud vs Normal maps for dinamic terrains sohta 6 4,174 Oct 11, 2006 12:55 AM
Last Post: sohta