All results have been acquired on a pretty old setup(i7 3770+GTX 770) running on DirectX 11 with medium quality and using RenderDoc and Nsight.
The game runs on Re Engine, a successor of MT Framework - the previous generation engine from Capcom R&D. Aside from RE2 it is used in DMC5 and RE7:Biohazard.
Frame breakdowns are among those things I really like on the internet.
I couldn’t find any material on RE Engine on the internet, so everything here is an (hopefully)educated guess. I’m covering about 90% of the frame structure here and just the general gist of the algorithms. It’s really difficult to cover more as it would require more experience than I have and time to reverse engineer the shaders.
As always, check out cool links at the bottom and don’t forget to reach out if you find any mistakes or have suggestions. I really like learning from the feedback.
Table of content
- General notes
- Table of content
- Frame Structure
- Particle/Fluid sim
- Light list calculation
- White point
- Determine occluders
- Occlusion culling
- Accumulate indirect arguments
- Depth prepass
- G-Buffer pass Geometry+Decals
- HiZ calculation
- Global Specular+Diffuse
- Update shadowmaps
- Local Specular+Diffuse+SSS
- Integrating the light
- Apply transparent glass
- Compute volumetrics/haze/smoke
- Apply volumetrics/haze/smoke
- TAA with previous HDR image
- Motion blur
- Post Processing
- Bonus section
Among other things ripple textures are being generated(Example from a different frame).
Ripples are used for water rendering which is not present in this frame.
Some of the results are being copied into a staging buffer which suggests that results may be used by CPU.
Light list calculation
This pass generates visible light list by testing light frustums against the view frustum. The result is visible light list and some sort of 3d table that maps view space positions to the corresponding lights.
Also per light visible instance lists are computed for later use in shadow map update.
This pass builds a histogram of brightness based on the previous hdr image and metering table. Then determines the whitepoint based on that data.
Occluders’ bounding boxes are being tested against view frustum in a compute shader and an indirect argument buffer is filled.
Occluders are rendered into a small resolution depth buffer and then bounding boxes are being tested against this depth buffer.
Used depth buffer is 4x multisampled. Probably to compensate for low res.
Looks like view oriented bounding boxes.
Example of occlusion test(From a different frame). Surviving pixels(green) write flags(1 for example) to the visibility buffer with per instance slots.
store_raw RWDrawIndirectArguments.x, v1.x, l(1)
Accumulate indirect arguments
Almost every world space geometry object is being rendered with an indirect drawcall.
Nsight profiler shows calls to NvAPI_D3D11_MultiDrawIndexedInstancedIndirect. Read  and  about its usage.
RenderDoc blocks MultiDraw extension so instead in the EventBrowser these expand into a lot of DrawIndexedInstancedIndirect where some of them are empty.
The job of this pass is to aggregate visibility masks from the previous pass and generate an argument buffer.
Nothing fancy. Subset of the scene with major occluders.
G-Buffer pass Geometry+Decals
- RT0 - r11g11b10 emissive
- RT1 - rgba8 albedo.rgb + metallness.a
- RT2 - r10g10b10a2 normal.rg + roughness.b + misc.a
- RT3 - r16g16b16a16 baked_ao.x + velocity.yz + sss.a
The rendered models use pre-baked ambient occlusion from hi-res models.
Multi pass compute shader determines each level of depth hierarchy.
SSAO or HBAO+ depending on your settings. SSAO in this case.
AO is calculated based on HiZ from the previous pass.
Using some non trivial algorithm light probes, cubemaps and AO are combined into global diffuse and specular maps.
Example cubemaps from the scene.
Global illumination diffuse component.
Global illumination specular component.
Per light shadowmaps are being updated for those lights that are affected by dynamic objects. Each shadow map is allocated on a big texture array.
Per light contribution to specular and diffuse component is computed.
Diffuse+SSS. SSS contribution is not visible is this frame.
Integrating the light
Specular/Diffuse components for radiosity/local lights are integrated with albedo. Check out the slider to get the gist of how each component contributes to the image.
Apply transparent glass
After all light has been applied, transparent glass is rendered.
Basically just a bunch of sprites.
This pass computes the blurred image to better lit the haze.
If the original haze mask is replaced with checkerboard.
The result of this pass.
TAA with previous HDR image
TTA is just magic.
Blur guide map is computed based on velocity map.
This pass computes the downscaled image first
And then applies bloom filter, tonemapping, distortion and chromatic aberration.
The Engine relies heavily on compute+indirect draw approach. All meshes and textures are of high quality. The game employs deferred rendering with TAA/FXAA and glass as a post process. Read this for more details on deferred rendering tricks. A lot of textures are BC7 compressed. In general, the used techniques are similar to those described at .
Had to really search for the right frame to notice the SSS contribution.
Tentacle monster breakdown
The monster is split into many parts.
The game has a lot of gore textures for different details.
Mip levels for textures are not just linearly filtered. The crispiness increases with each level. Also some textures already have specular highlights, not sure how this contributes to the look.
Geometry has good topology.
HBAO is of much better quality than SSAO.
Smoke takes cone lights into account.
The actual planes used to render the smoke.
New blog post: Resident Evil 2 Frame Breakdown. Warning: Tons of images https://t.co/INzXDCxWo2— Anton Schreiner (@kokoronomagnet) August 2, 2019