Skip to main content

Jet: Cascading Shadow Maps

This is a demo of my homegrown cascading shadow mapping.  Notice how the shadows remain sharp at all distances.  This is currently using 4 2048 byte shadow textures, but it looks similar with 1024 byte textures. Cascading shadow maps work by dividing the view frustum into sections, and assigning a shadow texture to each section.  This allows shadows to be rendered at great distance without loss of visual fidelity during close-up shots of a shadow.  The great thing about shadow mapping is that you get self-shadowing for free.

The performance isn't too bad either.  This demo ran at 270 frames per second on my EVGA 8800 GTS, with normal mapping and specular mapping.  Modern GPUs have really great texture lookup performance: the shader I wrote for this demo performs 7 texture lookups per pixel (1 for normal mapping, 1 for the diffuse map, 1 for specular mapping, and 4 for shadow mapping).  A previous iteration of this demo (with only 1 shadow texture lookup) ran on an Intel GMA at 35 frames per second, which isn't bad for an integrated graphics card.

The performance of this demo is fill-rate bound.  This is actually good, because it means I have plenty of vertex processing and CPU overhead to work with.  Also, most of the fill-rate-intensive shader work is done already so I don't really need anymore fill-rate.

My next couple of goals: multiple shadow-casting lights, spotlights, and point lights.

Comments

Popular posts from this blog

Lua-Style Coroutines in C++

Lua's implementation of coroutines is one of my all-time favorite features of the language. This (short) paper explains the whole reasoning behind the Lua's coroutine implementation and also a little about the history of coroutines. Sadly, coroutines are not supported out-of-the box by many modern languages, C++ included. Which brings me to the subject of this post: Lua-style coroutines in C++! For those who don't know (or were too lazy to read the paper!), Lua's coroutines support three basic operations: Create: Create a new coroutine object Resume: Run a coroutine until it yields or returns Yield: Suspend execution and return to the caller To implement these three operations, I'll use a great header file: ucontext.h. #include <vector> #include <ucontext.h> class Coroutine { public: typedef void (*Function)(void); Coroutine(Function function); void resume(); static void yield(); private: ucontext_t context_; std

Criterium: Road Screenshots

I finally got around to making the road tool for Criterium.  The tool has two parts: a Java application that lets you paint roads on the 2D heightmap texture, and a Ogre-based tool that automatically converts a 2D path into a 3D mesh.  The Ogre-tool queries the heightmap to get the height of the road, and performs smoothing so there are no discontinuous road segments.  I've posted a screenshot below.  Also, I've got my GIMP terrain shown in the screenshot.  I generated it using random noise and the GIMP lightmap filter.

Jet: Particle Systems

Here's a demo of the new particle systems I've implemented in OpenGL.  Performance is much improved over the DirectX version.  Particles are initialized in C++ rather than in Lua.  Also, I use two particle buffers and swap between them, rather than using one buffer per particle system.  Anyway, here's a video capture: