Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Calin Leafshade on Tue 22/06/2010 14:57:41

Title: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 14:57:41
So I've been thinking about reflections on uneven surfaces and how to model them and I can't quite get my head around it.

Now I know this has been discussed before and it was decided it would be very slow.. but that was modelling distortion on a whole background.. what if it's just a characters reflection that's modelled?

Basically I see it like this:

1, You have a greyscale reflection/height map for your surface,
2, you project a reflection onto that surface,
3, then you somehow 'transpose' that greyscale reflection map onto the position values of the sprites pixels
4, draw the sprite

I can handle steps 1,2 and 4 but step 3 is puzzling me a little :P

It doesnt have to be very accurate since we are talking about a 2D plane with a static camera, but it has to look convincing.

any help?

SteveMcCrea, GarageGothic, Khris, I'm looking at you.
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 15:32:20
(Doesn't Wintermute (http://forum.dead-code.org/index.php?topic=4353.msg25564#msg25564) support that kind of thing through shaders, Calin? ;))

Well, it doesn't make sense to talk about height maps unless you have some sort of 3D projection algorithm implemented (even just an approximated one), since a surface facing the player straight-on wouldn't show any distortion. You don't say whether this is for vertical or horizontal reflections but in either case a per-pixel displacement of an image would be similar to rendering a voxel landscape. I actually did this in an unfinished MAGS game, so it's possible but quite slow, mainly due to the GetPixel function.

It would help if you go into a bit more detail on what you're trying to achieve. If you could settle for displacement in vertical or horizontal strips (or both at once even) rather than per-pixel it would improve performance a lot, and even more so if the distortion could be math-based rather than using an image heightmap.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Wyz on Tue 22/06/2010 16:16:20
.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 16:55:00
Quote from: GarageGothic on Tue 22/06/2010 15:32:20
(Doesn't Wintermute (http://forum.dead-code.org/index.php?topic=4353.msg25564#msg25564) support that kind of thing through shaders, Calin? ;))

Don't judge me.. I want those damn alpha channels :D

Anyway, back to the task at hand!

basically i want to create a similar effect to this:

(http://img404.imageshack.us/img404/2497/comp1y.gif)

so pixels are shifted based on the luminance of the displacement map (in this case you can see the map used but that doesnt always have to be the case)

is it just that simple? Sample the colour value of the dis-map pixel and shift the character pixel depending on that? i.e 128 grey = no shift, 0 = full shift left and 255 = full shift right.

..im confused again..


Title: Re: [More Mathematics] Sprite Displacement
Post by: Monsieur OUXX on Tue 22/06/2010 16:55:36
Quote from: GarageGothic on Tue 22/06/2010 15:32:20
It would help if you go into a bit more detail on what you're trying to achieve.

Yes, describe exactly what kind of processing you plan to apply onto the pixels, depending on the displacement map (I shall call it that way because, as mentionned, it's not really a height map) :
- Are you moving whole rows of pixels horizontally to create some sort of "lake reflection"? (by the way, there's already a module doing that
- Are you moving each single pixel arbitrarily, based on the displacement map, to acheive some sort of distorted relection?
- Are you moving every pixel following a certain direction (angle) to achieve a fake 3D efect, voxel-style? (in that case it'd make sense to talk about a height map)

Let us know.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 16:56:44
Quote from: Monsieur OUXX on Tue 22/06/2010 16:55:36

- Are you moving each single pixel arbitrarily, based on the displacement map, to acheive some sort of distorted relection?


That one.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Monsieur OUXX on Tue 22/06/2010 16:59:33
Quote from: Calin Leafshade on Tue 22/06/2010 16:55:00
basically i want to create a similar effect to this:
so pixels are shifted based on the luminance of the displacement map

OK, so You're indeed in the second case I described.
Well, it sounds like your solution works (128 grey = no shift, 0 = full shift left and 255 = full shift right). Yes, I'd say it works.

Also, I believe that it will work better if you move the pixels in the same direction (horizontally, diagonally, vertically...) as the direction you chose to generate the kind-of light source when you created the displacement map. Otherwise the effect will work but will look awkward. But I might be wrong.

What do you think, people?


EDIT:  I believe that, to achieve the full effect, you might have to proceed as follow:
You might have to evaluate the "flatness" of each displacement map's pixel. It would NOT be ONLY about "how high" it is, but about "is this pixel facing the viewer?".
For example:
- if a pixel on the displacement map has 2 neighbours of the same color, it means you're in a area of the map that perfectly faces the viewer.
- However, if the pixel on the left is darker, and the pixel on the right is lighter, then it means that this area is not flat, and faces left. Similarly, if the pixel on the left is lighter and the pixel on the right is darker, then this area of the displacement map faces right.

This is equivalent to evaluating the direction of the NORMAL of each pixel of the displacement map.
You might have to do that in order to REALLY know of what amount you should displace the pixel up or down.

then again, I'm not sure if it's really necessary in your case, even though it is interesting to achieve cool effects.
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 17:17:43
I think you could build on the code you already used for the puddle reflections in McCarthy, or possibly Steve's underwater module, but instead of random/sinal distortion simply get the displacement values from the image map. If you're happy with displacement along a single axis (of any angle) that should be enough to achieve the effect. You may have to settle for a lower resolution on the reflection than in your example image though (e.g. displacing blocks of 4 pixels at a time), as long as things are the character is moving I doubt anyone would notice the difference.

Edit: I agree with Monsieur OUXX' edit, both on the technical part as well as his assumption that normal-based displacement would be overkill. The true art of game programming isn't simulating reality but creating an illusion of it with a fraction of the resources, which is something that took me a many overly complicated effect modules to learn :).
Title: Re: [More Mathematics] Sprite Displacement
Post by: Jim Reed on Tue 22/06/2010 17:20:34
It seems simple.
To bad it's hard to explain. =)
Catch me on irc, it's easier there.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 17:41:27
ok so, this is what I have so far

http://www.thethoughtradar.com/AGS/Distortion.zip (AGS 3.2 Final 5)

(edit: actually you can see the effect better with this slightly modified version http://www.thethoughtradar.com/AGS/Distortion2.zip)

It actually distorts pretty well and looks fairly cool except for the whole pixellyness of it.

so how could I fix that? some kind of bilinear filter?

...

...how do i do that?


EDIT: also how does the AGS colour system work? is there a function to convert it to RGB values?
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 18:09:49
No built-in function to get RGB values, but here's my script for it:


enum eRGBComponent {
 eRed,
 eGreen,
 eBlue,
 };

function GetRGBComponent(int color, eRGBComponent component) {
 if (component == eRed) return 8*(color/2048);
 if (component == eGreen) return 8*((color%2048)/64);
 int b = (8*((color%2048)%64));
 if (b > 255) return (8*(((color%2048)%64)-31))-1;
 return b;
 }


The test looks good to me. I don't think the reflection appears much more pixelly than the character itself, but you could always draw the final reflection multiple times slightly offset and at different transparencies to smooth out the edges a bit.

Edit: Cleaned up unnecessary "if else" statements in code.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 18:33:30
thanks GG, mind if i add that to the Util module? Seems like a good candidate.

and here is my latest effort with some kind of filtering.. It looks very cool but I feel it could be better.

http://www.thethoughtradar.com/AGS/Distortion3.zip

edit: some reports of frame rate would be nice - Compiled version for the curious http://www.thethoughtradar.com/AGS/Distortionbin.zip
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 18:45:43
Sure thing, Calin. I can't promise it's flawless, because it's a really bare-bones version of an earlier script that had many more conditionals (to map the first 32 palette slots correctly), but it has worked for my own purposes.

Love the effect in the new build, but the framerate is struggling between 24 and 33 in windowed mode on my 2.4GHz centrino. Though I do have several other applications open.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 18:46:53
struggling? Direct Draw or D3D mode?

it should be easy to refine and improve upon.. i use getpixel an awful lot.. i should probably just dump the values into an array.
Title: Re: [More Mathematics] Sprite Displacement
Post by: DoorKnobHandle on Tue 22/06/2010 18:51:37
No framerate problems here but my computer is pretty decent at 2x3.14Ghz intel in window mode while rendering a video too. :D

Looking very nice.
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 19:01:28
DirectDraw mode - I didn't think it would make much difference since all the DrawingSurface stuff happens in the CPU in either mode, but Direct3D gives me 35-36FPS. Probably full screen would bring it closer to 40, but my Nvidia drivers prevent me from testing that without shutting down Firefox, so it'll have to wait.

And yeah, GetPixel is the most likely culprit in terms of performance. Reducing the sampling resolution should help loads. For my per-pixel lighting module the performance/quality sweet spot seemed to be around 4 pixels, but that was a hi-res game so even sampling every second pixel would probably boost your game well above 40FPS.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 19:08:41
the way i've done the whole thing is really really messy but the actual calcs are really not that intensive so i'm pretty sure I can get 40fps on most modern systems
Title: Re: [More Mathematics] Sprite Displacement
Post by: Crimson Wizard on Tue 22/06/2010 19:16:24
Omg, freaking cool!
Can I use this in my game? Pleeese?  ;D

Okay, technical stuff.
Run on laptop with AMD Turion 2.0 Ghz, video ATI Mobility Radeon X1300 (128mb)

DirectDraw 5
Windowed mode, scaled x3 (960x720), FPS 37-41
FullScreen mode, scaled x2 (640x480)*, FPS 38-41

Direct3D
Windowed mode, scaled x3 (960x720), FPS 40 (stable)
FullScreen mode, scaled x2 (640x480)*, FPS 40 (stable)

* for some reason graphics driver could not run fullscreen with 960x720 resolution
Title: Re: [More Mathematics] Sprite Displacement
Post by: Jim Reed on Tue 22/06/2010 20:48:31
Quote from: Crimson Wizard on Tue 22/06/2010 19:16:24
freaking cool!
Ditto that. Heck, if you placed the distortion map precisely, and paint the distorted sprite black, but semi-transparent, you can have a real time shadow!

Calin, you da man!
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 20:56:25
Quote from: Jim Reed on Tue 22/06/2010 20:48:31Heck, if you placed the distortion map precisely, and paint the distorted sprite black, but semi-transparent, you can have a real time shadow!

Not one of the more efficient nor flexible ways to do realtime shadows, but if you wanted a shadow on, say, a rough cave wall, the displacement map technique could definitely be added on top of a straightforward shadow renderer.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 21:17:51
ok how's this for speed:

http://www.thethoughtradar.com/AGS/Distortionbin2.zip

I've dumped the displacement map to an array so it might be quicker.

but i have a feeling it's my multisampled rendering that is causing the slowdown.. I need to crop the reflection sprite somehow (which is currently the size of the whole screen);
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Tue 22/06/2010 21:35:17
Getting worse fps now, actually - around 22-24. Not sure that the array makes it that much faster (tried it for my voxel game but the performance increase was negligible compared to the drawback of increased room loading time). When you used GetPixel instead of array, did you keep the displacement map DrawingSurface in memory or recreate the DynamicSprite every loop?

Edit: Just looked at your code (next to last version) and I think you could gain some extra frames by not drawing directly to the background but to a smaller sprite displayed as an Object/Character. Also, use the red RGB component instead of blue if the image is grayscale anyway since it requires fewer calculations.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Tue 22/06/2010 21:59:46
hmm, I've added some things to the code that are probably not very efficient but no matter what I take out I can't get my processor usage to change.. it always sticks around 10%, even if i take out the multisampling (which i thought would be the biggest hit)

heres another slightly optimised version,

http://www.thethoughtradar.com/AGS/Distortionbin3.zip

plus the source if you think you can fix it:

http://www.thethoughtradar.com/AGS/Distortion3src.zip

EDIT: I've tested this on a 10 year old processor and get a full 40fps with only 40% processor load so I dont see why your centrino should struggle GG.
Title: Re: [More Mathematics] Sprite Displacement
Post by: GarageGothic on Thu 24/06/2010 22:19:58
Calin, I discovered what was going on. Turned out that my laptop power savings mode was limiting the CPU use to 50% even when plugged in. Not sure how long that setting has been active (most other games have worked alright, but I did begin to consider reinstalling Windows). Once I changed the setting to 100% I get a consistent 40FPS in your latest test version. Sorry if I caused you to waste time on unnecessary optimizations. :-[
Title: Re: [More Mathematics] Sprite Displacement
Post by: Dualnames on Thu 24/06/2010 23:23:18
Also, no trouble here, the whole thing is very smooth. Perhaps adding objects would be a better way to test, unless of course that's the actual room.
Title: Re: [More Mathematics] Sprite Displacement
Post by: SSH on Fri 25/06/2010 03:46:34
DOes this have perspective distortion on the shadowm, too?
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Fri 25/06/2010 11:33:46
not really, no.

In the latest version the distortion sprite is shifted in relation to the characters distance from the centre of the screen (or the horizontal component of the vanishing point.)

I think what i need to do is make a 'map' of nodes and distort that map and then split the character sprite into a series of squares and distort those squares in relation to the map. This should stop the pixelly nature of the reflection but i'm not exactly sure how to distort/stretch a sprite in that way.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Monsieur OUXX on Fri 25/06/2010 12:02:35
Quote from: Calin Leafshade on Fri 25/06/2010 11:33:46
what i need to do is make a 'map' of nodes and distort that map and then split the character sprite into a series of squares and distort those squares in relation to the map. This should stop the pixelly nature of the reflection.

I don't understand.
Title: Re: [More Mathematics] Sprite Displacement
Post by: Calin Leafshade on Fri 25/06/2010 12:20:41
ok, well:

currently the code samples the colour value beneath the sprite to be distorted and *moves* that pixel according to however much it is to be displaced. Now, because the pixel is just moved it creates two unwanted side effects:

Firstly it creates gaps between pixels. If 1 pixel is move 2 pixels to the left and the next one is moved only 1 pixel to the left then you have a gap between them.
secondly it allows two pixels to be moved to the same spot with the second pixel overlapping the first.

Now, if i created a grid of imaginary points the same size as the sprite and distorted those points I could use the data to cut the sprite into a series of squares (say 2x2 or 3x3) and distort those squares by resizing them by moving their 4 corners and letting the engine interpolate the gaps. Since i resize them in relation to the grid there would be no overlap and no gaps because pixels are not *moved* they are *stretched*
Title: Re: [More Mathematics] Sprite Displacement
Post by: Jim Reed on Fri 25/06/2010 14:13:35
That sounds like a good idea. You can resize them by the maximum displacememt possible. So if you cap the distortions at 3px max, you can use 3x3 squares for instance.