Internal rendering architecture
Questa pagina è una panoramica generale della progettazione del renderer interno di Godot 4. Non si applica alle versioni precedenti di Godot.
L'obiettivo di questa pagina è documentare le decisioni di progettazione prese per adattarsi al meglio alla filosofia di progettazione di Godot, fornendo allo stesso tempo un punto di partenza per i nuovi contributori al rendering.
If you have questions about rendering internals not answered here, feel free to
ask in the #rendering channel of the
Godot Contributors Chat.
Nota
If you have difficulty understanding concepts on this page, it is recommended to go through an OpenGL tutorial such as LearnOpenGL.
Modern low-level APIs (Vulkan/Direct3D 12/Metal) 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/Metal.
Metodi di rendering
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.
Mobile
Questo è un forward renderer che utilizza un approccio tradizionale a passaggio singolo per l'illuminazione. Internamente, si chiama Forward Mobile.
Progettato per le piattaforme mobili, ma può funzionare anche sulle piattaforme desktop. Questo metodo di rendering è ottimizzato per avere buone prestazioni sulle GPU mobili. Le GPU mobili hanno un'architettura molto diversa rispetto alle GPU desktop, a causa dei loro vincoli relativi al consumo di batteria, al calore e ai limiti generali di banda per leggere e scrivere dati. Anche gli shader di calcolo hanno un supporto molto limitato oppure non sono supportati affatto. Di conseguenza, il renderer mobile utilizza esclusivamente shader raster (frammento/vertice).
A differenza delle GPU desktop, le GPU mobili eseguono un tile-based rendering. Invece di renderizzare l'intera immagine come un'unica unità, l'immagine è suddivisa in tasselli più piccoli che si adattano alla memoria interna più veloce della GPU mobile. Ogni tassello viene renderizzato e poi scritto nella texture di destinazione. Tutto questo avviene automaticamente sul driver grafico.
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.
Il primo cambiamento importante nel renderer mobile è che esso non utilizza i formati di texture RGBA16F come il renderer desktop. Utilizza invece un formato di texture UNORM R10G10B10A2. Ciò dimezza la larghezza di banda richiesta e porta a ulteriori miglioramenti, poiché l'hardware mobile spesso ottimizza ulteriormente per i formati a 32 bit. Il compromesso è che il renderer mobile ha funzionalità di HDR limitate a causa della precisione ridotta e dei valori massimi nei dati dei colori.
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.
Sulle piattaforme desktop, l'uso dei sub-pass non avrà alcun impatto sulle prestazioni. Tuttavia, questo metodo di rendering può comunque offrire prestazioni migliori di Forward+ in scene semplici grazie alla sua minore complessità e al minor consumo di banda. Ciò è particolarmente evidente sulle GPU di fascia bassa, schede grafiche integrate o applicazioni in VR.
Given its low-end focus, this rendering method does not provide high-end rendering features such as SDFGI and Volumetric fog and fog volumes. Several post-processing effects are also not available.
Compatibilità
Nota
This is the only rendering method available when using the OpenGL driver. This rendering method is not available when using Vulkan, Direct3D 12, or Metal.
This is a traditional (non-clustered) forward renderer. Internally, it is called GL Compatibility. 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 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.
Driver di rendering
Godot 4 supporta le seguenti API grafiche:
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 is used as a Vulkan loader, and Vulkan Memory Allocator is used for memory management.
Both the Forward+ and Mobile Metodi di rendering are supported when using the Vulkan driver.
Creazione di contesto in Vulkan:
Creazione di contesto in Direct3D:
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 Metodi di rendering can be used with Direct3D 12.
Shader principali are shared with the Vulkan renderer. Shaders are transpiled from SPIR-V to DXIL using Mesa NIR (more information).
This driver is still experimental and only available in Godot 4.3 and later. 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 for more information.
Metal
Godot provides a native Metal driver that works on all Apple Silicon hardware (macOS ARM). Compared to using the MoltenVK translation layer, this is significantly faster, particularly in CPU-bound scenarios.
Both the Forward+ and Mobile Metodi di rendering can be used with Metal.
Shader principali are shared with the Vulkan renderer. Shaders are transpiled from GLSL to MSL using SPIRV-Cross.
Godot also supports Metal rendering via MoltenVK, which is used as a fallback when native Metal support is not available (e.g. on x86 macOS).
This driver is still experimental and only available in Godot 4.4 and later. See the pull request that introduced Metal support for more information.
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.
It is possible to use OpenGL ES 3.0 directly on desktop platforms
by passing the --rendering-driver opengl3_es command line argument, although this
will only work on graphics drivers that feature native OpenGL ES support (such
as Mesa).
Only the Compatibilità rendering method can be used with the OpenGL driver.
Shader principali are entirely different from the Vulkan renderer.
Many advanced features are not supported with this driver, as it targets low-end devices first and foremost.
Summary of rendering drivers/methods
The following rendering API + rendering method combinations are currently possible:
Vulkan + Forward+ (optionally through MoltenVK on macOS and iOS)
Vulkan + Mobile (optionally through MoltenVK on macOS and iOS)
Direct3D 12 + Forward+
Direct3D 12 + Mobile
Metal + Forward+
Metal + Mobile
OpenGL + Compatibility (optionally through ANGLE on Windows and macOS)
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
Nota
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, Direct3D 12, or Metal 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 WebGPU.
Implementazione di RenderingDevice in Vulkan:
Implementazione di RenderingDevice in Direct3D 12:
Implementazione di RenderingDevice in Metal:
Core rendering classes architecture
This diagram represents the structure of rendering classes in Godot, including the RenderingDevice abstraction:
Shader principali
Mentre gli shader nei progetti Godot vengono scritti attraverso un linguaggio personalizzato ispirato a GLSL, gli shader principali vengono scritti direttamente 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.
Avvertimento
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
VGPR 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 and Branching on a GPU blog posts for more information.
Shader dei materiali GLSL principali:
Forward+: servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
Mobile: servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
Compatibilità: drivers/gles3/shaders/scene.glsl
Generazione di shader per i materiali:
Altri shader GLSL per i metodi di rendering Forward+ e Mobile:
Altri shader GLSL per il metodo di rendering Compatibilità:
2D and 3D rendering separation
Nota
The following is only applicable in the Forward+ and Mobile rendering methods, not in Compatibility. Multiple Viewports can be used to emulate this when using the Compatibility renderer, or to perform 2D resolution scaling.
2D and 3D are rendered to separate buffers, as 2D rendering in Godot is performed in LDR sRGB-space while 3D rendering uses HDR linear space.
The color format used for 2D rendering is RGB8 (RGBA8 if the Transparent property on the Viewport is enabled). 3D rendering uses a 24-bit unsigned normalized integer depth buffer, or 32-bit signed floating-point if a 24-bit depth buffer is not supported by the hardware. 2D rendering does not use a depth buffer.
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:
FSR 1.0:
Tecniche di rendering 2D
2D light rendering is performed in a single pass to allow for better performance with large amounts of lights.
All rendering methods feature 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 a 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:
Tecniche di rendering 3D
Batching and instancing
In the Forward+ renderer, Vulkan instancing is used to group rendering of identical opaque or alpha-tested objects for performance. (Alpha-blended objects are never instanced.) This is not as fast as static mesh merging, but it still allows instances to be culled individually.
Rendering di luce, decalcomanie e sonde di riflessione
Nota
Decal rendering is currently not available in the Compatibility renderer.
The Forward+ renderer 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).
Il renderer Mobile utilizza un approccio di illuminazione a passaggio singolo, con un limite di 8 OmniLight + 8 SpotLight per ogni risorsa Mesh (oltre a un limite di 256 OmniLight + 256 SpotLight nella vista della telecamera). Questi limiti sono codificati e non si possono cambiare nelle impostazioni del progetto.
Il renderer Compatibilità utilizza un approccio di illuminazione ibrido a passo singolo + multi-passaggio. Le luci senza ombre sono renderizzate in un singolo passaggio. Le luci con ombre sono renderizzate in più passaggi. Questo è necessario per motivi di prestazioni sui dispositivi mobili. Pertanto, le prestazioni non scalano bene con molte luci che proiettano ombre. Si consiglia di avere solo poche luci con ombre alla volta nel tronco della telecamera e di distribuirle in modo che ogni oggetto sia influenzato da 1 o 2 luci con ombre alla volta. Il numero massimo di luci visibili alla volta si può regolare nelle impostazioni del progetto.
In tutti e 3 i metodi, le luci senza ombre sono molto più performanti di quelle con ombre. Per migliorare le prestazioni, le luci vengono aggiornate solo quando vengono modificate esse o gli oggetti nel loro raggio. Godot attualmente non separa il rendering delle ombre statiche dal rendering delle ombre dinamiche, ma ciò è previsto in una versione futura.
Il clustering è utilizzato anche per il rendering delle sonde di riflessione e delle decalcomanie nel renderer Forward+.
Mappatura delle ombre
Sia il metodo Forward+ sia il metodo Mobile utilizzano il filtro PCF per filtrare le mappe delle ombre e creare una penombra sfocata. Invece di utilizzare un pattern PCF fisso, questi metodi utilizzano un pattern a disco di Vogel, il che consente di cambiare il numero di campioni e di cambiarne gradualmente la qualità.
Godot supporta anche il percentage-closer soft shadows (PCSS) per renderizzare la penombra delle ombre in modo più realistico. Le ombre PCSS sono limitate al renderer Forward+, in quanto sono troppo esigenti per essere utilizzabili nel renderer Mobile. Anche PCSS utilizza un kernel a forma di disco di Vogel.
Inoltre, entrambe le tecniche di mappatura delle ombre ruotano il kernel pixel per pixel, al fine di attenuare gli artefatti di sottocampionamento.
Il renderer Compatibilità supporta la mappatura delle ombre per le luci DirectionalLight3D, OmniLight3D e SpotLight3D.
Antialiasing temporale
Nota
Disponibile solo nel renderer Forward+, non nei renderer Mobile o Compatibilità.
Godot utilizza un'implementazione personalizza del TAA, basata sulla vecchia implementazione del TAA di Spartan Engine.
L'antialiasing temporale richiede vettori di movimento per funzionare. Se i vettori di movimento non vengono generati correttamente, si verificherà un effetto ghosting quando la telecamera o gli oggetti si muovono.
I vettori di movimento vengono generati sulla GPU nello shader del materiale principale. Questo è fatto eseguendo il vertex shader corrispondente al frame renderizzato precedente (con la trasformazione della telecamera precedente) in aggiunta al vertex shader del frame attualmente renderizzato, poi memorizzando la differenza tra i due in un buffer di colore.
In alternativa, FSR 2.2 può essere utilizzato come soluzione di sovracampionamento che fornisce anche un proprio algoritmo di antialiasing temporale. FSR 2.2 è implementato sopra l'astrazione di RenderingDevice anziché utilizzare direttamente il codice di riferimento di AMD.
TAA resolve:
FSR 2.2:
Illuminazione globale
Nota
VoxelGI e SDFGI sono disponibili solo nel renderer Forward+, non nei renderer Mobile o Compatibilità.
La preparazione delle LightmapGI è disponibile solo nei renderer Forward+ e Mobile e si può eseguire solo all'interno dell'editor (non in un progetto esportato). Il rendering delle LightmapGI è supportato dal renderer Compatibilità.
Godot supporta l'illuminazione globale basata su voxel (VoxelGI), quella basata su signed distance field (SDFGI) e la preparazione e il rendering delle lightmap (LightmapGI). Queste tecniche si possono utilizzare simultaneamente, se desiderato.
La preparazione delle lightmap avviene sulla GPU attraverso shader di calcolo Vulkan. Il lightmapper basato sulla GPU è implementato nella classe LightmapperRD, la quale eredita dalla classe Lightmapper. Ciò consente di implementare lightmapper aggiuntivi, preparando la via per un futuro port del lightmapper basato sulla CPU presente in Godot 3.x. Ciò consentirebbe la preparazione delle lightmap mentre si utilizza il renderer Compatibilità.
Codice C++ fondamentale di GI:
scene/3d/voxel_gi.cpp - Nodo VoxelGI
editor/plugins/voxel_gi_editor_plugin.cpp - Interfaccia grafica nell'editor per i nodi VoxelGI
Shader GLSL fondamentali di GI:
servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl
servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl - Modalità disegno di debug per VoxelGI
servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl - Modalità debug di disegno per cascate SDFGI
servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl - Modalità debug di disegno per sonde SDFGI
servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl
servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
Codice C++ di Lightmapper:
scene/3d/lightmap_gi.cpp - Nodo LightmapGI
editor/plugins/lightmap_gi_editor_plugin.cpp - Interfaccia grafica nell'editor per i nodi LightmapGI
scene/3d/lightmapper.cpp - Classe astratta
modules/lightmapper_rd/lightmapper_rd.cpp - Implementazione di lightmapper basato sulla GPU
Shader GLSL di Lightmapper:
Profondità di campo
Nota
Disponibile solo nel renderer Forward+ e Mobile, non nel renderer Compatibilità.
I renderer Forward+ e Mobile utilizzano approcci diversi per renderizzare la DOF (profondità di campo), con risultati visivi diversi. Ciò si fa per adattarsi al meglio alle caratteristiche prestazionali dell'hardware di destinazione. In Forward+, la DOF viene eseguita attraverso uno shader di calcolo. In Mobile, la DOF viene eseguita attraverso uno shader di frammento (raster).
Sono disponibili forme bokeh a rettangolo, esagono e cerchio (dalla più veloce alla più lenta). La profondità di campo si può facoltativamente cambiare a ogni frame per migliorarne l'aspetto quando l'antialiasing temporale è abilitato.
Codice C++ della profondità di campo:
Shader GLSL della profondità di campo (calcolo - utilizzato per Forward+):
Shader GLSL della profondità di campo (raster - utilizzato per Mobile):
Effetti nello spazio dello schermo (SSAO, SSIL, SSR, SSS)
Nota
Disponibile solo nel renderer Forward+, non nei renderer Mobile o Compatibilità.
Il renderer Forward+ supporta l'occlusione ambientale nello spazio dello schermo, l'illuminazione indiretta nello spazio dello schermo, i riflessi nello spazio dello schermo e il subsurface scattering.
SSAO utilizza un'implementazione derivata da ASSAO di Intel (convertito in Vulkan). SSIL è derivato da SSAO per fornire illuminazione indiretta ad alte prestazioni.
Quando sono abilitati sia SSAO sia SSIL, certe parti di SSAO e SSIL sono condivise per ridurre l'impatto sulle prestazioni.
Come predefinito, SSAO e SSIL vengono eseguiti a metà risoluzione per migliorare le prestazioni. SSR viene sempre eseguito a metà risoluzione per migliorare le prestazioni.
Codice C++ per gli effetti nello spazio dello schermo:
Shader GLSL per l'occlusione ambientale nello spazio dello schermo:
servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
Shader GLSL per illuminazione indiretta nello spazio dello schermo:
servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
Shader GLSL per i riflessi nello spazio dello schermo:
servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
GLSL per subsurface scattering:
Rendering del cielo
Vedi anche
Godot supporta l'utilizzo di shader per renderizzare lo sfondo di cielo. La mappa di radianza (utilizzata per fornire luce ambientale e riflessi per i materiali PBR) è aggiornata automaticamente in base allo shader del cielo.
Le risorse SkyMaterial come ProceduralSkyMaterial, PhysicalSkyMaterial e PanoramaSkyMaterial generano uno shader integrato per renderizzare il cielo. Ciò è simile a quanto fornito da BaseMaterial3D per i materiali delle scene 3D.
Un'implementazione tecnica dettagliata si può trovare nell'articolo Custom sky shaders in Godot 4.0.
Codice C++ del rendering del cielo:
servers/rendering/renderer_rd/environment/sky.cpp - Rendering del cielo
scene/resources/sky.cpp - Risorsa Sky (da non confondere con il rendering del cielo)
scene/resources/sky_material.cpp Risorse SkyMaterial (utilizzate nella risorsa Sky)
Shader GLSL per il rendering del cielo:
Nebbia volumetrica
Nota
Disponibile solo nel renderer Forward+, non nei renderer Mobile o Compatibilità.
Vedi anche
Godot supporta un approccio froxel (frustum-aligned voxel) per il rendering della nebbia volumetrica. A differenza di un filtro di post-elaborazione, questo approccio è più generico, in quanto può funzionare con qualsiasi tipo di luce. La nebbia può anche utilizzare shader per un comportamento personalizzato, il che consente di animarla o di utilizzare una texture 3D per rappresentarne la densità.
La risorsa FogMaterial genera uno shader integrato per i nodi FogVolume. È simile a quanto fornito da BaseMaterial3D per i materiali delle scene 3D.
Una spiegazione tecnica dettagliata si può trovare nell'articolo Fog Volumes arrive in Godot 4.0.
Codice C++ per nebbia volumetrica:
servers/rendering/renderer_rd/environment/fog.cpp - Nebbia volumetrica generale
scene/3d/fog_volume.cpp - Nodo FogVolume
scene/resources/fog_material.cpp - Risorsa FogMaterial (utilizzata da FogVolume)
Shader GLSL per nebbia volumetrica:
Occlusion culling
Sebbene le GPU moderne riescano a disegnare tantissimi triangoli, il numero di draw call nelle scene complesse può comunque essere un collo di bottiglia (persino con Vulkan, Direct3D 12 e Metal).
Godot 4 supporta l'occlusion culling per ridurre l'overdraw (quando il depth prepass è disabilitato) e il rendimento dei vertici. Ciò avviene rasterizzando un buffer a bassa risoluzione sulla CPU tramite Embree. La risoluzione del buffer dipende dal numero di thread della CPU sul sistema, poiché questa operazione è eseguita in parallelo. Questo buffer include le forme di occlusione preparate nell'editor o create in fase di esecuzione.
Poiché gli occlusori complessi possono sforzare moltissimo la CPU, gli occlusori preparati si possono semplificare automaticamente quando vengono generati nell'editor.
L'occlusion culling di Godot non supporta ancora gli occlusori dinamici, ma è comunque possibile cambiare la visibilità dei nodi OccluderInstance3D o spostarli. Tuttavia, ciò risulterà lento quando si aggiornano occlusori complessi. Pertanto, in fase di esecuzione, è meglio aggiornare gli occlusori solo se hanno forme semplici, come quadranti o cuboidi.
Questo approccio basato sulla CPU ha alcuni vantaggi rispetto ad altre soluzioni, come portali e stanze oppure una soluzione di culling basata sulla GPU:
Non è richiesta alcuna configurazione manuale (ma è possibile regolarla manualmente per ottenere le migliori prestazioni).
Nessun ritardo di frame, il che è problematico nelle cutscene durante i cambi di inquadratura, o quando la telecamera si muove velocemente dietro un muro.
Funziona allo stesso modo su tutti i driver e metodi di rendering, senza comportamenti imprevedibili che dipendono dal driver o dall'hardware GPU.
L'occlusion culling è eseguito registrando le mesh occlusori, utilizzando i nodi di OccluderInstance3D (che a loro volta utilizzano le risorse di Occluder3D). RenderingServer esegue quindi l'occlusion culling chiamando Embree in RendererSceneOcclusionCull.
Codice C++ per occlusion culling:
Campo di visibilità (LOD)
Godot supporta il livello di dettaglio gerarchico (HLOD) creato manualmente, con distanze specificate dall'utente nell'ispettore.
In RenderingSceneCull, le funzioni _scene_cull() e _render_scene() sono quelle in cui avviene maggiormente la determinazione del LOD. Ogni viewport può renderizzare la stessa mesh con LOD diversi (per consentire al rendering a schermo diviso di apparire corretto).
Codice C++ di campo di visibilità:
LOD automatico di mesh
La classe ImporterMesh è utilizzata per la procedura di importazione delle mesh 3D nell'editor. La sua funzione generate_lods() gestisce la generazione attraverso la libreria meshoptimizer.
La generazione dei mesh LOD genera anche mesh di ombre allo stesso tempo. Queste sono mesh i cui vertici sono saldati a prescindere da smussatura e materiali. Ciò è utilizzato per migliorare le prestazioni di rendering delle ombre, riducendo il rendimento dei vertici necessari per renderizzarle.
La funzione _render_scene() della classe RenderingSceneCull determina quale LOD della mesh utilizzare durante il rendering. Ogni viewport può renderizzare la stessa mesh con LOD diversi (per consentire al rendering a schermo diviso di apparire corretto).
Il LOD della mesh viene scelto automaticamente secondo una metrica di copertura dello schermo. Questa tiene conto dei cambiamenti di risoluzione e del campo visivo della telecamera, senza richiedere l'intervento dell'utente. Il moltiplicatore di soglia si può regolare nelle impostazioni del progetto.
Per migliorare le prestazioni, anche il rendering delle ombre e delle sonde di riflessione scelgono le proprie soglie degli LOD di mesh (le quali possono essere diverse dal rendering della scena principale).
Codice C++ della generazione dei LOD di mesh all'importazione:
Codice C++ della determinazione dei LOD: