Git Product home page Git Product logo

love-dpbr's Introduction

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.

love-dpbr's People

Contributors

imagicthecat avatar

Stargazers

Ivan Azoyan avatar  avatar ~ avatar dennis avatar Semyon avatar れみろう avatar Steven Johnson avatar Florian Fischer avatar Marcus Thunström avatar Dawid Bugajski avatar

Watchers

Florian Fischer avatar James Cloos avatar  avatar

Forkers

wolrajhti

love-dpbr's Issues

Blend pass.

The blend pass would be a "non-solid" pass for different kind of effects, like refraction.

Ambient occlusion map.

After research, an AO map might be a good addition:

  • SSAO is costly and can be ugly (not so easy to get right)
  • the AO can be added as the blue channel of the MR map
  • with improved ambient/indirect lighting it becomes an essential effect
  • the lack of dynamic AO is probably less of an issue with a 2D workflow

Distorsion blending.

Screen-space refraction is costly; a simple distortion is enough for a lot of effects.

Improve PBR and rendering.

  • Use https://github.com/google/filament as a reference for PBR design, documentation and optimizations.
  • Exploit the constraints of 2.5D: research screen-space techniques, e.g. Alexander Sannikov's work on global illumination and shadows for PoE.

The techniques don't have to work for all kind of rendering, e.g. some effects may work very well with 2D isometric rendering and it may be worth the effort.

Sprite batch attributes support.

If easy/efficient to take optional attributes for the material pass, add support for depth per sprite (and possibly for other properties).

Ex: this would allow better batching of a 2D pseudo-isometric map without having to use a custom shader.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.