mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-04 14:11:02 +03:00
Add a page documenting Godot's internal rendering architecture
This is intended for new and returning engine contributors.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 223 KiB |
@@ -19,6 +19,7 @@ This section covers the basics that you will encounter in (almost) every source
|
||||
variant_class
|
||||
object_class
|
||||
inheritance_class_tree
|
||||
internal_rendering_architecture
|
||||
|
||||
Extending Godot by modifying its source code
|
||||
--------------------------------------------
|
||||
|
||||
@@ -0,0 +1,791 @@
|
||||
.. _doc_internal_rendering_architecture:
|
||||
|
||||
Internal rendering architecture
|
||||
===============================
|
||||
|
||||
This page is a high-level overview of Godot 4's internal renderer design.
|
||||
It does not apply to previous Godot versions.
|
||||
|
||||
The goal of this page is to document design decisions taken to best suit
|
||||
:ref:`Godot's design philosophy <doc_best_practices_for_engine_contributors>`,
|
||||
while providing a starting point for new rendering contributors.
|
||||
|
||||
If you have questions about rendering internals not answered here, feel free to
|
||||
ask in the ``#rendering`` channel of the
|
||||
`Godot Contributors Chat <https://chat.godotengine.org/channel/rendering>`__.
|
||||
|
||||
.. note::
|
||||
|
||||
If you have difficulty understanding concepts on this page, it is
|
||||
recommended to go through an OpenGL tutorial such as
|
||||
`LearnOpenGL <https://learnopengl.com/>`__.
|
||||
|
||||
Modern low-level APIs (Vulkan/Direct3D 12) require intermediate
|
||||
knowledge of higher-level APIs (OpenGL/Direct3D 11) to be used
|
||||
effectively. Thankfully, contributors rarely need to work directly with
|
||||
low-level APIs. Godot's renderers are built entirely on OpenGL and
|
||||
RenderingDevice, which is our abstraction over Vulkan/Direct3D 12.
|
||||
|
||||
.. _doc_internal_rendering_architecture_methods:
|
||||
|
||||
Rendering methods
|
||||
-----------------
|
||||
|
||||
Forward+
|
||||
^^^^^^^^
|
||||
|
||||
This is a forward renderer that uses a *clustered* approach to lighting.
|
||||
|
||||
Clustered lighting uses a compute shader to group lights into a 3D frustum
|
||||
aligned grid. Then, at render time, pixels can lookup what lights affect the
|
||||
grid cell they are in and only run light calculations for lights that might
|
||||
affect that pixel.
|
||||
|
||||
This approach can greatly speed up rendering performance on desktop hardware,
|
||||
but is substantially less efficient on mobile.
|
||||
|
||||
Forward Mobile
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
This is a forward renderer that uses a traditional single-pass approach to lighting.
|
||||
|
||||
Intended for mobile platforms, but can also run on desktop platforms. This
|
||||
rendering method is optimized to perform well on mobile GPUs. Mobile GPUs have a
|
||||
very different architecture compared to desktop GPUs due to their unique
|
||||
constraints around battery usage, heat, and overall bandwidth limitations of
|
||||
reading and writing data. Compute shaders also have very limited support or
|
||||
aren't supported at all. As a result, the mobile renderer purely uses
|
||||
raster-based shaders (fragment/vertex).
|
||||
|
||||
Unlike desktop GPUs, mobile GPUs perform *tile-based rendering*. Instead of
|
||||
rendering the whole image as a single unit, the image is divided in smaller
|
||||
tiles that fit within the faster internal memory of the mobile GPU. Each tile is
|
||||
rendered and then written out to the destination texture. This all happens
|
||||
automatically on the graphics driver.
|
||||
|
||||
The problem is that this introduces bottlenecks in our traditional approach. For
|
||||
desktop rendering, we render all opaque geometry, then handle the background,
|
||||
then transparent geometry, then post-processing. Each pass will need to read the
|
||||
current result into tile memory, perform its operations and then write it out
|
||||
again. We then wait for all tiles to be completed before moving on to the next
|
||||
pass.
|
||||
|
||||
The first important change in the mobile renderer is that the mobile renderer
|
||||
does not use the RGBA16F texture formats that the desktop renderer does.
|
||||
Instead, it is using a R10G10B10A2 UNORM texture format. This halves the bandwidth
|
||||
required and has further improvements as mobile hardware often further optimizes
|
||||
for 32-bit formats. The tradeoff is that the mobile renderer has limited HDR
|
||||
capabilities due to the reduced precision and maximum values in the color data.
|
||||
|
||||
The second important change is the use of sub-passes whenever possible.
|
||||
Sub-passes allows us to perform the rendering steps end-to-end per tile saving
|
||||
on the overhead introduced by reading from and writing to the tiles between each
|
||||
rendering pass. The ability to use sub-passes is limited by the inability to
|
||||
read neighboring pixels, as we're constrained to working within a single tile.
|
||||
|
||||
This limitation of subpasses results in not being able to implement features
|
||||
such as glow and depth of field efficiently. Similarly, if there is a
|
||||
requirement to read from the screen texture or depth texture, we must fully
|
||||
write out the rendering result limiting our ability to use sub-passes. When such
|
||||
features are enabled, a mix of sub-passes and normal passes are used, and these
|
||||
features result in a notable performance penalty.
|
||||
|
||||
On desktop platforms, the use of sub-passes won't have any impact on
|
||||
performance. However, this rendering method can still perform better than
|
||||
Clustered Forward in simple scenes thanks to its lower complexity and lower
|
||||
bandwidth usage. This is especially noticeable on low-end GPUs, integrated
|
||||
graphics or in VR applications.
|
||||
|
||||
Given its low-end focus, this rendering method does not provide high-end
|
||||
rendering features such as SDFGI and :ref:`doc_volumetric_fog`. Several
|
||||
post-processing effects are also not available.
|
||||
|
||||
.. _doc_internal_rendering_architecture_compatibility:
|
||||
|
||||
Compatibility
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
This is the only rendering method available when using the OpenGL driver.
|
||||
This rendering method is not available when using Vulkan or Direct3D 12.
|
||||
|
||||
This is a traditional (non-clustered) forward renderer. It's intended for old
|
||||
GPUs that don't have Vulkan support, but still works very efficiently on newer
|
||||
hardware. Specifically, it is optimized for older and lower-end mobile devices
|
||||
However, many optimizations carry over making it a good choice for older and
|
||||
lower-end desktop as well.
|
||||
|
||||
Like the Mobile renderer, the Compatibility renderer uses an R10G10B10A2 UNORM
|
||||
texture for 3D rendering. Unlike the mobile renderer, colors are tonemapped and
|
||||
stored in sRGB format so there is no HDR support. This avoids the need for a
|
||||
tonemapping pass and allows us to use the lower bit texture without substantial
|
||||
banding.
|
||||
|
||||
The Compatibility renderer uses a traditional forward single-pass approach to
|
||||
drawing objects with lights, but it uses a multi-pass approach to draw lights
|
||||
with shadows. Specifically, in the first pass, it can draw multiple lights
|
||||
without shadows and up to one DirectionalLight3D with shadows. In each
|
||||
subsequent pass, it can draw up to one OmniLight3D, one SpotLight3D and one
|
||||
DirectionalLight3D with shadows. Lights with shadows will affect the scene
|
||||
differently than lights without shadows, as the lighting is blended in sRGB space
|
||||
instead of linear space. This difference in lighting will impact how the scene
|
||||
looks and needs to be kept in mind when designing scenes for the Compatibility
|
||||
renderer.
|
||||
|
||||
Given its low-end focus, this rendering method does not provide high-end
|
||||
rendering features (even less so compared to Forward Mobile). Most
|
||||
post-processing effects are not available.
|
||||
|
||||
Why not deferred rendering?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Forward rendering generally provides a better tradeoff for performance versus
|
||||
flexibility, especially when a clustered approach to lighting is used. While
|
||||
deferred rendering can be faster in some cases, it's also less flexible and
|
||||
requires using hacks to be able to use MSAA. Since games with a less realistic
|
||||
art style can benefit a lot from MSAA, we chose to go with forward rendering for
|
||||
Godot 4 (like Godot 3).
|
||||
|
||||
That said, parts of the forward renderer *are* performed with a deferred approach
|
||||
to allow for some optimizations when possible. This applies to VoxelGI and SDFGI
|
||||
in particular.
|
||||
|
||||
A clustered deferred renderer may be developed in the future. This renderer
|
||||
could be used in situations where performance is favored over flexibility.
|
||||
|
||||
Rendering drivers
|
||||
-----------------
|
||||
|
||||
Godot 4 supports the following graphics APIs:
|
||||
|
||||
Vulkan
|
||||
^^^^^^
|
||||
|
||||
This is the main driver in Godot 4, with most of the development focus going
|
||||
towards this driver.
|
||||
|
||||
Vulkan 1.0 is required as a baseline, with optional Vulkan 1.1 and 1.2 features
|
||||
used when available. `volk <https://github.com/zeux/volk>`__ is used as a Vulkan
|
||||
loader, and
|
||||
`Vulkan Memory Allocator <https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator>`__
|
||||
is used for memory management.
|
||||
|
||||
Both the Forward+ and Mobile
|
||||
:ref:`doc_internal_rendering_architecture_methods` are supported when using the
|
||||
Vulkan driver.
|
||||
|
||||
**Vulkan context creation:**
|
||||
|
||||
- `drivers/vulkan/vulkan_context.cpp <https://github.com/godotengine/godot/blob/4.0/drivers/vulkan/vulkan_context.cpp>`__
|
||||
|
||||
Direct3D 12
|
||||
^^^^^^^^^^^
|
||||
|
||||
Like Vulkan, the Direct3D 12 driver targets modern platforms only. It is
|
||||
designed to target both Windows and Xbox (whereas Vulkan can't be used directly on Xbox).
|
||||
|
||||
Both the Forward+ and Mobile :ref:`doc_internal_rendering_architecture_methods` can be
|
||||
used with Direct3D 12.
|
||||
|
||||
:ref:`doc_internal_rendering_architecture_core_shaders` are shared with the
|
||||
Vulkan renderer. Shaders are transpiled from GLSL to HLSL using
|
||||
Mesa NIR (`more information <https://godotengine.org/article/d3d12-adventures-in-shaderland/>`__).
|
||||
This means you don't need to know HLSL to work on the Direct3D 12 renderer,
|
||||
although knowing the language's basics is recommended to ease debugging.
|
||||
|
||||
**As of May 2023, this driver is still in development and is not merged in
|
||||
Godot 4.0 or the master branch.** While Direct3D 12 allows supporting
|
||||
Direct3D-exclusive features on Windows 11 such as windowed optimizations and
|
||||
Auto HDR, Vulkan is still recommended for most projects. See the
|
||||
`pull request that introduced Direct3D 12 support <https://github.com/godotengine/godot/pull/70315>`__
|
||||
for more information.
|
||||
|
||||
Metal
|
||||
^^^^^
|
||||
|
||||
Godot supports Metal rendering via `MoltenVK <https://github.com/KhronosGroup/MoltenVK>`__,
|
||||
as macOS and iOS do not support Vulkan natively.
|
||||
This is done automatically when specifying the Vulkan driver in the Project Settings.
|
||||
|
||||
MoltenVK makes driver maintenance easy at the cost of some performance overhead.
|
||||
Also, MoltenVK has several limitations that a native Metal driver implementation
|
||||
wouldn't have. Both the clustered and mobile
|
||||
:ref:`doc_internal_rendering_architecture_methods` can be used with a Metal
|
||||
backend via MoltenVK.
|
||||
|
||||
A native Metal driver is planned in the future for better performance and
|
||||
compatibility.
|
||||
|
||||
OpenGL
|
||||
^^^^^^
|
||||
|
||||
This driver uses OpenGL ES 3.0 and targets legacy and low-end devices that don't
|
||||
support Vulkan. OpenGL 3.3 Core Profile is used on desktop platforms to run this
|
||||
driver, as most graphics drivers on desktop don't support OpenGL ES.
|
||||
WebGL 2.0 is used for web exports.
|
||||
|
||||
Only the :ref:`doc_internal_rendering_architecture_compatibility` rendering
|
||||
method can be used with the OpenGL driver.
|
||||
|
||||
:ref:`doc_internal_rendering_architecture_core_shaders` are entirely different
|
||||
from the Vulkan renderer.
|
||||
|
||||
**As of May 2023, this driver is still in development.** Many features
|
||||
are still not implemented, especially in 3D.
|
||||
|
||||
Summary of rendering drivers/methods
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following rendering API + rendering method combinations are currently possible:
|
||||
|
||||
- Vulkan + Forward+
|
||||
- Vulkan + Forward Mobile
|
||||
- Direct3D 12 + Forward+
|
||||
- Direct3D 12 + Forward Mobile
|
||||
- Metal + Forward+ (via MoltenVK)
|
||||
- Metal + Forward Mobile (via MoltenVK)
|
||||
- OpenGL + Compatibility
|
||||
|
||||
Each combination has its own limitations and performance characteristics. Make
|
||||
sure to test your changes on all rendering methods if possible before opening a
|
||||
pull request.
|
||||
|
||||
RenderingDevice abstraction
|
||||
---------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
The OpenGL driver does not use the RenderingDevice abstraction.
|
||||
|
||||
To make the complexity of modern low-level graphics APIs more manageable,
|
||||
Godot uses its own abstraction called RenderingDevice.
|
||||
|
||||
This means that when writing code for modern rendering methods, you don't
|
||||
actually use the Vulkan or Direct3D 12 APIs directly. While this is still
|
||||
lower-level than an API like OpenGL, this makes working on the renderer easier,
|
||||
as RenderingDevice will abstract many API-specific quirks for you. The
|
||||
RenderingDevice presents a similar level of abstraction as Metal or WebGPU.
|
||||
|
||||
**Vulkan RenderingDevice implementation:**
|
||||
|
||||
- `drivers/vulkan/rendering_device_vulkan.cpp <https://github.com/godotengine/godot/blob/4.0/drivers/vulkan/rendering_device_vulkan.cpp>`__
|
||||
|
||||
Core rendering classes architecture
|
||||
-----------------------------------
|
||||
|
||||
This diagram represents the structure of rendering classes in Godot, including the RenderingDevice abstraction:
|
||||
|
||||
.. image:: img/rendering_architecture_diagram.webp
|
||||
|
||||
`View at full size <https://raw.githubusercontent.com/godotengine/godot-docs/4.0/contributing/development/core_and_modules/img/rendering_architecture_diagram.webp>`__
|
||||
|
||||
.. _doc_internal_rendering_architecture_core_shaders:
|
||||
|
||||
Core shaders
|
||||
------------
|
||||
|
||||
While shaders in Godot projects are written using a
|
||||
:ref:`custom language inspired by GLSL <doc_shading_language>`, core shaders are
|
||||
written directly in GLSL.
|
||||
|
||||
These core shaders are embedded in the editor and export template binaries at
|
||||
compile-time. To see any changes you've made to those GLSL shaders, you need to
|
||||
recompile the editor or export template binary.
|
||||
|
||||
Some material features such as height mapping, refraction and proximity fade are
|
||||
not part of core shaders, and are performed in the default BaseMaterial3D using
|
||||
the Godot shader language instead (not GLSL). This is done by procedurally
|
||||
generating the required shader code depending on the features enabled in the
|
||||
material.
|
||||
|
||||
By convention, shader files with ``_inc`` in their name are included in other
|
||||
GLSL files for better code reuse. Standard GLSL preprocessing is used to achieve
|
||||
this.
|
||||
|
||||
.. warning::
|
||||
|
||||
Core material shaders will be used by every material in the scene – both
|
||||
with the default BaseMaterial3D and custom shaders. As a result, these
|
||||
shaders must be kept as simple as possible to avoid performance issues and
|
||||
ensure shader compilation doesn't become too slow.
|
||||
|
||||
If you use ``if`` branching in a shader, performance may decrease as
|
||||
:abbr`VGPR (Vector General-Purpose Register)` usage will increase in the
|
||||
shader. This happens even if all pixels evaluate to ``true`` or ``false`` in
|
||||
a given frame.
|
||||
|
||||
If you use ``#if`` preprocessor branching, the number of required shader
|
||||
versions will increase in the scene. In a worst-case scenario, adding a
|
||||
single boolean ``#define`` can *double* the number of shader versions that
|
||||
may need to be compiled in a given scene. In some cases, Vulkan
|
||||
specialization constants can be used as a faster (but more limited)
|
||||
alternative.
|
||||
|
||||
This means there is a high barrier to adding new built-in material features
|
||||
in Godot, both in the core shaders and BaseMaterial3D. While BaseMaterial3D
|
||||
can make use of dynamic code generation to only include the shader code if
|
||||
the feature is enabled, it'll still require generating more shader versions
|
||||
when these features are used in a project. This can make shader compilation
|
||||
stutter more noticeable in complex 3D scenes.
|
||||
|
||||
See
|
||||
`The Shader Permutation Problem <https://therealmjp.github.io/posts/shader-permutations-part1/>`__
|
||||
and
|
||||
`Branching on a GPU <https://medium.com/@jasonbooth_86226/branching-on-a-gpu-18bfc83694f2>`__
|
||||
blog posts for more information.
|
||||
|
||||
**Core GLSL material shaders:**
|
||||
|
||||
- Forward+: `servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl>`__
|
||||
- Forward Mobile: `servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl>`__
|
||||
- Compatibility: `drivers/gles3/shaders/scene.glsl <https://github.com/godotengine/godot/blob/4.0/drivers/gles3/shaders/scene.glsl>`__
|
||||
|
||||
**Material shader generation:**
|
||||
|
||||
- `scene/resources/material.cpp <https://github.com/godotengine/godot/blob/4.0/scene/resources/material.cpp>`__
|
||||
|
||||
**Other GLSL shaders for Forward+ and Forward Mobile rendering methods:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/ <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/>`__
|
||||
- `modules/lightmapper_rd/ <https://github.com/godotengine/godot/blob/4.0/modules/lightmapper_rd>`__
|
||||
|
||||
**Other GLSL shaders for the Compatibility rendering method:**
|
||||
|
||||
- `drivers/gles3/shaders/ <https://github.com/godotengine/godot/blob/4.0/drivers/gles3/shaders/>`__
|
||||
|
||||
2D and 3D rendering separation
|
||||
------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
The following is only applicable in the Forward+ and Forward Mobile
|
||||
rendering methods, not in Compatibility. Multiple Viewports can be used to
|
||||
emulate this when using the Compatibility backend, or to perform 2D
|
||||
resolution scaling.
|
||||
|
||||
2D and 3D are rendered to separate buffers, as 2D rendering in Godot is performed
|
||||
in :abbr:`LDR (Low Dynamic Range)` sRGB-space while 3D rendering uses
|
||||
:abbr:`HDR (High Dynamic Range)` linear space.
|
||||
|
||||
3D resolution scaling is performed differently depending on whether bilinear or
|
||||
FSR 1.0 scaling is used. When bilinear scaling is used, no special upscaling
|
||||
shader is run. Instead, the viewport's texture is stretched and displayed with a
|
||||
linear sampler (which makes the filtering happen directly on the hardware). This
|
||||
allows maximizing the performance of bilinear 3D scaling.
|
||||
|
||||
The ``configure()`` function in RenderSceneBuffersRD reallocates the 2D/3D
|
||||
buffers when the resolution or scaling changes.
|
||||
|
||||
Dynamic resolution scaling isn't supported yet, but is planned in a future Godot
|
||||
release.
|
||||
|
||||
**2D and 3D rendering buffer configuration C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp>`__
|
||||
|
||||
2D rendering techniques
|
||||
-----------------------
|
||||
|
||||
2D light rendering is performed in a single pass to allow for better performance
|
||||
with large amounts of lights.
|
||||
|
||||
The Forward+ and Mobile rendering methods don't feature 2D batching yet, but
|
||||
it's planned for a future release.
|
||||
|
||||
The Compatibility backend features 2D batching to improve performance, which is
|
||||
especially noticeable with lots of text on screen.
|
||||
|
||||
MSAA can be enabled in 2D to provide "automatic" line and polygon antialiasing,
|
||||
but FXAA does not affect 2D rendering as it's calculated before 2D rendering
|
||||
begins. Godot's 2D drawing methods such as the Line2D node or some CanvasItem
|
||||
``draw_*()`` methods provide their own way of antialiasing based on triangle
|
||||
strips and vertex colors, which don't require MSAA to work.
|
||||
|
||||
A 2D signed distance field representing LightOccluder2D nodes in the viewport is
|
||||
automatically generated if an user shader requests it. This can be used for
|
||||
various effects in custom shaders, such as 2D global illumination. It is also
|
||||
used to calculate particle collisions in 2D.
|
||||
|
||||
**2D SDF generation GLSL shader:**
|
||||
|
||||
- `https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl <servers/rendering/renderer_rd/shaders/canvas_sdf.glsl>`__
|
||||
|
||||
3D rendering techniques
|
||||
-----------------------
|
||||
|
||||
Batching and instancing
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In the Forward+ backend, Vulkan instancing is used to group rendering
|
||||
of identical objects for performance. This is not as fast as static mesh
|
||||
merging, but it still allows instances to be culled individually.
|
||||
|
||||
Light, decal and reflection probe rendering
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Reflection probe and decal rendering are currently not available in the
|
||||
Compatibility backend.
|
||||
|
||||
As its name implies, the Forward+ backend uses clustered lighting. This
|
||||
allows using as many lights as you want; performance largely depends on screen
|
||||
coverage. Shadow-less lights can be almost free if they don't occupy much space
|
||||
on screen.
|
||||
|
||||
All rendering methods also support rendering up to 8 directional lights at the
|
||||
same time (albeit with lower shadow quality when more than one light has shadows
|
||||
enabled).
|
||||
|
||||
The Forward Mobile backend uses a single-pass lighting approach, with a
|
||||
limitation of 8 OmniLights + 8 SpotLights affecting each Mesh *resource* (plus a
|
||||
limitation of 256 OmniLights + 256 SpotLights in the camera view). These limits
|
||||
are hardcoded and can't be adjusted in the project settings.
|
||||
|
||||
The Compatibility backend uses a hybrid single-pass + multi-pass lighting
|
||||
approach. Lights without shadows are rendered in a single pass. Lights with
|
||||
shadows are rendered in multiple passes. This is required for performance
|
||||
reasons on mobile devices. As a result, performance does not scale well with
|
||||
many shadow-casting lights. It is recommended to only have a handful of lights
|
||||
with shadows in the camera frustum at a time and for those lights to be spread
|
||||
apart so that each object is only touched by 1 or 2 shadowed lights at a time.
|
||||
The maximum number of lights visible at once can be adjusted in the project
|
||||
settings.
|
||||
|
||||
In all 3 methods, lights without shadows are much cheaper than lights with
|
||||
shadows. To improve performance, lights are only updated when the light is
|
||||
modified or when objects in its radius are modified. Godot currently doesn't
|
||||
separate static shadow rendering from dynamic shadow rendering, but this is
|
||||
planned in a future release.
|
||||
|
||||
Clustering is also used for reflection probes and decal rendering in the
|
||||
Forward+ backend.
|
||||
|
||||
Shadow mapping
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Both Forward+ and Forward Mobile methods use
|
||||
:abbr:`PCF (Percentage Closer Filtering)` to filter shadow maps and create a
|
||||
soft penumbra. Instead of using a fixed PCF pattern, these methods use a vogel
|
||||
disk pattern which allows for changing the number of samples and smoothly
|
||||
changing the quality.
|
||||
|
||||
Godot also supports percentage-closer soft shadows (PCSS) for more realistic
|
||||
shadow penumbra rendering. PCSS shadows are limited to the Forward+
|
||||
backend as they're too demanding to be usable in the Forward Mobile backend.
|
||||
PCSS also uses a vogel-disk shaped kernel.
|
||||
|
||||
Additionally, both shadow-mapping techniques rotate the kernel on a per-pixel
|
||||
basis to help soften under-sampling artifacts.
|
||||
|
||||
The Compatibility backend doesn't support shadow mapping for any light types yet.
|
||||
|
||||
Temporal antialiasing
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Only available in the Forward+ backend, not the Forward Mobile or
|
||||
Compatibility methods.
|
||||
|
||||
Godot uses a custom TAA implementation based on the old TAA implementation from
|
||||
`Spartan Engine <https://github.com/PanosK92/SpartanEngine>`__.
|
||||
|
||||
Temporal antialiasing requires motion vectors to work. If motion vectors
|
||||
are not correctly generated, ghosting will occur when the camera or objects move.
|
||||
|
||||
Motion vectors are generated on the GPU in the main material shader. This is
|
||||
done by running the vertex shader corresponding to the previous rendered frame
|
||||
(with the previous camera transform) in addition to the vertex shader for the
|
||||
current rendered frame, then storing the difference between them in a color buffer.
|
||||
|
||||
Using `FSR 2.0 <https://github.com/GPUOpen-Effects/FidelityFX-FSR2>`__ instead
|
||||
of a custom TAA implementation is planned in a future release.
|
||||
|
||||
**TAA resolve:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl>`__
|
||||
|
||||
Global illumination
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
VoxelGI and SDFGI are only available in the Forward+ backend, not the
|
||||
Forward Mobile or Compatibility methods.
|
||||
|
||||
LightmapGI *baking* is only available in the Forward+ and Forward Mobile
|
||||
methods, and can only be performed within the editor (not in an exported
|
||||
project). LightmapGI *rendering* will eventually be supported by the
|
||||
Compatibility backend.
|
||||
|
||||
Godot supports voxel-based GI (VoxelGI), signed distance field GI (SDFGI) and
|
||||
lightmap baking and rendering (LightmapGI). These techniques can be used
|
||||
simultaneously if desired.
|
||||
|
||||
Lightmap baking happens on the GPU using Vulkan compute shaders. The GPU-based
|
||||
lightmapper is implemented in the LightmapperRD class, which inherits from the
|
||||
Lightmapper class. This allows for implementing additional lightmappers, paving
|
||||
the way for a future port of the CPU-based lightmapper present in Godot 3.x.
|
||||
This would allow baking lightmaps while using the Compatibility backend.
|
||||
|
||||
**Core GI C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_rd/environment/gi.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/environment/gi.cpp>`__
|
||||
- `scene/3d/voxel_gi.cpp <https://github.com/godotengine/godot/blob/4.0/scene/3d/voxel_gi.cpp>`__ - VoxelGI node
|
||||
- `editor/plugins/voxel_gi_editor_plugin.cpp <https://github.com/godotengine/godot/blob/4.0/editor/plugins/voxel_gi_editor_plugin.cpp>`__ - Editor UI for the VoxelGI node
|
||||
|
||||
**Core GI GLSL shaders:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl>`__ - VoxelGI debug draw mode
|
||||
- `servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl>`__ - SDFGI Cascades debug draw mode
|
||||
- `servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl>`__ - SDFGI Probes debug draw mode
|
||||
- `servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl>`__
|
||||
|
||||
**Lightmapper C++ code:**
|
||||
|
||||
- `scene/3d/lightmap_gi.cpp <https://github.com/godotengine/godot/blob/4.0/scene/3d/lightmap_gi.cpp>`__ - LightmapGI node
|
||||
- `editor/plugins/lightmap_gi_editor_plugin.cpp <https://github.com/godotengine/godot/blob/4.0/editor/plugins/lightmap_gi_editor_plugin.cpp>`__ - Editor UI for the LightmapGI node
|
||||
- `scene/3d/lightmapper.cpp <https://github.com/godotengine/godot/blob/4.0/scene/3d/lightmapper.cpp>`__ - Abstract class
|
||||
- `modules/lightmapper_rd/lightmapper_rd.cpp <https://github.com/godotengine/godot/blob/4.0/modules/lightmapper_rd/lightmapper_rd.cpp>`__ - GPU-based lightmapper implementation
|
||||
|
||||
**Lightmapper GLSL shaders:**
|
||||
|
||||
- `modules/lightmapper_rd/lm_raster.glsl <https://github.com/godotengine/godot/blob/4.0/modules/lightmapper_rd/lm_raster.glsl>`__
|
||||
- `modules/lightmapper_rd/lm_compute.glsl <https://github.com/godotengine/godot/blob/4.0/modules/lightmapper_rd/lm_compute.glsl>`__
|
||||
- `modules/lightmapper_rd/lm_blendseams.glsl <https://github.com/godotengine/godot/blob/4.0/modules/lightmapper_rd/lm_blendseams.glsl>`__
|
||||
|
||||
Depth of field
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Only available in the Forward+ and Forward Mobile methods, not the
|
||||
Compatibility backend.
|
||||
|
||||
The Forward+ and Forward Mobile methods use different approaches to
|
||||
DOF rendering, with different visual results. This is done to best
|
||||
match the performance characteristics of the target hardware. In Clustered
|
||||
Forward, DOF is performed using a compute shader. In Forward Mobile, DOF is
|
||||
performed using a fragment shader (raster).
|
||||
|
||||
Box, hexagon and circle bokeh shapes are available (from fastest to slowest).
|
||||
Depth of field can optionally be jittered every frame to improve its appearance
|
||||
when temporal antialiasing is enabled.
|
||||
|
||||
**Depth of field C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_rd/effects/bokeh_dof.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/effects/bokeh_dof.cpp>`__
|
||||
|
||||
**Depth of field GLSL shader (compute - used for Forward+):**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl>`__
|
||||
|
||||
**Depth of field GLSL shader (raster - used for Forward Mobile):**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl>`__
|
||||
|
||||
Screen-space effects (SSAO, SSIL, SSR, SSS)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Only available in the Forward+ backend, not the Forward Mobile or
|
||||
Compatibility methods.
|
||||
|
||||
The Forward+ backend supports screen-space ambient occlusion,
|
||||
screen-space indirect lighting, screen-space reflections and subsurface scattering.
|
||||
|
||||
SSAO uses an implementation derived from Intel's
|
||||
`ASSAO <https://www.intel.com/content/www/us/en/developer/articles/technical/adaptive-screen-space-ambient-occlusion.html>`__
|
||||
(converted to Vulkan). SSIL is derived from SSAO to provide high-performance
|
||||
indirect lighting.
|
||||
|
||||
When both SSAO and SSIL are enabled, parts of SSAO and SSIL are shared to reduce
|
||||
the performance impact.
|
||||
|
||||
SSAO and SSIL are performed at half resolution by default to improve performance.
|
||||
SSR is always performed at half resolution to improve performance.
|
||||
|
||||
**Screen-space effects C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_rd/effects/ss_effects.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/effects/ss_effects.cpp>`__
|
||||
|
||||
**Screen-space ambient occlusion GLSL shader:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssao.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssao.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl>`__
|
||||
|
||||
**Screen-space indirect lighting GLSL shader:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssil.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssil.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl>`__
|
||||
|
||||
**Screen-space reflections GLSL shader:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl>`__
|
||||
|
||||
**Subsurface scattering GLSL:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl>`__
|
||||
|
||||
Sky rendering
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`doc_sky_shader`
|
||||
|
||||
Godot supports using shaders to render the sky background. The radiance map
|
||||
(which is used to provide ambient light and reflections for PBR materials) is
|
||||
automatically updated based on the sky shader.
|
||||
|
||||
The SkyMaterial resources such as ProceduralSkyMaterial, PhysicalSkyMaterial and
|
||||
PanoramaSkyMaterial generate a built-in shader for sky rendering. This is
|
||||
similar to what BaseMaterial3D provides for 3D scene materials.
|
||||
|
||||
A detailed technical implementation can be found in the
|
||||
`Custom sky shaders in Godot 4.0 <https://godotengine.org/article/custom-sky-shaders-godot-4-0>`__
|
||||
article.
|
||||
|
||||
**Sky rendering C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_rd/environment/sky.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/environment/sky.cpp>`__ - Sky rendering
|
||||
- `scene/resources/sky.cpp <https://github.com/godotengine/godot/blob/4.0/scene/resources/sky.cpp>`__ - Sky resource (not to be confused with sky rendering)
|
||||
- `scene/resources/sky_material.cpp <https://github.com/godotengine/godot/blob/4.0/scene/resources/sky_material.cpp>`__ SkyMaterial resources (used in the Sky resource)
|
||||
|
||||
**Sky rendering GLSL shader:**
|
||||
|
||||
Volumetric fog
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Only available in the Forward+ backend, not the Forward Mobile or
|
||||
Compatibility methods.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`doc_fog_shader`
|
||||
|
||||
Godot supports a frustum-aligned voxel (froxel) approach to volumetric fog
|
||||
rendering. As opposed to a post-processing filter, this approach is more
|
||||
general-purpose as it can work with any light type. Fog can also use shaders for
|
||||
custom behavior, which allows animating the fog or using a 3D texture to
|
||||
represent density.
|
||||
|
||||
The FogMaterial resource generates a built-in shader for FogVolume nodes. This is
|
||||
similar to what BaseMaterial3D provides for 3D scene materials.
|
||||
|
||||
A detailed technical explanation can be found in the
|
||||
`Fog Volumes arrive in Godot 4.0 <https://godotengine.org/article/fog-volumes-arrive-in-godot-4>`__
|
||||
article.
|
||||
|
||||
**Volumetric fog C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_rd/environment/fog.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/environment/fog.cpp>`__ - General volumetric fog
|
||||
- `scene/3d/fog_volume.cpp <https://github.com/godotengine/godot/blob/4.0/scene/3d/fog_volume.cpp>`__ - FogVolume node
|
||||
- `scene/resources/fog_material.cpp <https://github.com/godotengine/godot/blob/4.0/scene/resources/fog_material.cpp>`__ - FogMaterial resource (used by FogVolume)
|
||||
|
||||
**Volumetric fog GLSL shaders:**
|
||||
|
||||
- `servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl>`__
|
||||
- `servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl>`__
|
||||
|
||||
Occlusion culling
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
While modern GPUs can handle drawing a lot of triangles, the number of draw
|
||||
calls in complex scenes can still be a bottleneck (even with Vulkan and Direct3D
|
||||
12).
|
||||
|
||||
Godot 4 supports occlusion culling to reduce overdraw (when the depth prepass
|
||||
is disabled) and reduce vertex throughput.
|
||||
This is done by rasterizing a low-resolution buffer on the CPU using
|
||||
`Embree <https://github.com/embree/embree>`__. The buffer's resolution depends
|
||||
on the number of CPU threads on the system, as this is done in parallel.
|
||||
This buffer includes occluder shapes that were baked in the editor or created at
|
||||
run-time.
|
||||
|
||||
As complex occluders can introduce a lot of strain on the CPU, baked occluders
|
||||
can be simplified automatically when generated in the editor.
|
||||
|
||||
Godot's occlusion culling doesn't support dynamic occluders yet, but
|
||||
OccluderInstance3D nodes can still have their visibility toggled or be moved.
|
||||
However, this will be slow when updating complex occluders this way. Therefore,
|
||||
updating occluders at run-time is best done only on simple occluder shapes such
|
||||
as quads or cuboids.
|
||||
|
||||
This CPU-based approach has a few advantages over other solutions, such as
|
||||
portals and rooms or a GPU-based culling solution:
|
||||
|
||||
- No manual setup required (but can be tweaked manually for best performance).
|
||||
- No frame delay, which is problematic in cutscenes during camera cuts or when
|
||||
the camera moves fast behind a wall.
|
||||
- Works the same on all rendering drivers and methods, with no unpredictable
|
||||
behavior depending on the driver or GPU hardware.
|
||||
|
||||
Occlusion culling is performed by registering occluder meshes, which is done
|
||||
using OccluderInstance3D *nodes* (which themselves use Occluder3D *resources*).
|
||||
RenderingServer then performs occlusion culling by calling Embree in
|
||||
RendererSceneOcclusionCull.
|
||||
|
||||
**Occlusion culling C++ code:**
|
||||
|
||||
- `scene/3d/occluder_instance_3d.cpp <https://github.com/godotengine/godot/blob/4.0/scene/3d/occluder_instance_3d.cpp>`__
|
||||
- `servers/rendering/renderer_scene_occlusion_cull.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_scene_occlusion_cull.cpp>`__
|
||||
|
||||
Visibility range (LOD)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Godot supports manually authored hierarchical level of detail (HLOD), with
|
||||
distances specified by the user in the inspector.
|
||||
|
||||
In RenderingSceneCull, the ``_scene_cull()`` and ``_render_scene()`` functions
|
||||
are where most of the LOD determination happens. Each viewport can render the
|
||||
same mesh with different LODs (to allow for split screen rendering to look correct).
|
||||
|
||||
**Visibility range C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_scene_cull.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_scene_cull.cpp>`__
|
||||
|
||||
Automatic mesh LOD
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ImporterMesh class is used for the 3D mesh import workflow in the editor.
|
||||
Its ``generate_lods()`` function handles generating using the
|
||||
`meshoptimizer <https://meshoptimizer.org/>`__ library.
|
||||
|
||||
LOD mesh generation also generates shadow meshes at the same time. These are
|
||||
meshes that have their vertices welded regardless of smoothing and materials.
|
||||
This is used to improve shadow rendering performance by lowering the vertex
|
||||
throughput required to render shadows.
|
||||
|
||||
The RenderingSceneCull class's ``_render_scene()`` function determines which
|
||||
mesh LOD should be used when rendering. Each viewport can render the
|
||||
same mesh with different LODs (to allow for split screen rendering to look correct).
|
||||
|
||||
The mesh LOD is automatically chosen based on a screen coverage metric. This
|
||||
takes resolution and camera FOV changes into account without requiring user
|
||||
intervention. The threshold multiplier can be adjusted in the project settings.
|
||||
|
||||
To improve performance, shadow rendering and reflection probe rendering also choose
|
||||
their own mesh LOD thresholds (which can be different from the main scene rendering).
|
||||
|
||||
**Mesh LOD generation on import C++ code:**
|
||||
|
||||
- `scene/resources/importer_mesh.cpp <https://github.com/godotengine/godot/blob/4.0/scene/resources/importer_mesh.cpp>`__
|
||||
|
||||
**Mesh LOD determination C++ code:**
|
||||
|
||||
- `servers/rendering/renderer_scene_cull.cpp <https://github.com/godotengine/godot/blob/4.0/servers/rendering/renderer_scene_cull.cpp>`__
|
||||
Reference in New Issue
Block a user