Skip to content

ImagicTheCat/love-DPBR

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

love-DPBR

love-DPBR is a Deferred Physically Based Rendering LÖVE library.

At the frontier between 2D and 3D, it aims to be a simple and versatile tool to do PBR rendering. It doesn’t aim to be a 3D rendering engine.

Use case examples
  • 3D baked scene: Point&Click, title screen, etc.

  • 2D side/top views: lighting, etc.

  • 2D isometric/pseudo-isometric: proper overlapping of tiles, lighting, etc.

  • 3D meshes / SDF ray-marching: use the library as the pipeline for the final rendering

  • …​

See examples (copy the library, install MGL and launch the directory with LÖVE).

0
Figure 1. Examples video

Install

See src.

API

Module

-- Create a scene.
--
-- A scene defines a 2D-3D space (view space), parameters and data to properly
-- render each material/object. Functions requiring 3D coordinates (like a
-- point light) are in view space (defined by the projection). The default
-- projection is 2D/orthographic, with a depth of 10 and "log" normalization.
-- All passes must be called, even if not used, in that order:
--   Material -> Light -> Background -> Blend => Render
--
-- All colors must be linear unless an option for other color spaces exists.
-- If the API is too limited, it is better to write custom shaders and directly
-- call the LÖVE API and work around the library to fill the buffers (ex:
-- ray-marching SDF, different kind of textures, etc.).
--
-- w,h: render dimensions
-- settings: (optional) map of settings
--- half_float: flag, use "16f" instead of "32f" for floating-point buffers
-- return Scene
M.newScene(w, h, settings)

Scene

self.w, self.h -- dimensions
self.pass -- current pass: "idle", "material", "light", "background", "blend"
self.AA_mode -- string
self.projection, self.inv_projection -- mat4x4, columns are vectors, list of values in row-major order
self.depth_mode, self.depth -- scene depth and mode
self.material_depth_mode, self.material_depth
self.material_emission_mode, self.material_emission_max

-- deferred buffers
self.g_albedo
self.g_normal
self.g_MR
self.g_emission
self.g_depth
self.g_luma

-- Define how the scene depth is interpreted.
-- mode: string, normalization mode
--- "raw": z' = z
--- "linear": z' = z/max
--- "log": z' = log2(z+1)/log2(max+1)
-- depth: (optional) max depth (default: 1)
Scene:setDepth(mode, depth)

-- Set projection and inverse projection matrices.
-- matrix format: mat4, columns are vectors, list of values in row-major order
Scene:setProjection(projection, inv_projection)

-- Set orthographic projection (top-left origin).
-- Allows for any kind of 2D rendering, with the possibility to adjust the
-- depth of each element and perform meaningful transformations. The depth is
-- positive, view->far. Correct scene dimensions are important to keep
-- consistency for light computation (distance, etc.).
--
-- depth: scene depth
-- mode: (optional) scene depth mode (default: "log", see Scene:setDepth)
-- sw, sh: (optional) scene view dimensions (default: w, h)
Scene:setProjection2D(depth, mode, sw, sh)

-- Set ambient/indirect lighting BRDF lookup texture.
-- The BRDF integration LUT is a precomputed texture in the context of the
-- split-sum approximation for the specular part of the reflectance equation
-- (for ambient / image-based lighting). The texture is sampled with (dot(n,v),
-- roughness) and a bottom-left origin.
--
-- LUT: texture
Scene:setAmbientBRDF(LUT)

-- Set gamma used for correction.
-- (scene default: 2.2, ignored by "filmic" TMO)
Scene:setGamma(gamma)

-- Set exposure adjustment.
-- (scene default: 1)
Scene:setExposure(exposure)

-- Set tone mapping operator.
-- tmo: tone mapping operator (string)
--- "raw" (scene default)
--- "reinhard"
--- "filmic" (Jim Hejl, Richard Burgess-Dawson)
Scene:setToneMapping(tmo)

-- Configure bloom.
-- Scene default is (0.8,0.5,6.5,0.05).
--
-- threshold: level of brightness
-- knee: 0-1 (0: hard threshold, 1: soft threshold)
-- radius: bloom radius (resolution-independent)
-- intensity: bloom intensity (0 to disable bloom)
-- safe_clamp: (optional) safe color extraction (default: 1e20)
Scene:setBloom(threshold, knee, radius, intensity, safe_clamp)

-- Set material textures color profiles.
-- Scene default is "sRGB" for color/albedo and "linear" for MRA.
-- Normal, depth and emission maps must be linear (color wise).
--
-- color, MRA: color space string ("sRGB" or "linear")
Scene:setMaterialColorProfiles(color, MRA)

-- Define how the material depth is interpreted.
-- Scene default: "raw".
--
-- mode: normalization mode (see Scene:setDepth)
-- depth: (optional) max depth (default: 1)
Scene:setMaterialDepth(mode, depth)

-- Define how the material emission is interpreted.
-- Scene default: "raw".
--
-- mode: normalization mode (see Scene:setDepth)
-- max: (optional) max emission (default: 1)
Scene:setMaterialEmissionMax(mode, max)

-- Set FXAA parameters.
-- contrast_threshold: (scene default: 0.0312)
--- Trims the algorithm from processing darks.
---   0.0833 - upper limit (default, the start of visible unfiltered edges)
---   0.0625 - high quality (faster)
---   0.0312 - visible limit (slower)
--
-- relative_threshold: (scene default: 0.125)
--- The minimum amount of local contrast required to apply algorithm.
---   0.333 - too little (faster)
---   0.250 - low quality
---   0.166 - default
---   0.125 - high quality
---   0.063 - overkill (slower)
--
-- subpixel_blending: (scene default: 0.75)
--- Choose the amount of sub-pixel aliasing removal.
--- This can effect sharpness.
---   1.00 - upper limit (softer)
---   0.75 - default amount of filtering
---   0.50 - lower limit (sharper, less sub-pixel aliasing removal)
---   0.25 - almost off
---   0.00 - completely off
Scene:setFXAA(contrast_threshold, relative_threshold, subpixel_blending)

-- Set anti-aliasing mode.
-- mode: string
--- "none": disabled (scene default)
--- "FXAA": FXAA 3.11
Scene:setAntiAliasing(mode)

-- Bind canvases and shader.
-- The material pass is the process of writing the albedo/shape (RGBA), normal,
-- metalness/roughness/AO and depth/emission of objects to the G-buffer.
--
-- The albedo texture is to be used with LÖVE draw calls, it defines the albedo
-- and shape (alpha, 0 discard pixels) of the object (affected by LÖVE color).
Scene:bindMaterialPass()

-- Bind normal map.
-- The normal map must be in view space and encoded as (X,-Y,-Z) between 0-1.
-- It implies (X right, Y up, Z out) for the 2D projection (to match 2D normal
-- maps).
--
-- normal_map: 3-components texture (RGBA8 format recommended)
Scene:bindMaterialN(normal_map)

-- Bind metalness/roughness/AO map.
-- The metalness sets the material as dielectric/insulator or
-- metallic/conductor (0: dielectric, 1: metallic).
-- The roughness determines the surface roughness (0-1).
-- The ambient factor determines the final intensity of ambient/indirect
-- lighting (also known as ambient occlusion, 0: full occlusion, 1: no
-- occlusion).
--
-- MRA_map: 3-components texture (metalness + roughness + ambient factor, RGBA8 format recommended)
-- metalness: (optional) metalness factor (default: 1)
-- roughness: (optional) roughness factor (default: 1)
-- ambient: (optional) ambient factor (default: 1)
Scene:bindMaterialMRA(MRA_map, metalness, roughness, ambient)

-- Bind depth/emission map.
--
-- DE_map: 2-component texture (depth + emission, RG16/32F format recommended)
-- z: (optional) added depth (default: 0)
-- emission_factor: (optional) emission intensity factor (default: 1)
Scene:bindMaterialDE(DE_map, z, emission_factor)

-- Bind light canvas and shader (additive HDR colors/floats).
-- The light pass is the process of lighting the materials.
Scene:bindLightPass()

-- (uses LÖVE color)
Scene:drawAmbientLight(intensity)

-- Image-based lighting (IBL).
-- (uses LÖVE color)
--
-- baked_diffuse: partial diffuse irradiance cubemap (without kD and albedo)
-- baked_specular: partial specular irradiance cubemap with mipmaps in function of roughness
-- transform: (optional) mat3 rotation applied to the lookup vector (the normal) (columns are vectors, list of values in row-major order)
Scene:drawEnvironmentLight(baked_diffuse, baked_specular, intensity, transform)

-- (uses LÖVE color)
Scene:drawPointLight(x, y, z, radius, intensity)

-- (uses LÖVE color)
Scene:drawDirectionalLight(dx, dy, dz, intensity)

-- Draw emission light pass (uses LÖVE color).
-- intensity: (optional) (default: 1)
Scene:drawEmissionLight(intensity)

-- Bind raw light.
-- Used to add raw light on the light buffer with draw calls.
Scene:bindLight(intensity)

-- Bind render canvas.
-- This pass is used to fill the render background with HDR colors (floats)
-- before the final rendering. No operation is performed by default (no clear).
Scene:bindBackgroundPass()

-- Bind canvases and shader.
-- The blend pass is similar to the material pass. It is the process of
-- blending the color/shape (RGBA) of objects to the render buffer, using
-- depth/emission data. It can be used to create various effects like lighting,
-- darkening, transparency, etc.
--
-- The color texture is to be used with LÖVE draw calls, it defines the
-- color/light and shape/opacity (alpha, 0 discard pixels) of the object
-- (affected by LÖVE color and multiplied by emission).
-- Material settings and Scene:bindMaterialDE are used.
Scene:bindBlendPass()

-- Final rendering (output normalized colors).
-- target: (optional) target canvas (on screen otherwise)
Scene:render(target)

Guidance

Ambient / environment lighting

For ambient / indirect lighting, the BRDF lookup texture must be loaded. One can be generated using tools/bake.lua or the precomputed examples/BRDF_LUT.exr can be re-used (16-bit float, 512x512, 1024 samples).

For environment / IBL (image-based lighting), the partial diffuse and specular irradiance must be computed into two cubemaps.

cmftStudio can be used to compute the cubemaps:
  • Make sure to keep the HDRI in linear color space for all processing.

  • The Irradiance cubemap is the diffuse cubemap.

  • The Radiance cubemap is the specular cubemap. Unfortunately, cmft doesn’t seem to support the Cook-Torrance BRDF used in this library; the blinnBRDF lighting model is probably the closest available.

  • Very high intensity in the input HDRI can give invalid outputs, clipping may be needed.

ℹ️
The examples environment cubemaps are computed from Greenwich Park 02 from HDRIHaven.

References

PBR

The implemented PBR is mostly based on the PBR tutorials from learnopengl and this paper from Epic Games.

The filmic tone mapping operator comes from John Hable’s post.

Bloom

The implemented bloom is based on the technique explained here and take inspirations from KinoBloom and Blender EEVEE implementations.

Rough explanation
  • Bright areas are extracted from the render.

  • The result is downsampled successively N times with a 2x2 blur filter, effectively applying a 4x4 blur filter (texture bilinear filtering).

  • The result is then upsampled successively N times the same way and accumulated to each previous downsampled buffer until finally added to the render.

FXAA

The implementation is based on this tutorial about FXAA 3.11.

About

Deferred Physically Based Rendering - LÖVE library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages