bump mapping (blinn's 1978 method)

I'm having a few problems implementing bump mapping as Jim Blinn describes in his 1978 "Simulation of Wrinkled Surfaces" paper. (A download of that paper can be found in this thread: http://www.beyond3d.com/forum/showthread.php?t=25306 )

Just curious if anyone here has implemented it (exactly) as described in that paper?
I haven't implemented Blinn's method "to the letter", but I have implemented a number of different bump mapping techniques, so I might be able to help.

What problem are you having?
 
The problems I am having occur when bump mapping a height map, whenever the slope of the height map is at extreme (nearly flat) levels. I have a demo that shows the 3D vector math of Blinn's method in Ken Silverman's Evaldraw ( http://advsys.net/ken/download.htm ). I will post the code here once I clean it up to make it easier to review. I will do this later on today...

It is not uncommon to get confused with 3D vector math, so I am not doubting that I have missed something simple!
 
Simon F,

I figured out the problem with my Blinn bump mapping. It requires that the partial derivatives (pu, pv) of the original surface and the original surface's normal (N) to create a coordinate system (pu, pv, N). In other words, pu and pv must create a right angle, which they do not if they are not "flat". The original surface must be parameterized in order to have this set properly... I was assuming I could use the px and py (of my height map defined in (x,y)) as the pu & pv, which obviously do not create a coordinate system on most slopes.

Anyways... Blinn's method does not work for me unless I parameterize my height map into (u,v) which I am not sure how to accomplish.

Another issue is that I am using fully 3D procedural bump map textures, and fully 3D surfaces, not 2D ones. This matters in that it is difficult for me to parameterize my 3D surfaces into a 2D (u,v) system, and I do not wish to as I want to map my 3D bump map precisles "as-is" to my 3D surfaces (as if they were carved out of an already existing 3D material).

Sorry if they is unclear, I am almost confusing myself here. I'm hoping that discussing it will help clarify the issue to myself!

Have your (Simon F or anyone) experiences with bump map coding involved fully 3D bump maps?
 
There are lots of articles on creating the necessary U/V coordinate systems.
The short version is it's not trivial.
I'd start on Nvidias site.
 
It turns out I found a very simple solution, due to the fact I am using a 3D bump map texture. I can perturb the original surfaces normal vector by another "perturbation vector" that is nothing more than the gradients (rate of change in rise/run) in x, y, and z in the 3D bump map texture. In other words, the values of (x,y,z) in this perturbation vector are the slope values of the bump map in x, y, and z. I've tried it out and it seems to work fine in all the extreme cases.

To create the u/v coordinate system seems to be something required if I were to be using a 2D bump map texture.

Thanks for helping me out!!
 
Last edited by a moderator:
The solution I have is not optimal. The perturbation of the original (smooth) surface normal can exceed 90 degrees (something which should not happen if the bump map represents a height field, as the bump map can never represent an angle of greater than 90 degrees.)

Is there a simple solution I am missing?

Anyone would has bump mapped a 3D surface via a 3D texture, I would love to discuss these issues with you!
 
How can that be possible? IIRC, the pertubation you add to the normal lies in the plane of the tangents.

Very true, but the perturbation is added to a normalized (lenght 1.0) normal, so if you were to get a gradient (rise/run rate of change) of greater than 1.0 in the direction of the normal, (because the gradient value is subtracted from the normal) it would perturb the normal to point in the opposite direction.

That is hard to understand, so let me clarify with an example:

------------

N = original smooth surface normal
N' = bump mapped surface normal
P = perturbation vector (composed of rise/run slopes, gradients, in x, y, and z)
N' = N - P

N = (0,0,1) = normalized normal pointing towards positive z
bump map gradient in x = 0
bump map gradient in y = 0
bump map gradient in z = 3
(In other words, the bump map has a rise/run slope of 3 in the direction of positive z, and 0 slopes in x & y.)
P is constructed from the gradients:
P = (0,0,3)

N' = N - P
= (0,0,1) - (0,0,3)
= (0,0,-2)

Normalize N':

N' = (0,0,-1)

N' now points in the opposite direction, 180 degrees rotated from N!

------------

A gradient of 3 is a rise/run of 3/1, which is only an angle of... atan(3/1) = 1.25 radians or 71.6 degrees.

71.6 degrees seems like a sharp slope. (It is.) But the bump map height field has the potential to produce slopes up to 90 degrees. But that is just from my extreme example. The point in which a slope has the potential to surpass the normalized original normal length of 1.0, is when the rise/run because greater than 1.0, which occurs at 45 degrees. 45 degrees in practice is uncommon, but I was hoping for a solution that would work in all cases.

I still feel like I'm missing a better solution.

What I have done for now, works, which is to catch all perturbations of the normal vector that are greater than 90 degrees, and rotate them BACK to the 90 degree point (in the same direction of rotation of course). So, whenever the perturbation causes a >90 degree rotation, I calculate where it would be if the rotation happened to be only 90 degrees.

I hope this explains my problem better!
 
Last edited by a moderator:
I don't think you are calculating that correctly. I've just skimmed through Jim Blinn's paper and the displacement that is added to the original normal, N, lies in the plane perpendicular to N. (Look 1/2 way down the second column of the second page)

Therefore, it should be impossible to achieve even a 90 degree perturbation.

He gives some (Fortran :) ) pseudo code to do it that you could base your code on (shrug).
 
Simon F, I'm sorry but I stopped using Blinn's method and started using a new method!

(I first explained this in my post in this thread that starts, "It turns out I found a very simple solution..." I realize that I confused this whole thread when I did this, but I could not go back and change the thread title!)

Blinn's method is great for 2D bump maps that have to be mapped onto 3D surfaces. But, I have a 3D bump map, which is just a 3D texture, mapped onto a 3D surface.

The bump mapping method I am using is a modified version of and idea I stumbled upon when looking at this 3D noise example (by Ken Perlin):
http://mrl.nyu.edu/~perlin/homepage2006/bumpy/index.html

Note that the above example is using a 3D texture as the bump map. Visit the above link to see visuals.

The code of that example:
http://mrl.nyu.edu/~perlin/homepage2006/bumpy/Sphere.java

The bump mapping portion of that code:
Code:
         /* sample code of Ken Perlin's 3D bump mapping of a unit sphere */

         // COMPUTE POINT ON UNIT SPHERE (WHICH IS ALSO THE SURFACE NORMAL)

         normal[0] = X / R;
         normal[1] = Y / R;
         normal[2] = Math.sqrt(1 - normal[0]*normal[0] - normal[1]*normal[1]);

         // SAMPLE THE FUNCTION FOUR TIMES TO GET GRADIENT INFO

         double f0 = f(normal[0]      ,normal[1]      ,normal[2]      ),
                fx = f(normal[0]+.0001,normal[1]      ,normal[2]      ),
                fy = f(normal[0]      ,normal[1]+.0001,normal[2]      ),
                fz = f(normal[0]      ,normal[1]      ,normal[2]+.0001);

         // SUBTRACT THE FUNCTION'S GRADIENT FROM THE SURFACE NORMAL

         normal[0] -= (fx - f0) / .0001;
         normal[1] -= (fy - f0) / .0001;
         normal[2] -= (fz - f0) / .0001;
	 normalize(normal);

It is so simple and appears to work great. It (seems to) make complete sense when you look at it in 2D, but I know it can be broken (as previously explained) in 3D with extreme bump map angles. (I have actually "broken" it in my software, and I explain how it can happen in my previous post.)

I still have a feeling there is a better solution (that never "breaks" for any rise/run angle encountered in the bump map) when dealing with 3D bump map textures on 3D surfaces...

In searching for bump mapping methods, I usually only find methods that are for 2D bump maps. I have ideas on how to turn my 3D bump map into a 2D bump map (a 2D slice of my 3D bump map would do it) on a per-pixel basis, which would make these methods work, but Ken Perlin's code has given me some indication (or a feeling) that an easier, and more elegant, solution exists!
 
Last edited by a moderator:
I might be missing something, but your example confuses me. How can you have a3d bump map?
I mean, for what purpose? You could produce "hang over" ;-) bumps in case you use a 3d color texture as well, hm? But I doubt that this works in practice. But in that case, of course you can produce bump normals pointing opposite the surface normal as in your example. You can produce any kind of bump normal with that. A 3D bump would needed to be coupled with a specific model to avoid this behaviour.

Just a few thought... Please tell me if I missing the whole point... lol

Edit: Just took a look at Ken Perlin's example. At first glace I guess the function f produces a "good" bump normal, i.e. one which doesn't hang over. However, its just a guess. Did you try using Ken's noise functions?
 
Last edited by a moderator:
The bump map is not 3D in the sense that you are thinking about it.

The bump map is nothing more than a 3D texture. The 3D texture is a 3D procedural texture that takes in (x,y,z) and returns -1.0..1.0. The -1.0..1.0 output is a height. -1.0 is the lowest height possible, and 1.0 the highest.

So, the 3D bump map is still only a height field, but just one that has values within a 3D area as opposed to a 2D area (like a normal 2D texture).

The way this helps is that the 3D surface being bump mapped with the 3D bump map can use a "carved out" section of the 3D bump map that perfectly fits the 3D surface. Imagine texturing a 2D texture on a sphere. It is difficult to do without distortion the 2D texture in one way or another. Texturing a 3D texture on a sphere just requires sampling of the 3D texture in a spherical shape. The values returned by that 3D texture can be used just the same as value from a 2D texture would be used.

Please let me know if that explains it... or if it explains it but still sounds confusing. I can always clarify more!

...

By the way, the Ken Perlin example above uses his 3D noise as a 3D bump map texture, exactly the way I explained above (in this post).

My 3D noise is based upon Ken Perlin's original gradient noise (aka Perlin noise) work, so it is very familar. That's where I adopted the -1.0..1.0 range (as opposed to a 0.0..1.0 range).
 
Matthew,
What you are doing with the 3D Perlin textures sound very much like what I/we did in a previous job when applying bump maps in a ray tracing system. Unfortunately it was a long time ago and I can't remember the details.:cry:

I can't recall having any problems with normals etc.

There were images of the results on the net but they seem to have vanished.
 
Last edited by a moderator:
Anyone who has programmed a ray tracer with bump mapping using 3D textures would be running into the same issues as I am.

I think the solution I now have works, so I am ok. The solution works for small bumps, and large bumps "break the system" of bump mapping, what I mean is the bump emulation effect stops working for large bumps (it produces unconvincing results for large bumps), so I will be avoiding this anyway.

I just had to make some effort to see if a more elegant solution existed!

If you ever stumble upon this problem (or solution), and you remember me, please let me know! My bump mapping code is quite modularized and very easy to change at any point in time.
 
Please let me know if that explains it... or if it explains it but still sounds confusing. I can always clarify more!

Thanks, well, ok, got it. But in this case it is definitely not possible to get a bump normal having a negative z component. (If the 3d bump map is really just a 2d heightfield defined in 3d space it has the same limitations like a 2d bump map, hm?)
 
Thanks, well, ok, got it. But in this case it is definitely not possible to get a bump normal having a negative z component. (If the 3d bump map is really just a 2d heightfield defined in 3d space it has the same limitations like a 2d bump map, hm?)
Exactly. Any 2D plane (oriented in any angle at all) of the 3D bump map is a 2D bump map just like any other 2D bump map. The fact that they values are obtained via 3D (x,y,z) instead of 2D (x,y) doesn't change what the values mean. They are still just height values.

EDIT:

I should be using (u,v,w) and (u,v) when dealing with 3D and 2D texture coordinates instead of (x,y,z) and (x,y).
 
Last edited by a moderator:
So, but what you just said contradicts this earlier post:

What I have done for now, works, which is to catch all perturbations of the normal vector that are greater than 90 degrees, and rotate them BACK to the 90 degree point (in the same direction of rotation of course). So, whenever the perturbation causes a >90 degree rotation, I calculate where it would be if the rotation happened to be only 90 degrees.

There cannot be a any perturbations greater than 90 degrees in a 2d bump map.
 
Last edited by a moderator:
There cannot be any perturbations greater than 90 degrees in a 2d bump map.

With the proper formula, this is true. (This is the algorithm I am looking for!)

With the formula I am using (based on Ken Perlin's code), this is not true. So, the bump mapping formula I am using is not optimal.

The bump mapping algorithm I am using only causes >90 degree perturbations when it encounters extreme bump map angles, which I now catch for and handle. These are angles that rarely, and hopefully never, happen... as they are so extreme that bump mapping itself begins to stop working as a visual tool to showcase such extreme angles. (Anyone who has tried to see how far bump mapping can go by increasing the "strength" or height of their bump maps, knows what I mean. You can only go so far before the visuals stop making sense.)

From my explanations in previous posts of how and when the algorithm I am using "breaks", I showed it requires a bump map gradient, rise/run slope, of greater than 1.0, which is a 45 degree angle. And even still, even with a greater than 1.0 gradient, the gradient has to be pointing in right direction to fail. So, it never fails just because a >1.0 gradient exists, but it requires a >1.0 gradient in order for it to fail.
 
Last edited by a moderator:
Anyone who has tried to see how far bump mapping can go by increasing the "strength" or height of their bump maps, knows what I mean. You can only go so far before the visuals stop making sense.

Yes, this is because bump mapping is basically only a fake... ;-)

Anyway, your example and your explaination still confuses me:

You worte in the example:

P = perturbation vector (composed of rise/run slopes, gradients, in x, y, and z)

If it is like it is in your explaination there shouldn't be a gradient in z direction because a bump map is only a 2d heightfield. There are just x- and y-slopes.
 
Back
Top