• 11
• 9
• 10
• 9
• 10
• entries
235
509
• views
172302

# Navigation & Water Part 3

127 views

Well, I fixed some more bugs in the navigation system yesterday, and successfully got an enemy to follow my character down some stairs. Unfortunately, he wouldn't follow the player up the stairs.

I believe the problem comes from the fact that, although the new technique of using physically simulated spheres is closer to reality, it still does not totally match what the character can really do. When you get a path from the A* routine, it's often full of sharp corners. You need an algorithm to smooth it out somehow. My areas tend to be large, often skinny reactangles, so moving from one to another can appear awkward. What I do now is to let the enemy skip ahead one or two nav points. This isn't ideal, b/c if the nav points are small, he can really still go out of his way when there is a straighter path. This is one of the tradeoffs of using large nav areas - the paths need more complex smoothing than a fixed grid. The process of smoothing can lead to invalid paths, which requires a real-time steering controller to avoid pits, bumping against walls, etc.

Another problem is that the paths are not necessarily valid for different-sized characters. Several parts of the code rely on using some size for the character, including the rectangularizer, the portalizer, and the steering code. The upshot of this is that we will need to standardize on just a few sizes of characters, probably three : small, medium ( human ), and large. Then I will have 3 navigation structures, one for each size.

I am going to wait on further changes to this until I have the capsule vs triangle code implemented. Rather than use ellipsoids, which appear to be fairly hard to intersect with other shapes when they can rotate, we are going to use oriented capsules instead for the character models. This should also match the bbox of the characters better.

Then, once that code is in place, I will use the actual character movement code to test the navigation - so I will break that piece of the code out of the session::tick() function and into its own routine, so it can be called separately. I will basically add a routine that will simulate a capsule as an upright humanoid entity, and allow it to 'walk' from voxel to voxel, then look at how long it took to arrive, which will give me a cost for the voxel, and whether it made it or not, which will tell me where the area boundary is.

I wonder how much complex 3d games hand-tweak their navigation systems - I'm starting to suspect quite a bit. I met someone a while back who claimed that EA has full-time positions for ppl placing navigation points in game maps...

Water Part 3

Ok, last time we had the water refracting nicely, but the clear disconnect between the pixel-level fresnel & reflection vs the vertex-level refraction was not going to cut it. Perhaps scaling the texture up so that it matched the tessellation a bit better would have helped, but I decided do go whole-hog with per-pixel level refraction.

Now, for planar reflections & refractions, there is really no better choice than old EMBM - that's right, DirectX6-era technology is still the coolest real time effect in games. Varialtions on Environmental Bump Mapping are used for heat distortion effects in Doom & FarCry, as well as water in most modern titles.

The idea behind fixed-function EMBM is to :

a) sample a bump map texture to get 2 2d offsets

b) put these 2d offsets through a 2x2 constant matrix. This lets you rotate and scale the offsets.

c) after the matrix, add these offsets to the original 2d interpolated texture coordinates

d) sample a 2d texture with these resulting texture coordinates

Nowadays, EMBM is usually done in a vertex shader, where you can effectively specily the 2x2 matrix on a per-vertex basis instead. This lets you do tricks like fade out the bump mapping on water at the horizon.

It turns out the shaders for doing per-vertex refraction & per-pixel refraction are almost exactly alike, so for those playing along at home, I recommend getting the per-vertex method up & running first, then saving that version, & switching over to per-pixel afterwards.

The difference is mainly in the pixel shader - where you perform 2 'texbem' instructions, one for the distorted version of the underwater scene, and the other, for a fake reflection map ( discussed later on ).

Here is my shader for the per-vertex version :

ps_1_1tex t0  // mist / water layer 0tex t1  // normal  back buffer texturetex t2  // distorted back buffer texturetex t3  // skybox reflectionmul r0.rgb, v0, t3+mad_d2 r0.a, v0.a, v0.a, v0.amul_sat r1.rgb, t2.a, t2mad r1.rgb, t1, 1-t2.a, r1add_sat r0.rgb, r1, r0

And here is the version with per-pixel refraction :

ps_1_1tex t0  // mist / water layer 0tex t1  // normal  back buffer texturetexbem t2, t0  // distorted back buffer texturetexbem t3, t0  // skymap reflectionmul r0.rgb, v0, t3+mad_d2 r0.a, v0.a, v0.a, v0.amul_sat r1.rgb, t2.a, t2mad r1.rgb, t1, 1-t2.a, r1add r0.rgb, r0, r1

v0 holds the liquid's diffuse color ( used to tint the water ) times the water's sunlight shadow term.
v0.a holds the E.N fresnel term

Yes, the water has a shadow term, which is very important for an indoor engine. In my case, the water does not receive dynamic shadows, but does
store the sunlight shadow term calculated at level load time, at each vertex. This term is also averaged between neighboring vertices to smooth
it out and eliminate any gouraud artifacts.

Next time I'll talk about sunlight on the water, the textures I used, and the fake reflection mapping.

Here is my first shot with EMBM refraction. It was just a noisy texture, so it doesn't look like water, but could be a cool force-field effect.

And here is one of the first shots with a fake EMBM reflection texture applied for the sunlight.

The sunlight reflection texture is just a round falloff, which is easier to see with still water.

There are no comments to display.