Solved

# Render a height map on a texture ?

Posted on 2001-07-19
417 Views
Does anyone know, or can explain how to perform shading and/or refraction of a height map on a texture or image.

Say we have a 20 X 20 array which holds height values ranging from 0 to 10. How can I use this map to apply it to a 20 by 20 image ?
0
Question by:CyberKnight
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• Learn & ask questions
• 4
• 4

LVL 6

Accepted Solution

edey earned 60 total points
ID: 6300002
For both shading & refraction you'd want to calculate a list of delta values for each heightmap "pixel". I'm assuming that the height map is stored in a 1 dim array, say a PIntegerArray:

Type
TIntegerArray = array[0..32767] of integer;
PIntegerArray = ^TIntegerArray;

that we happen to know if so wide & so tall. So we could do somthing like this:

for iy := 0 to heightMapHeight-1 do
for ix := 0 to heightMapWidth-1 do
begin
deltaX := heightMap[abs((ix-1)+(iy*heightMapWidth))mod(heightMapWidth*heightMap.Height)]-heightMap[abs((ix+1)+(iy*heightMapWidth))mod(heightMapWidth*heightMap.Height)];
deltaY := heightMap[abs(ix+((iy-1)*heightMapWidth))mod(heightMapWidth*heightMap.Height)]-heightMap[abs(ix+((iy+1)*heightMapWidth))mod(heightMapWidth*heightMap.Height)];

those rather ugly & unoptomized array ref's really just treat a 1 dim array like a 2 dim one and find the values for (a-b) & (c-d) if:

c
a,(ix,iy),b
d

It also takes care of over & under runs so you'll always refer to a real position in the array - even if you try a neg number or one past the end.

What you do with deltaX & deltaY depends on if you want shading or refraction.  For shading you could adjust the rgb values of each pixel according to the the magnitude of the vector (deltaX,deltaY).  For refraction you'd prob do something like this:

1)take that vector & multiply by some constant (like 0.01)
2)add the result to (ix,iy)
3)draw the pixel at (ix,iy)+i*(deltaX,deltaY) to (ix,iy)

This stuff take quite a bit of tweaking to look good - esp the refraction.  if the delta vectors get too big the result just looks rather random.  Another note is you'd prob. want to keep a "clean" v of your src bmp and never draw to it.  So you'll need two bmp's, one for a ref, the other to prepare your shaded (or refracted, or both) bmp.  That way you don't have to worry about refracting pixels that will need to be referred to later.

GL
Mike
0

LVL 21

Expert Comment

ID: 6300423
You can try using the openGL library. It's very powerful. if you have opengl32.dll and glu32.dll on your PC your almost there; you just have to write to code. Delphi also includes openGl.pas/dcu etc.

0

Author Comment

ID: 6301986
Ok Mike, I kind of follow.

Lets tackle shading first.

(for simplicity lets say that the height map ranges from 0-100, just like percentage)
If height map looks like this
10 20 30
40 50 60
40 60 70

(Lets say position x,y = 50 (middle of the map))

Then DeltaX for X,Y(50) = 60-40 = 20
And  DeltaY for X,Y(50) = 60-20 = 40

right ??

And if Pixel X,Y on my texture/image is a color like (R,G,B)100,155,50 (for example)

Then to get the new pixel color..??? what do I do with the Delta values..and the RGB values (100,155,50 in this example)..??
0

LVL 6

Expert Comment

ID: 6303950
The general idea is to get some scalar value from (deltaX,deltaY) with which to modify (somehow) (r,g,b). Let's tackle the former first.

How do you want to shade your bmp?  For the following I'm going to assume that pixels with a high angle of incidence (the vector points away from you, the slope is high) will be shaded and pixels with a low angle of incidence (that portion of the height map is relatively flat, "reflects" back to you) will be normally illuminated.  So now we have to calculate our shading scalar. It would be nice to get a value we know is going to be between 0 and 1 this would be a posibility:

deltaX := cos(arcTan(deltaX));
deltaY := cos(arcTan(deltaY));

Note:, if everything comes out really dark you might want to try:

deltaX := cos(arcTan(deltaX/1000));
deltaY := cos(arcTan(deltaY/1000));

or some other constant. Then a simple average gets:

now we want that to be our total shade adjustment, and not for every r,g & b byte so:

and so:

and so on.
I hope that that's clear.  One thing I should make clear is that there are an infinite number of "right" ways to do this, each situation is a little different & playing with the constants, the formulas & such is highly recomended.

GL
Mike
0

Author Comment

ID: 6304428
Hey Mike !!!

That was X-cellent !!! Thank you !

I got the shading working pretty well !!!
Kewl.. It produces a really great effect.

You are right bout the inifite "right" ways to do it...
I had to play around with the formulas and constants a bit before I got it looking reasonable.

Can we touch on refraction ?
How do I manipulate the RGB pixels values with the delta values..?
0

Author Comment

ID: 6304442
Hey Mike !!!

That was X-cellent !!! Thank you !

I got the shading working pretty well !!!
Kewl.. It produces a really great effect.

You are right bout the inifite "right" ways to do it...
I had to play around with the formulas and constants a bit before I got it looking reasonable.

Can we touch on refraction ?
How do I manipulate the RGB pixels values with the delta values..?
0

LVL 6

Expert Comment

ID: 6305701
Refraction, In my opinion, is actually simpler and more straight forward.  A couple general steps:

1)Get the Normal to the plane (the height map) at the current pixel (x,y). Thats the vector perpendicular to the plane, in this case the plane tangent to the "surface" of out height field @ (x,y).  We're actualy going to cheat & use (deltaX,deltaY) so we can use most of the shading code.

2)"Tune" the normal vector, if the magnitude of the vector is too high, we'll just get noise, if it's too low we won't see anything.

3)Add the normal to our current heightMap location (x,y).  Check to see if our new point is outside the map, if it is, try to put it somwhere that "sorta" makes sense.  If you've done a good job of "tuning", though, this shouldn't be too muich  of a promblem & you can just use one of two solutions:

a)remember our height field is a linear array, so take (x,y) & get a scalar, p = x+y*heightMap.width. Remeber that x & y don't equal (x,y) any more, but (x,y)+k(deltaX,deltaY) where k is prob. some small number, like 0.001.  Given this, if p < 0 then p := 0 else if p >= heightMap.width*heightMap.height then p := heightMap.width*heightMap.height-1

b)Similar to a), once you've calculated p manipulate it like so: p := (p+heightMap.width*heightMap.height)mod (heightMap.width*heightMap.height).  This will ensure that it's a legal value, but not nec. one of the two values allowed by a).  Note, if you're clever you'll choose the dim's of you're height map carefully.  For example, if the dim's are both [0..127] then the above can be replaced with:

p := p and (16385)

which is much faster then using mod.

4)now instead of writing the rgb data from out ref. bmp to the display bmp we do something like this:

iy := p mod heightMap.width;
ix := p div heightMap.width;

destBmp[x,y] := sourceBmp[ix,iy];

Aaaaaaaaaaaaaand, that should about do it :)

GL
Mike
0

Author Comment

ID: 6329556
Ok, Excellent ! Finally got the refraction working well.

Thanx Mike !!!!!!
0

LVL 6

Expert Comment

ID: 6329842
Excelelnt, glad to be of service :)

GL
Mike
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

### Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the inâ€¦
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi databaseâ€¦
Six Sigma Control Plans
Introduction to Processes
###### Suggested Courses
Course of the Month6 days, 16 hours left to enroll

#### 732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.