Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Render a height map on a texture ?

Posted on 2001-07-19
9
Medium Priority
?
424 Views
Last Modified: 2010-04-06
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
Comment
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
9 Comments
 
LVL 6

Accepted Solution

by:
edey earned 240 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

by:gemarti
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

by:CyberKnight
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 6

Expert Comment

by:edey
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:

shadeRatio := (deltaX+deltaY)/2;

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

shadeRatio := 1-(shadeRatio*sqrt(1/3));

and so:

r := r*shadeRation;

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

by:CyberKnight
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

by:CyberKnight
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

by:edey
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

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

Thanx Mike !!!!!!
0
 
LVL 6

Expert Comment

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

GL
Mike
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

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

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

Join & Ask a Question