Water
Water
So for those of you curious I’m throwing down some water rendering magic. Not to mention real-time environment cube mapping. Behold the result.
So it’s broken and the ocean needs some motion (pun fully intended). I also may be slightly sleep deprived… but onwards and upwards.
Shadows are EVIL
Shadows are EVIL!
Okay above you see rough and blurred. The rough pass uses a single sample against the depth buffer. Those bloody pixels are a result of the resolution of the shadow map.
The blurred insanity is a shadow method called PCSS, based on the White Paper, “Integrating Realistic Soft Shadows into Your Game Engine” by Kevin Myers, Randima (Randy) Fernando, & Louis Bavoil. Sadly some of there stuff uses Shader Model 4 so I did my best approximation.
Not happy with either method… pulling my hair out.
To Debug it… Draw it
To Debug it… Draw it
Many people will tell you this but whenever you have a problem try to visualise it. This can be applied to almost everything (except cases where visualisation is a constraint, think advanced maths and quantum). So above you see the debug frustum.
Well after fighting with all these various problems I’m thinking to myself… I need to double check my Frustrum. Five minutes to write and BAM problem is instantly visible. The problem I was debugging for 5 hours solved in 5 minutes.
Printf & Debug Draw rocks.
Problem: Shadows giving strange LightViewSpace results
Well the problem manifested in many ways. I was debugging shaders and tweaking render targets. Not to mention twiddling the depth bias so often that it was indecent.
The problem was two fold. Firstly the sun view & position didn’t match up. The result of a quick hack to get the sun in the right place, hacks bad. The second issue was todo with the scene bounds.
The view matrix is built with a look-at call. Well the key is that the centre of the bounds must be equal to the look-at target. Why is this? Well draw some random shapes on an A4 page. Now draw a circle which contains all those objects. Now measure the radius of the circle and draw a square at the centre of the page with double that length per side.
You see the problem, unless the circle is at the centre of the page their will be bits of it outside of the box, which means they won’t be shadowed.
So you compensate for offset and increase the radius. To do this instead of measuring the radius of the circle measure the distance from the centre of the page to the furthest point of the circle.
Before you ask we can’t move the box from the centre of the page as that would change the angle the light was coming from.
Onwards and upwards.
The shadow is low quality due to…
Wooot!
Progress, the shadow is low quality due to PC card limits. I need to add some bias to avoid flicker, and smooth off the edges to get soft shadows.
Almost
Full Screen shadows almost done. Had to run. Just caught last bus home. Some weird filming on the lot.
More tomorrow.
Shadows and Reworks
Shadows and Reworks
So after a lot of thought and planning yesterday I set about implementing soft shadows using shaders tonight.
Sadly this meant I needed to re-haul the entire scene manager and packer to support texture swapping, and effect management. I also had to write a big ass shader to do several things, and optimise.
That’s done, now all I need to do is add the Shadow Render pass and it all should work. I’m going to miss the last bus home, so I gotta run.
Shadows & Light
Lights Camera & Action
Well lighting & shadows are a complex bag of trickery and maths.
Basic Lighting is simple. Take a book outside into the sun now rotate the bugger around and throw it. You will notice the amount of light on a surface can be measure as an angle between the light direction (from the sun) and the facing direction of the surface. A very cheap and easy calculation we love, called dot product.
Now shadows are more complex. Light as a physics based thing in reality is a crazy thing which drove Einstein insane. For instance do you know light is affected by gravity so it actually bends around objects forming a very distinctive halo effect. So not only is it a ray cast but it’s a particle/wave which is affected by gravity fields. They also split up and bounce all over the place.
Now in games we fake it, cause those calculations are really expensive, and most times we care more about whether a bullet hit a guys head.
Bake It
A cheap and simply trick is to back the shadows. This works well if the lights & geometry don’t move much. Even in AAA games with more advanced systems, baked light maps do a lot of the heavy lifting.
To bake it we basically do the calculation before the game runs. The simplest form is a flat planar map, some bake a projection map and some cases even bake shadow volumes. We can animate the baked textures and get some awesome effects.
Fake It
Okay so we have this bad guy, race car or some other object in the world. Well we can forgive a lot with our suspension of disbelief. What if we glued a “blob” shadow to the feet of bad guys or race car.
You would be amazed how many games use this system to optimise thing and it looks great.
Flatten It
Well if we simplify light and ignore the bending, bouncing, and craziness of it, then we can treat it as a straight line from the light. Now we like planes, planes are really nice simple flat things.
Okay so now we have this thing called the projection matrix which is part of the matrix of projecting a 3D object into a 2D image. Well if we use the same trick we can clone an object, then squish it into a projection and render it all black. We have a shadow, Peter Pan Style.
Deferred Volume
Okay well know in reality we need to drop shadows onto complex geometries. Now we also have this wonderful shader pipeline. Before we render the scene we render the entire world from the perspective of the light (as we would the camera). We then grab the depth buffer and save it.
This needs to be done once for each light.
Now this makes an image of how far the beam of light travels. Which we pass in to the next render pass, along with light matrix. Now if we take a point in space transform it by the Model-View-Projection as normal. Also Transform is by Model-Light-Projection. Then we compare the MLP read-out against the baked texture we can tell if the light reaches that point or not.
Another way of doing Volume Shadows is to use Stencil Buffers, this is the traditional way to do things and how most shadow volumes have been done in the last 10 years.
Day & Night Cycle
Day & Night Cycle
Woot! Not only did I get a pretty awesome Sky-Sphere in place but I also managed to knock up a day/night cycle. I also cleaned up the shaders and have global lighting in place.
Found an awesome tut, and manage to knock the shader up from that.
Next thing is to look at shadows, but don’t you think that is preeety.
Coupling Issue solved with Interface
Ye gods captain, PROGRESS.
After the dismal run around the pointlessness I have actually made some progress last night and today.
- Coupling Issue solved with Interface
- Island has day/night cycle
- Shop Blimp interior & exterior modelled
- Blimp added to world
- Add a reliable help to translate between tile and world space
- Started work on Sky Box
Coupling Issue
Okay so we don’t want the model (island & prop data) coupled to the view (scene graph, animations, models). Well the solution was to give every node in the scene graph a user data element which had an interface.
The core functions being, Update & Pre-Render. Further functions and event handles can be added to the interface to handle animations and the like. The interface is the façade which prevents tight coupling. Neat and clean, kicking myself for not seeing this solution weeks ago.
Sky Box
My reason for posting, indirectly. I waster the last hour or so trying to generate normal & height maps for clouds. Reading up on things I already knew how todo if I stopped and thought for a second. The moment I saw my folly I stopped to write this to break me out of it.
I will now grab some food then hopefully not be stupid.
My Kingdom for a Team
My Kingdom for a Team
What’s the best tool to explore and solve problems? Explain it to someone else. It’s good enough for Sherlock Holmes and its good enough for me. I hate working in isolation because you don’t need to justify or explain yourself to people. So massive gaping holes form in your logic.
Long story short is explain in the picture. WRONG! It took me a few experiments to realise this but I finally did.
- Radial Menus are conceptually complex
- This makes them good to manage large amounts of choices
- ONE BUTTON!!!
Okay this game is focused on being simple and broad age range according to the brief. So one button is good. This combined with the mantra, “You can do what Frank can do”. A break through moment I had on the bus which confused many people last week.
So whenever you push the button on something you activate the action Frank would. The only additional actions are, Highlight, Pick-up (optional) & Customize(optional).
When interacting with Frank the actions are Praise / Scold, and Pick-up.
Now there are other actions. Like looking at stats, buying things from the shop, selling things, ect… But I realised I should bake these into the world as objects. That way they are easier to identify and interact with (kids prefer less abstraction). They are self-contextual and tbh look cooler.
The Other Problem
So what have I been wrestling with all day other than my own stupidity. Well a design choice and some coding issues.
The design choices involve things like.
- Camera Facing / World Orientated (see last post)
- Facing: Cleaner Smoother Fonts (made less of an issue by HD)
- World: Feels more part of the world
- World: Able to animate in 3D and look cooler (sounds stupid but cool is a test)
- Floating above, fixed location or surrounding
Anyway they are game specific and rather dull. I want to talk about a code issue.
You want HOW MANY!
Beginners and hackers will always dynamically allocate verts and primitives. THIS IS BAD! I know it’s convenient but it’s wrong. Resources should be compiled and processed by the content pipeline or equivalent. This allows unified buffers, optimisation of vertex declarations and lots of other neat things which make the Tech Trolls happy, otherwise they club you with a big stick.
This applies to the UI because well I was looking at generating the menu based on X choices which means generating verts based on splits… blah blah blah.
Caveat: Rules are made to be broken! Truly dynamic objects, like water simulations for instance may need to be altered. However try move choices like vert declarations and number verts to pack time. Understand why you are breaking the rule before breaking it. Remember over assigning a large pool on a loose fit is often better than a dynamic solution which fits better but restrains you more.
Wow that was a long post.