Possible methods of specialised shadow casting and water reflection.

The setup I’m looking to support these effects is very specific: I’m using a parallel-projection isometric viewpoint, with global ambient lighting (well, as far as the viewer is concerned,) a global directional light source (again, as far as the viewer is concerned,) which I want to project shadows, and probably a large number of point/spot light sources with very limited bounds that are unlikely to intersect or even affect most of the world, which don’t need to cast shadows.

My thought for supporting shadow casting is essentially to render the world from the perspective of the directional light source, at a similar resolution to the main screen, with all textures disabled, to produce a pixel-by-pixel depth-map of the screen. Then, during the main rendering process, diffuse lighting would be disabled, or greatly attenuated, for points of greater depth in terms of the shadow-projection coordinates than those produced in the shadow-rendering pass. Y’know, because they were obscured.

Water surfaces in the engine I’m trying to develop would typically be completely flat, and the advantage of isometric projection is that differences in height can be compensated through simple translation, so my fudge solution would be render the world upside down at the same angle relative to the surface normal from the viewer’s perspective, then slap the generated image onto the water surface modulated with a nice ripple effect. This isn’t true ripple reflection, which would require many, many viewpoints rendered, but it’s close enough for aesthetic purposes.

While this is all probably doable, and reasonably efficient, I don’t know if it can be done without hacking the J3d source, so especially in that scenario some tips and pointers would be appreciated.

Depending on the complexity of the shadows you are looking for, you can create effects like this on a height map terrain:

http://members.aol.com/mnjacobs/newimages/OceanidumMons.jpg

The approach used here is to do a reverse ray tracing from each vertex to the light source, determining if the the light ray is obscured by something on the height map. The approach is described well here: http://www.gamedev.net/reference/articles/article1817.asp.

Mike

For water reflections, there may be some useful tips on this thread: http://www.javadesktop.org/forums/thread.jspa?threadID=12861&tstart=0 discussing how to create a mirror. I suspect you might want to do something similar and apply a wave filter (maybe something as simple as multiple sine waves) to the texture to give the impression of waves.

Mike

[quote]The approach used here is to do a reverse ray tracing from each vertex to the light source, determining if the the light ray is obscured by something on the height map. The approach is described well here…
[/quote]
Ah yes, that’s essentially a subset of line-of-sight checking on a terrain-tile basis. However, my intention was to be able to produce the shadows of individual unit sprites on the ground or other objects, not simply restricted to the terrain.
What I’d really like to know is whether you can set up a View from the same perspective as a directional lght source:

  • That pays no attention to texture colouring, diffusion, ambience, specularity or emission, but does notice transparency.
  • That will produce a pixel-by-pixel depth map of the surfaces (as in, distance from the light source according to some standardised coordinate system,)
    And if I can:
  • Modulate diffuse lighting application on a pixel-by-pixel basis, with reference to the 3d coordinates of the surfaces concerned.

[quote]…I suspect you might want to do something similar and apply a wave filter (maybe something as simple as multiple sine waves) to the texture to give the impression of waves.
[/quote]
I was thinking that. The problem is, rendering the entire scene from an alternate viewpoint for the sake of a surface that will most likely only occupy a small portion of the screen seems wasteful. I’d like to be able to mask out irrelevant areas to create a ‘rendering window’ in the same shape as the reflective surfaces, but I can’t think of a method using the api.

It’s nothing urgent, but I wanted to bring up the idea now to have plenty of time to flesh out possible techniques.

What you are getting to here is very much like the GPU shadow-casting algortihms you can see today in books like “GPU Gems.”

Two issues:

(1) These all require multi-pass rendering. Java3D cant do that today. (Its a feature the team knows is important. We hope to see in 1.5 though I dont knwo if they have comitted to that yet.).

(2) Be aware that shadow casting has a fundemental aliasing problem. It generates “jaggy” shadows depending on how far the ground is from the object being cast against. There are some interstign anti-aliasing techniques otu ther that have been tried, but your gettign toward the bleeding edge there. I’d highly recommend reading the first few GPU gems books sectiosn on shadows if you haven’t already.

quote These all require multi-pass rendering. Java3D cant do that today. (Its a feature the team knows is important. We hope to see in 1.5 though I dont knwo if they have comitted to that yet.).
[/quote]
I was thinking that if I switched to Immediate mode rendering, I could render the shadow map to an offscreen canvas, reset the textures properly, modify diffuse lighting as neccesary, then activate a standard rendering pass on the main canvas3D. That doesn’t give me the depth map, however. I’ve been considering porting to Xith3D so I can hack the source on OSX, but that could entail significant hassle if I try to use the code in an Applet. Assuming I’m even up to the task.

quote Be aware that shadow casting has a fundemental aliasing problem. It generates “jaggy” shadows depending on how far the ground is from the object being cast against. There are some interstign anti-aliasing techniques otu ther that have been tried, but your gettign toward the bleeding edge there. I’d highly recommend reading the first few GPU gems books sectiosn on shadows if you haven’t already.
[/quote]
Yeah, I’ve seen those in AoE3. I reckon that since I’m using a parallel isometric projection and the shadow render would be of roughly the same resolution as the main screen, jag artifacts would be pretty minimal. I’ll try and pick up one of those books if I spot them.

Good point, if you dont have a perspective transformation there migth not be an aliasing issue :slight_smile:

I explored this a bit ago for JNWN, including the idea of using immediate mode, and gave up deciding instead to wait for multi-pass. I forget why i gave up but after talking to the J3D guys I know I concluded trying to hack around it woudl be very difficult and labor consumign if not out-right impossible.

I believe I know a method that would work, at least for ground-shadows.
Using immediate mode, alter the appearance of all ground based polies to a texture where their position is immediately distinguishable- maybe a colour gradient between red and blue, say, to demarcate depth- and set everything else to a different colour (e.g. green,) no texture, 100% ambient/emissive so they stand out. Render the scene to an offscreen canvas.
Swtich back to normal appearance for non-ground polys, and switch the ground texture to the standard form. Then alter the ground texture to simulate shadows by transforming it’s x/y/z coordinates (which you will know,) into shadow-projection coordinates, and checking if the colour at that point on the offscreen canvas matches that generated during the shadow pass. Voila. Ground shadows. Then render normally to the main screen.
The difficulty lies in being able to dynamically alter ground texture like this. Which is merely tricky, not impossible. You might be able to use the AlternateAppearance class…

EDIT: Goddamnit. I just realised all I need is the Depth Buffer, which I can’t access. Any relatively simple way to hack around that?

Froma discussion we just had at work, I thin kthe answer is no, but Ill double check.

The good news is that, if i understood what I was listening to, the J3D guys have it marked as a known issue to be addressed (but no i dont knwo when)