Слайд 1
The Rendering Technologies of
Слайд 2Thin G-Buffer 2.0
For Crysis 3, wanted:
Minimize redundant drawcalls
AB details on
G-Buffer with proper glossiness
Tons of vegetation => Deferred translucency
Multiplatform friendly
Слайд 12G-Buffer Packing
World space normal packed into 2 components (WIKI00)
Stereographic projection
worked ok in practice (also cheap)
Glossiness + Normal Z sign
packed together
Слайд 13G-Buffer Packing (2)
Albedo in Y’CbCr color space (WIKI01)
Stored in 2
channels via Chrominance Subsampling (WIKI02)
Слайд 14Hybrid Deferred Rendering
Deferred lighting still processed as usual (SOUSA11)
L-Buffers now
using BW friendlier R11G11B10F formats
Precision was sufficient, since material properties
not applied yet
Deferred shading composited via fullscreen pass
For more complex shading such as Hair or Skin, process forward passes
Allowed us to drop almost all opaque forward passes
Less Drawcalls, but G-Buffer passes now with higher cost
Fast Double-Z Prepass for some of the closest geometry helps slightly
Overall was nice win, on all platforms*
Слайд 15Hybrid Deferred Rendering (2)
Deferred (Red) + Forward (Green)
Слайд 16Thin G-Buffer Benefits
Unified solution across all platforms
Deferred Rendering for less
BW/Memory than vanilla
Good for MSAA + avoiding tiled rendering on
Xbox360
Tackle glossiness for transparent geometry on G-Buffer
Alpha blended cases, e.g. Decals, Deferred Decals, Terrain Layers
Can composite all such cases directly into G-Buffer
Avoid need for multipass
Deferred sub-surface scattering
Visual + performance win, in particular for vegetation rendering
Слайд 17Thin G-Buffer Hindsights
Why not pack G-Buffer directly?
Because we need to
be able to blend details into G-Buffer
Would need to decode
–> blend –> encode
Or could blend such cases into separate targets (bad for MSAA/Consoles)
Programmable blending would have been nice
Transparent cases can’t use alpha channel for store*
sRGB output only for couple channels or all
Would allow for more interesting and optimal packing schemes
While at it, stencil write from fragment shader would also be handy
Слайд 18Volumetric Fog Updates
Density calculation based on fog model established for
Crysis 1 (WENZEL06)
Deferred pass for opaque geometry
Per-Vertex approximation for
transparent geometry
Слайд 19Volumetric Fog Updates
Little tuning: Artist controllable gradients (via ToD tool)
Height
based: Density and color for specified top and bottom height
Radial
based: Size, color and lobe around sun position
Слайд 20Volumetric Fog Shadows
Based on TÓTH09: Don’t accumulate in-scattered light but
shadow contribution along view ray instead
Слайд 21Volumetric fog shadows
Interleave pass distributes 1024 shadow samples on a
8x8 grid shared by neighboring pixels
Half resolution destination target
Gather pass
computes final shadow value
Bilateral filtering was used to minimize ghosting and halos
Shadow stored in alpha, 8 bit depth in red channel
Used 8 taps to compare against center full resolution depth
Max sample distance configurable (~150-200m in C3 levels)
Cloud shadow texture baked into final result
Final result modifies fog height and radial color
Слайд 25Silhouette POM
Alternative to tessellation based displacement mapping
Looked into various approaches,
most weren’t practical for production
Current implementation is based on principle
of barycentric correspondence (JESCHKE07)
Слайд 26Silhouette POM: Steps
Transform vertices and extrude - VS
Generate prisms (do
not split into tetrahedral) and setup clip planes - GS
Generally
prism sides are bilinear patches, we approximate by a conservative plane
Note to IHVs: Emitting per-triangle constants would be nice!
In theory, on DX11.1, we could emit via UAV output?
Ray marching - PS
Compute intersection of view ray with prism in WS, translate to texture space via (Jeschke07) barycentric correspondence
Use resulting texture uv and height for entry and exit to trace height field
Compute final uv and selectively discard pixel (viewer below height map; view ray leaving prism before hitting terrain)
Lots of pressure on PS, yet GS is the bottleneck (prism gen)
Слайд 30Massive Grass: Simulation
Grass blade instance:
A chain of points held together
by constraints
Distance + bending constrains to try maintain local space
rest pose angle per-particle
Physics collision geometry converted into small sphere set
Collisions handled as plane constrains
No stable collision handling, overdamp the instance
Applied to vegetation meshes via software-skinning
Exposed parameters per group:
Stiffness, damping, wind force factor, random variance
Слайд 35Massive Grass: Mesh Merging
One patch results in N-Meshes
N is number
of materials used
Instances grouped into 16x16x16 meter patches (yes, volumetric)
Typical
Numbers:
50k – 70k visible instances on consoles. PC > 100k
Instances have 18 to 3.6k vertices depending on mesh complexity
Closest instances simulated every frame
Based on distance: simulation and time sliced skinning
Instances removed further away
Слайд 37Massive Grass: Update Loop
Culling process (for each visible patch):
Mark visible
instances
Compute LOD
Check if instance should be skipped in distance
After culling:
Allocate
(from pool) dynamic VB/IB memory for each patch
Sample force fields into per-patch buffer (coarse discretization 4x4x4)
Sample physics for potential colliders, extract collider geometry
Dispatch sim & skin jobs for each patch
Слайд 38Massive Grass: Challenges
Efficient buffer management
Resulting meshes can vary in size
per frame
Naive implementation (C2) resulted in bad perf on PC
and out of vram on consoles due to fragmentation
Current implementation inspired by “Don’t Throw it all Away” (McDONALD12)
Large pools for dynamic IB/VB
Each maintains two free lists (usable and pending)
Each item in pending list is moved to main free list as soon as GPU query guarantees GPU done with pool
1.3 MB consoles main memory and PC 16 MB
Слайд 39Massive Grass: Challenges (2)
Efficient scheduling:
Patch instances are divided into small
groups
Sim job kicked off for each group in main thread
DP
in render thread has blocking wait for sim job
Job considered low-priority
Important:
Avoid unnecessary copies, skin directly to final destination
Reduce throughput and memory requirements (used half & fixed point precision everywhere)
PC: ~15 ms, 300 to 600 jobs on worst case scenarios
Xbox360 ~16ms, 800 jobs; PS3 ~10ms, 100-400 jobs
Слайд 40Massive Grass: Challenges (3)
Alpha tested geometry, literaly everywhere
Massive overdraw, also
troublesome for MSAA
Literaly worst case scenario for RSX due to
poor z-cull
Prototyped alternatives (e.g. geometry based)
Art was not happy with these unfortunately
End solution: keep it simple
G-Buffer stage minimalistic
Consoles: Mostly outputting vertex data
Art side surface coverage minimization
Слайд 41Anti-aliasing
Subjective topic: Sharp VS Blurry
Some PC gamers hate blurry,
some hate sharp.
Some even love 800x600 and no AA
Слайд 42DX11 Deferred MSAA: 101
The problem:
Multiple passes and reading/writing from Multisampled
Render Targets
SV_SampleIndex / SV_Coverage system value semantics allow to solve
via multipass for pixel/sample frequency passes (Thibieroz08)
SV_SampleIndex
Forces pixel shader execution for each sub-sample
SV_SampleIndex provides index of the sub-sample currently executed
Index can be used to fetch sub-sample from your Multisampled RT
E.g. FooMS.Load( UnnormScreenCoord, nCurrSample)
SV_Coverage
Indicates to pixel shader which sub-samples covered during raster stage
Can also modify sub-sample coverage for custom coverage mask
Слайд 43DX11 Deferred MSAA
Foundation for almost all our supported AA techniques
Simple
theory => troublesome practice
At least with fairly complex and deferred
based engines
Disclaimer:
Non-MSAA friendly code accumulates fast
Breaks regularly as new techniques added with no care for MSAA
Pinpoint non-msaa friendly techniques, and update them one by one.
Rinse and repeat and you’ll get there eventually.
Will be enforced by default on our future engine versions
Слайд 44Custom Resolve & Per-Sample Mask
Post G-Buffer, perform a custom msaa
resolve:
Outputs sample 0 for lighting/other msaa dependent passes
Creates sub-sample mask
on same pass, rejecting similar samples
Tag stencil with sub-sample mask
How to combine with existing complex techniques that might be using Stencil Buffer already?
Reserve 1 bit from stencil buffer
Update it with sub-sample mask
Make usage of stencil read/write bitmask to avoid bit override
Restore whenever a stencil clear occurs
Слайд 48Pixel/Sample Frequency Passes
Ensure disabling sample bit override via stencil write
mask
StencilWriteMask = 0x7F
Pixel Frequency Passes
Set stencil read mask to reserved
bits for per-pixel regions (~0x80)
Bind pre-resolved (non-multisampled) targets SRVs
Render pass as usual
Sample Frequency Passes
Set stencil read mask to reserved bit for per-sample regions (0x80)
Bind multisampled targets SRVs
Index current sub-sample via SV_SAMPLEINDEX
Render pass as usual
Слайд 49Alpha Test Super-Sampling
Alpha testing is a special case
Default SV_Coverage only
applies to triangle edges
Create your own sub-sample coverage mask
E.g. check
if current sub-sample AT or not and set bit
Слайд 50Alpha Test Super-Sampling
Alpha Test SSAA Disabled
Слайд 51Alpha Test Super-Sampling
Alpha Test SSAA Enabled
Слайд 52Corner Cases
Cascades sun shadow maps:
Doing it “by the book” gets
expensive quickly
Render shadows as usual at pixel frequency
Bilateral upscale during
deferred shading composite pass
Слайд 53Corner Cases
Soft particles (or similar techniques accessing depth):
Recommendation to tackle
via per-sample frequency is quite slow on real world scenarios
Max
Depth instead works quite ok for most cases and N-times faster
Bad
Good
Слайд 54MSAA Friendliness
MSAA unfriendly techniques, the usual suspects:
No AA at
all or noticeable bright/dark silhouettes
Bad
Good
Слайд 55MSAA Friendliness
MSAA unfriendly techniques, the usual suspects:
No AA at
all or noticeable bright/dark silhouettes
Bad
Good
Слайд 56MSAA Friendliness
Rules of thumb:
Accessing and/or rendering to Multisampled
Render Targets?
Then you’ll need to care about accessing/outputting correct
sub-sample
Obviously, always minimize BW – avoid fat formats
The later is always valid, but even more for MSAA cases
Слайд 57MSAA Correctness vs Performance
Our goal was correctness and quality over
performance
You can always cut some corners as most games doing:
Alpha
to Coverage instead of Alpha Test Super-Sampling
Or even no Alpha Test AA
Render only opaque with MSAA
Then render alpha blended passes withouth MSAA
Assuming HDR rendering: note that tone mapping is implicitly done post-resolve resulting is loss of detail on high contrast regions
Note to IHVs: Having explicit access to HW capabilities such as EQAA/CSAA would be nice
Smarter AA combos
Слайд 58Conclusion
What’s next for CryENGINE ?
A Big Next Generation leap is
finally upon us
In 2 years time, GPUs will be at
~16 TFLOPS and ridiculous amount of available memory.
Extrapolate results from there, without >8 year old consoles slowing progress
4k resolution will bring some interesting challenges/opportunities
Call to arms - still a lot of problems to solve
IHVs/Microsoft: PC GPU profilers have a lot to evolve! How about a unified GPU Profiler, working great for all IHVs?
Microsoft: Sup with DX11 (lack of) documentation? Where’s DX12?
You: No great realtime GI / realtime reflections solution yet!
Слайд 59Special Thanks
Nicolas Thibieroz
Chris Auty, Carsten Wenzel, Chris Raine, Chris Bolte,
Baldur Karlsson, Andrew Khan, Michael Kopietz, Ivo Zoltan Frey, Desmond
Gayle, Marco Corbetta, Jake Turner, Pierre-Ives Donzallaz, Magnus Larbrant, Nicolas Schulz, Nick Kasyan, Vladimir Kajalin..
Uff… lets just make it shorter:
Thanks to the entire Crytek Team ^_^
Слайд 60Questions?
Tiago@Crytek.com / Twitter: Crytek_Tiago
Carsten@Crytek.com
ChristopherR@Crytek.com / Twitter: Cry_Raine
Слайд 62References
WENZEL06 – Wenzel, C. “Real-time Atmospheric Effects in Games”, 2006
JESCHKE07
- Jeschke, S. et al. “Interactive Smooth and Curved Shell
Mapping”, 2007
THIBIEROZ08 – Thibieroz, N. “Deferred Shading with Multisampling Anti-Aliasing in DirectX10”, 2008
TÓTH09 – Tóth, B. et al. “Real-time Volumetric Lighting in Participating Media”, 2009
SOUSA11 - Sousa, T. “CryENGINE 3 Rendering Techniques”, 2011
McDONALD12 – McDonald, J. “Don’t Throw it all Away”, 2012
WIKI00 – “Stereographic projection”, http://en.wikipedia.org/wiki/Stereographic_projection
WIKI01 – “Y’CbCr”, http://en.wikipedia.org/wiki/YCbCr
WIKI02– “Chroma subsampling”, http://en.wikipedia.org/wiki/Chroma_subsampling
Слайд 64Massive Grass: Challenges
Trick: Updating allocation done with Copy-On-Write in case
GPU still using original location
Consoles: incrementally defragment pools with GPU
memory copies
Also possible on PC, but more expensive due to CopySubResource limitations (need scratchpad memory, since CSR won’t allow copies where Dst/Src are same resource)
Note to IHVs: Being able to copy from same Dst/Src resource, if non-overlapping memory regions, would be handy
Ended up using allocation & usage scheme for static geometry as well