Author: https://t.me/martianov
This project demonstrates a full deferred rendering pipeline in Defold with support for G-buffer, SSAO, point light shadows, volumetric light, and filmic tonemapping. You can use the project as a foundation for your own scenes and renderers.
- G‑Buffer: writing albedo, normals (oct-encoding), and depth into separate buffers for subsequent lighting.
- SSAO: screen-space ambient occlusion with position reconstruction from depth, oriented kernels, and smoothing.
- Point light shadows: rendering shadow cubemaps into an atlas (6 faces per light).
- Volumetric light: simple integration of scattering along the camera ray, light “glow”.
- PBR lighting (simplified): Lambertian diffuse + base F0, BRDF stubs.
- Filmic tonemapping: gentle mapping of HDR lighting into LDR.
- Render scaling: automatic resizing of targets to the window size.
- Flexible scene: free-fly camera, multiple point lights, a set of objects and materials.
Rendering is performed in several passes and assembled in render.render_script:
- G‑Buffer (
Assets/Materials/Deferred/GBuffer/*)- In
GBuffer.fpalbedo is sampled from a texture, the normal is reconstructed from a normal map in world space and encoded into 2 channels (oct-encoding, seeModules/NormalCoder.glsl). InGBuffer.vpvaryings and matrices are prepared. - Result: COLOR0 = albedo (premultiplied alpha), COLOR1 = normals.xy + roughness.z, DEPTH = depth.
- In
- Cubemap shadows (
Assets/Materials/Deferred/DepthPass/*)- For every point light, 6 faces are rendered into the shared atlas using
RenderScriptToolkit.render_multi_cubemapand theDepthPassmaterial.
- For every point light, 6 faces are rendered into the shared atlas using
- SSAO (
Assets/Materials/Deferred/SSAOPass/*)- In
SSAOPass.fpposition is reconstructed from depth, normals are decoded; random directions are chosen from the kernel/noise (Modules/SSAOUtils.luagenerates u_ssaoKernel/u_ssaoNoise). The output is a single‑channel AO map.
- In
- Lighting (
Assets/Materials/Deferred/LightingPass/*)- In
LightingPass.fpworld positions are reconstructed, normals are decoded, SSAO is applied, arrays of light sources are iterated, BRDF is evaluated, shadows are applied (see modules inAssets/Materials/Deferred/Modules/*), volumetric light and tonemapping are applied.
- In
- Composition to screen
- The lighting result is output to a separate render target and then drawn onto the
RenderRootsprite stretched to the window size.
- The lighting result is output to a separate render target and then drawn onto the
render.render_script— the main render script. Manages targets, passes, materials, and ties all pipeline stages together.Render.render— the list of materials attached to the render script.Modules/Render/Backend/Nodes/RenderRoot.*— wrapper node for presenting the final image; reacts to window resize and reports it to the renderer.Modules/RenderScriptToolkit.lua— rendering utilities: create/bind targets, draw fullscreen quad, render cubemaps, etc.Modules/Camera.lua— simple camera with perspective projection and frustum update.Modules/SSAOUtils.lua— kernel and noise generation for SSAO.Materials/RenderRoot.*,Shaders/RenderRoot.*— material/shaders of the screen sprite.
Modules/Render/Scene/Nodes/Camera.go+Camera.script— free‑fly camera (WASD + mouse), sendscamera_updateto the renderer.Nodes/Light.go+Light.script— point lights (color, intensity, radii), sendcreate_point_lightto the renderer.Materials/Billboard.*— light icon visualization.
Assets/Materials/Deferred/GBuffer/*,SSAOPass/*,DepthPass/*,LightingPass/*— materials and shaders of all passes.Modules/*.glsl— reusable GLSL modules: normal encoder, lighting utilities, SSAO, shadows, volumetric light, filmic, etc.
Objects/*— example scene objects (models, materials with albedo/normal/roughness).Main.collection— scene with camera, lights, level meshes, and attachedRenderRoot.
- Messages to the renderer:
camera_update— camera view/projection matrices and transform.set_render_size— new window size → re‑create/resize targets, update projection.create_point_light— add a point light (position, color, intensity, radii).
- Buffers:
camera_render_target(G‑Buffer): COLOR0 albedo, COLOR1 normals+roughness, DEPTH depth.ssao_render_target: AO map at half resolution.light_shadowmap: shadow cubemap atlas RGBA32F + DEPTH.
- Light arrays (in
LightingPass.fp):light_position_array,light_color_array,light_properties_array(intensity, surface radius, volume radius).
- Open the project in Defold.
- Make sure
Main.collectionis the startup collection. - Run the project. The camera is controlled by WASD + mouse (sensitivity/speed in
Modules/Render/Scene/Nodes/Camera.script). - Window resize automatically rebuilds render targets; the final image is stretched onto
RenderRoot.
- Add a model to
Assets/Meshesand PBR textures (albedo/normal/roughness) toAssets/Textures. - Define a material in
Assets/Materials/Scenes/model.materialand bind textures to samplersalbedo,normal,roughness. - Create a GO/collection in
Objectsand place it intoMain.collection.
- Currently, shadows are rendered in real time and for all light sources. For optimization, you can later refine this so that shadows are not processed for some lights, or are rendered only when the player is nearby.
- Reduce
ssao_render_targetsize to speed up SSAO. - Reduce
light_shadowmapsize or the number of light sources. - Limit
light_countor use clustering/tiling (future work). - Move part of calculations to half‑precision where possible.
- Shadows: basic sampling without PCF/PCSS filtering (configured in
lighting_shadow.glsl). - BRDF: simplified diffuse, without a full metallic/specular pipeline.
- Volumetric light: simplified integration, without multi‑sample phase functions and multiple scattering.
Use freely for educational and prototyping purposes. Textures and models are taken from publicly available sources — check their licenses when distributing.
