Shadows David Luebke University of Virginia Shadows An important visual cue, traditionally hard to do in real-time rendering Outline: – – – – – – – Notation Planar shadows Soft shadows Projective shadows Shadow volumes Shadow maps Shadow optimizations Notation Light source – Point vs area Occluders & receivers – Identify ahead of time? – Self-shadowing? Shadow – Umbra – Penumbra Soft vs hard shadows Planar Shadows Old trick: project the occluder geometry to a plane and render over ground plane – Can do with a matrix – Z-bias issues – Semiopaque shadows harder Stencil and Z-buffer tricks – Another option: generate textured rectangle Problems – Light source inside object (Antishadows) – Only planar receivers no self-shadowing Planar Soft Shadows Basic idea: – Sample light source multiple times, average results (accumulation buffer) into a texture Gooch et al: move plane up and down – Nested shadows fewer passes Projective Shadows Render scene from light’s point of view – Render all occluders as black – Can turn off depth buffer etc Project onto receiver polygons using projective texture mapping Works for curved surfaces Designer separates occluders and receivers no self-shadowing Shadow Volumes Basic idea: – Create polygonal objects to represent shadowed volumes – Make clever use of stencil buffer so that these objects affect what lighting is done Stencil Buffer The stencil buffer has been around since OpenGL 1.0 – Basic idea: provide a per-pixel flag to indicate whether pixels are drawn or not – But… – Let that flag be an integer (usually 8 bits) Usually shared with depth buffer – And let drawing operations increment or decrement the stencil buffer based on different events Always, depth-pass, depth-fail, etc. Shadow Volumes Details of the basic algorithm: – Compute shadow volumes View-independent! – Clear stencil buffer – Render the scene without diffuse/spec lighting – “Render” front faces of shadow volumes Turn off color, depth updates (but leave depth test on) Visible polygons increment pixel stencil buffer count – “Render” back faces of shadow volumes Turn off color, depth updates (but leave depth test on) Visible polygons decrement pixel stencil buffer count – Render scene with only diffuse/spec lighting Only update pixels where stencil = 0 Shadow Volumes Refinements (see book, next slides) – NV30, XBox supports signed stencil addition Two-sided lighting determines whether polygon adds or subtracts 1 from stencil buffer One-pass algorithm! But a little slower in practice? – What if you’re inside a shadow volume? Invert meaning of stencil test – What if near clip intersects shadow plane? Carmack, others: use z-fail test Clever extensions in NV2X help this idea out – Creating shadow volumes: vertex program! ATI: clever degenerate-edge trick again Shadow Volumes Advantages: – Robust – Self-shadowing – GPU Disadvantages: – Can be geometry limited Stencil polys Multi-pass scene geometry – Can be fill limited – Stencil test – per pixel expense – Hard shadows Shadow Volumes Will return to the gruesome details shortly Shadow Maps Idea: – Render scene from light source, read Z-buffer – Result: discretized image (shadow map) telling distance of objects to light source – Render scene normally At each pixel, calculate distance D to light Compare to distance S stored in shadow map If D=S, surface lit by light, else in shadow Shadow Maps The basic algorithm (w/o hardware) – Render scene with ambient lighting only – Read Z-buffer, transform values into coordinate system of light – Use comparison to set alpha buffer – Render w/ diffuse and specular components, multiplying by alpha Shadow Maps Advantages: – Hardware-accelerated general shadow algorithm – Supports self-shadowing – Cost is linear in # lights and # polygons Disadvantages: – Self-shadow aliasing Biasing and other techniques can help, but not fix – Shadow map resolution critical! Solution: perspective shadow maps