Skip to content

Commit

Permalink
Merge custom tonemappers branch
Browse files Browse the repository at this point in the history
  • Loading branch information
debian build committed Aug 8, 2024
1 parent 9225428 commit 3dc441f
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 15 deletions.
20 changes: 16 additions & 4 deletions doc/classes/Environment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -418,14 +418,14 @@
<constant name="TONE_MAPPER_LINEAR" value="0" enum="ToneMapper">
Linear tonemapper operator. Reads the linear data and passes it on unmodified. This can cause bright lighting to look blown out, with noticeable clipping in the output colors.
</constant>
<constant name="TONE_MAPPER_REINHARDT" value="1" enum="ToneMapper">
Reinhardt tonemapper operator. Performs a variation on rendered pixels' colors by this formula: [code]color = color / (1 + color)[/code]. This avoids clipping bright highlights, but the resulting image can look a bit dull.
<constant name="TONE_MAPPER_REINHARD" value="1" enum="ToneMapper">
Reinhard tonemapper operator. Performs a variation on rendered pixels' colors by this formula: [code]color = color / (1 + color)[/code]. This avoids clipping bright highlights, but the resulting image can look a bit dull.
</constant>
<constant name="TONE_MAPPER_FILMIC" value="2" enum="ToneMapper">
Filmic tonemapper operator. This avoids clipping bright highlights, with a resulting image that usually looks more vivid than [constant TONE_MAPPER_REINHARDT].
Filmic tonemapper operator. This avoids clipping bright highlights, with a resulting image that usually looks more vivid than [constant TONE_MAPPER_REINHARD].
</constant>
<constant name="TONE_MAPPER_ACES" value="3" enum="ToneMapper">
Use the Academy Color Encoding System tonemapper. ACES is slightly more expensive than other options, but it handles bright lighting in a more realistic fashion by desaturating it as it becomes brighter. ACES typically has a more contrasted output compared to [constant TONE_MAPPER_REINHARDT] and [constant TONE_MAPPER_FILMIC].
Use the Academy Color Encoding System tonemapper. ACES is slightly more expensive than other options, but it handles bright lighting in a more realistic fashion by desaturating it as it becomes brighter. ACES typically has a more contrasted output compared to [constant TONE_MAPPER_REINHARD] and [constant TONE_MAPPER_FILMIC].
[b]Note:[/b] This tonemapping operator is called "ACES Fitted" in Godot 3.x.
</constant>
<constant name="TONE_MAPPER_AGX" value="4" enum="ToneMapper">
Expand All @@ -434,6 +434,18 @@
<constant name="TONE_MAPPER_AGX_PUNCHY" value="5" enum="ToneMapper">
Use the AgX tonemapper with the "punchy" look. AgX is slightly more expensive than other options, but it handles bright lighting in a more realistic fashion by desaturating it as it becomes brighter. The punchy look increases contrast and saturation, bringing its visuals closer to [constant TONE_MAPPER_ACES].
</constant>
<constant name="TONE_MAPPER_PBR_NEUTRAL" value="6" enum="ToneMapper">
Use the Khronos PBR Neutral tonemapper. PBR Neutral handles bright lighting in a more realistic fashion by desaturating it as it becomes brighter. PBR Neutral aims to look similar to [constant TONE_MAPPER_LINEAR] while reducing the clipping of bright highlights. Unlike [constant TONE_MAPPER_ACES], original colors are preserved as much as possible. The whitepoint value is ignored with this tonemapper, as PBR Neutral does not offer a whitepoint adjustment.
</constant>
<constant name="TONE_MAPPER_HABLE" value="7" enum="ToneMapper">
Use the Uncharted 2 tonemapper (also known as Hable tonemapper). Developed by John Hable for Uncharted 2, this operator provides great contrast and color preservation. It's particularly good at handling bright specular highlights while maintaining rich mid-tones. This tonemapper offers a good balance between realism and visual appeal, often producing more vibrant results than [constant TONE_MAPPER_REINHARD] while avoiding the potential over-saturation of [constant TONE_MAPPER_FILMIC].
</constant>
<constant name="TONE_MAPPER_CINEON" value="8" enum="ToneMapper">
Use the Cineon film response curve tonemapper. This method simulates the response of traditional film, providing a cinematic look with rich shadows and controlled highlights. It's particularly effective for preserving details in high-contrast scenes and achieving a classic film aesthetic. Cineon can produce more natural-looking results in some scenarios compared to [constant TONE_MAPPER_FILMIC], especially for scenes with a wide dynamic range.
</constant>
<constant name="TONE_MAPPER_DRAGO" value="9" enum="ToneMapper">
Use Drago's adaptive logarithmic mapping tonemapper (2003). This operator provides good compression of high dynamic range images, preserving details in both dark and bright areas. It adaptively adjusts the logarithmic basis to improve local contrast. Drago's method is particularly effective for scenes with extreme luminance variations and can produce natural-looking results without the need for manual parameter tuning.
</constant>
<constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="GlowBlendMode">
Additive glow blending mode. Mostly used for particles, glows (bloom), lens flare, bright sources.
</constant>
Expand Down
12 changes: 12 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5168,6 +5168,18 @@
<constant name="ENV_TONE_MAPPER_AGX_PUNCHY" value="5" enum="EnvironmentToneMapper">
Use the AgX tonemapper with the "punchy" look. AgX is slightly more expensive than other options, but it handles bright lighting in a more realistic fashion by desaturating it as it becomes brighter. The punchy look increases contrast and saturation, bringing its visuals closer to [constant ENV_TONE_MAPPER_ACES].
</constant>
<constant name="ENV_TONE_MAPPER_PBR_NEUTRAL" value="6" enum="EnvironmentToneMapper">
Use the Khronos PBR Neutral tonemapper. PBR Neutral handles bright lighting in a more realistic fashion by desaturating it as it becomes brighter. PBR Neutral aims to look similar to [constant ENV_TONE_MAPPER_LINEAR] while reducing the clipping of bright highlights. Unlike [constant ENV_TONE_MAPPER_ACES], original colors are preserved as much as possible. The whitepoint value is ignored with this tonemapper, as PBR Neutral does not offer a whitepoint adjustment.
</constant>
<constant name="ENV_TONE_MAPPER_HABLE" value="7" enum="EnvironmentToneMapper">
Use the Uncharted 2 tonemapper (also known as Hable tonemapper). Developed by John Hable for Uncharted 2, this operator provides excellent contrast and color preservation. It's particularly good at handling bright specular highlights while maintaining rich mid-tones. This tonemapper offers a good balance between realism and visual appeal, often producing more vibrant results than [constant ENV_TONE_MAPPER_REINHARD] while avoiding the potential over-saturation of [constant ENV_TONE_MAPPER_FILMIC].
</constant>
<constant name="ENV_TONE_MAPPER_CINEON" value="8" enum="EnvironmentToneMapper">
Use the Cineon film response curve tonemapper. This method simulates the response of traditional film, providing a cinematic look with rich shadows and controlled highlights. It's effective for preserving details in high-contrast scenes and achieving a classic film aesthetic. Cineon can produce more natural-looking results in some scenarios compared to [constant ENV_TONE_MAPPER_FILMIC], especially for scenes with a wide dynamic range.
</constant>
<constant name="ENV_TONE_MAPPER_DRAGO" value="9" enum="EnvironmentToneMapper">
Use Drago's adaptive logarithmic mapping tonemapper (2003). This method compresses high dynamic range images while preserving details across the luminance range. It adaptively adjusts the logarithmic basis to enhance local contrast. Drago's operator is well-suited for scenes with extreme brightness variations, often producing natural-looking results without requiring manual parameter adjustments.
</constant>
<constant name="ENV_SSR_ROUGHNESS_QUALITY_DISABLED" value="0" enum="EnvironmentSSRRoughnessQuality">
Lowest quality of roughness filter for screen-space reflections. Rough materials will not have blurrier screen-space reflections compared to smooth (non-rough) materials. This is the fastest option.
</constant>
Expand Down
2 changes: 1 addition & 1 deletion drivers/d3d12/rendering_device_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
struct MeshShaderCapabilities {
static const uint32_t MAX_THREAD_GROUPS = 63999; // Quoting the DirectX Mesh Shader Spec: "Each of the three thread group counts must be less than 64k" so ok...
bool is_supported = false;
};
};

RenderingContextDriverD3D12 *context_driver = nullptr;
RenderingContextDriver::Device context_device;
Expand Down
93 changes: 92 additions & 1 deletion drivers/gles3/shaders/tonemap_inc.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,85 @@ vec3 tonemap_aces(vec3 color, float p_white) {
return color_tonemapped / p_white_tonemapped;
}

// Adapted from https://modelviewer.dev/examples/tone-mapping#commerce
vec3 tonemap_pbr_neutral(vec3 color) {
const float start_compression = 0.8 - 0.04;
const float desaturation = 0.15;

float x = min(color.r, min(color.g, color.b));
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
color -= offset;

float peak = max(color.r, max(color.g, color.b));
if (peak < start_compression) {
return color;
}

float d = 1.0 - start_compression;
float new_peak = 1.0 - d * d / (peak + d - start_compression);
color *= new_peak / peak;

float g = 1.0 - 1.0 / (desaturation * (peak - new_peak) + 1.0);
return mix(color, vec3(1.0, 1.0, 1.0), g);
}

// "Hable Tone Mapping" a.k.a Uncharted 2 tonemapping.
// source: https://64.github.io/tonemapping/#uncharted-2
vec3 hable_tonemap_partial(vec3 x) {
const float A = 0.15f;
const float B = 0.50f;
const float C = 0.10f;
const float D = 0.20f;
const float E = 0.02f;
const float F = 0.30f;
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}

vec3 tonemap_hable(vec3 color, float white) {
const float EXPOSURE_BIAS = 2.0f;
vec3 curr = hable_tonemap_partial(color * EXPOSURE_BIAS);

vec3 W = vec3(11.2f);
float white_padding = white;
if (white >= 1.0) {
white_padding = white + 1.0;
}
vec3 white_scale = vec3(white_padding) / hable_tonemap_partial(W);
return curr * white_scale;
}

// Optimised cineon tonemapping.
// Adapted from Three.js (MIT)
vec3 tonemap_cineon(vec3 color, float white) {
color *= white;
color = max(vec3(0.0), color - 0.004);
return pow(
(color * (6.2 * color + 0.5)) /
(color * (6.2 * color + 1.7) + 0.06),
vec3(2.2)
);
}

float luminance_drago(float L, float b) {
const float LMax = 1.0;
float Ld = b / (log(LMax + 1.0) / log(10.0));
Ld *= log(L + 1.0) / log(2.0 + 8.0 * pow((L / LMax), log(b) / log(0.5)));
return Ld;
}

// Based on the paper: "Adaptive Logarithmic Mapping For Displaying High Contrast Scenes"
// https://resources.mpi-inf.mpg.de/tmo/logmap/logmap.pdf
vec3 tonemap_drago(vec3 color, float white) {
const float BIAS = 0.85;

float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
float Ld = luminance_drago(luminance, BIAS);
color = color * (Ld / luminance);
color *= white;
return clamp(color, 0.0, 1.0);
}

>>>>>>> origin/tonemappers
// Mean error^2: 3.6705141e-06
vec3 agx_default_contrast_approx(vec3 x) {
vec3 x2 = x * x;
Expand Down Expand Up @@ -157,6 +236,10 @@ vec3 tonemap_agx(vec3 color, float white, bool punchy) {
#define TONEMAPPER_ACES 3
#define TONEMAPPER_AGX 4
#define TONEMAPPER_AGX_PUNCHY 5
#define TONEMAPPER_PBR_NEUTRAL 6
#define TONEMAPPER_HABLE 7
#define TONEMAPPER_CINEON 8
#define TONEMAPPER_DRAGO 9

vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always outputs clamped [0;1] color
// Ensure color values passed to tonemappers are positive.
Expand All @@ -171,8 +254,16 @@ vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always
return tonemap_aces(max(vec3(0.0f), color), p_white);
} else if (tonemapper == TONEMAPPER_AGX) {
return tonemap_agx(max(vec3(0.0f), color), p_white, false);
} else { // TONEMAPPER_AGX_PUNCHY
} else if (tonemapper == TONEMAPPER_AGX_PUNCHY){
return tonemap_agx(max(vec3(0.0f), color), p_white, true);
} else if (tonemapper == TONEMAPPER_PBR_NEUTRAL) {
return tonemap_pbr_neutral(max(vec3(0.0f), color));
} else if (tonemapper == TONEMAPPER_HABLE) {
return tonemap_hable(max(vec3(0.0f), color), p_white);
} else if (tonemapper == TONEMAPPER_CINEON) {
return tonemap_cineon(max(vec3(0.0f), color), white);
} else { // TONEMAPPER_DRAGO
return tonemap_drago(max(vec3(0.0f), color), white);
}
}

Expand Down
3 changes: 2 additions & 1 deletion scene/3d/lightmap_gi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,10 +1163,11 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
}
}

Lightmapper::BakeError lightmapper->bake(
Lightmapper::BakeError bake_err = lightmapper->bake(
Lightmapper::BakeQuality(effective_bake_quality),
use_denoiser,
denoiser_strength,
denoiser_range,
effective_bounces,
bounce_indirect_energy,
bias,
Expand Down
8 changes: 6 additions & 2 deletions scene/resources/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white);

ADD_GROUP("Tonemap", "tonemap_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES,AgX,AgX Punchy"), "set_tonemapper", "get_tonemapper");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES,AgX,AgX Punchy,PBR Neutral,Hable Filmic,Cineon,Drago"), "set_tonemapper", "get_tonemapper");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white");

Expand Down Expand Up @@ -1642,11 +1642,15 @@ void Environment::_bind_methods() {
BIND_ENUM_CONSTANT(REFLECTION_SOURCE_SKY);

BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR);
BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT);
BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARD);
BIND_ENUM_CONSTANT(TONE_MAPPER_FILMIC);
BIND_ENUM_CONSTANT(TONE_MAPPER_ACES);
BIND_ENUM_CONSTANT(TONE_MAPPER_AGX);
BIND_ENUM_CONSTANT(TONE_MAPPER_AGX_PUNCHY);
BIND_ENUM_CONSTANT(TONE_MAPPER_PBR_NEUTRAL);
BIND_ENUM_CONSTANT(TONE_MAPPER_HABLE);
BIND_ENUM_CONSTANT(TONE_MAPPER_CINEON);
BIND_ENUM_CONSTANT(TONE_MAPPER_DRAGO);

BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_ADDITIVE);
BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN);
Expand Down
6 changes: 5 additions & 1 deletion scene/resources/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@ class Environment : public Resource {

enum ToneMapper {
TONE_MAPPER_LINEAR,
TONE_MAPPER_REINHARDT,
TONE_MAPPER_REINHARD,
TONE_MAPPER_FILMIC,
TONE_MAPPER_ACES,
TONE_MAPPER_AGX,
TONE_MAPPER_AGX_PUNCHY,
TONE_MAPPER_PBR_NEUTRAL,
TONE_MAPPER_HABLE,
TONE_MAPPER_CINEON,
TONE_MAPPER_DRAGO,
};

enum DynamicGICascadeFormat {
Expand Down
6 changes: 4 additions & 2 deletions servers/movie_writer/movie_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,20 +191,22 @@ void MovieWriter::add_frame() {
#ifdef DEBUG_ENABLED
DisplayServer::get_singleton()->window_set_title(
vformat(
"MovieWriter: Frame %d (time: %s) - %s | real time: %s (DEBUG)",
"MovieWriter: Frame %d (time: %s) - %s (frames saved: %s) | real time: %s (DEBUG)",
Engine::get_singleton()->get_frames_drawn(),
movie_time,
project_name,
frame_to_save,
real_time
)
);
#else
DisplayServer::get_singleton()->window_set_title(
vformat(
"MovieWriter: Frame %d (time: %s) - %s | real time: %s",
"MovieWriter: Frame %d (time: %s) - %s (frames saved: %s) | real time: %s",
Engine::get_singleton()->get_frames_drawn(),
movie_time,
project_name,
frame_to_save,
real_time
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2816,6 +2816,8 @@ RenderForwardMobile::RenderForwardMobile() {
// defines += "\n#define HDDAGI_OCT_SIZE " + itos(gi.hddagi_get_lightprobe_octahedron_size()) + "\n";
defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n";
}
// defines += "\n#define HDDAGI_OCT_SIZE " + itos(gi.hddagi_get_lightprobe_octahedron_size()) + "\n";
defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(MAX_DIRECTIONAL_LIGHTS) + "\n";

{
//lightmaps
Expand Down
4 changes: 2 additions & 2 deletions servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ bool RendererSceneRenderRD::_debug_draw_can_use_effects(RS::ViewportDebugDraw p_
case RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER:
case RS::VIEWPORT_DEBUG_DRAW_SSAO:
case RS::VIEWPORT_DEBUG_DRAW_SSIL:
case RS::VIEWPORT_DEBUG_DRAW_SDFGI:
case RS::VIEWPORT_DEBUG_DRAW_HDDAGI:
case RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER:
case RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS:
can_use_effects = true;
Expand All @@ -808,7 +808,7 @@ bool RendererSceneRenderRD::_debug_draw_can_use_effects(RS::ViewportDebugDraw p_
case RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION:
case RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE:
case RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS:
case RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES:
case RS::VIEWPORT_DEBUG_DRAW_HDDAGI_PROBES:
case RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD:
can_use_effects = true;
break;
Expand Down
Loading

0 comments on commit 3dc441f

Please sign in to comment.