Skip to content

Commit adc0d1b

Browse files
committed
Implement Reinhard and ACES tone mapping.
1 parent f02b760 commit adc0d1b

File tree

7 files changed

+123
-5
lines changed

7 files changed

+123
-5
lines changed

src/apps/ch11_voxel/ch11_voxel/FrameGraph.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ void FrameGraph::renderFinalScene(const scenic::SceneTree & aSceneTree,
223223
graphics::setUniform(program, "u_VoxelSize", aVoxelizer.mVoxelSize);
224224
graphics::setUniform(program, "u_AabbMin", aVoxelizer.mSceneAabb.leftBottomZMin());
225225

226+
graphics::setUniform(program, "u_TanHalfAperture", mFrameControl.mConeAperture.data());
227+
228+
graphics::setUniform(program, "u_ToneMapping", (GLuint)mFrameControl.mToneMapping);
229+
226230
glProgramUniform4fv(program,
227231
glGetUniformLocation(program, "u_LightingFactors"),
228232
1, &mFrameControl.mDirectDiffuseFactor);
@@ -293,6 +297,9 @@ void FrameGraph::appendUi()
293297
FrameControl::gPolygonModes.end(),
294298
[](auto aModeIt) {return graphics::to_string(*aModeIt); });
295299

300+
imguiui::addComboContinuousEnum<FrameControl::ToneMapping::_End>(
301+
"Tone Mapping", mFrameControl.mToneMapping);
302+
296303
ImGui::SliderAngle("Diffuse Cone Aperture", &mFrameControl.mConeAperture.data(), 1.f, 180.f);
297304

298305
ImGui::Checkbox("Grid Aligned Trace Origin", &mFrameControl.mGridAlign);
@@ -309,5 +316,19 @@ void FrameGraph::appendUi()
309316
}
310317

311318

319+
std::string to_string(FrameGraph::FrameControl::ToneMapping aValue)
320+
{
321+
#define STR(enumerator) case FrameGraph::FrameControl::ToneMapping::enumerator: return #enumerator
322+
switch (aValue)
323+
{
324+
STR(None);
325+
STR(Reinhard);
326+
STR(Aces);
327+
STR(AcesApprox);
328+
default:
329+
throw std::logic_error{ "Unhandled tone mapping." };
330+
}
331+
#undef STR
332+
}
312333

313334
} // namespace ad

src/apps/ch11_voxel/ch11_voxel/FrameGraph.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,19 @@ struct FrameGraph
3434
GL_FILL,
3535
};
3636

37+
enum class ToneMapping : GLuint
38+
{
39+
None,
40+
Reinhard,
41+
Aces,
42+
AcesApprox,
43+
_End/* keep last */
44+
};
45+
3746
decltype(gPolygonModes)::const_iterator mPolygonMode = gPolygonModes.begin() + 2;
47+
48+
ToneMapping mToneMapping = ToneMapping::AcesApprox;
49+
3850
math::Radian<GLfloat> mConeAperture = math::Degree<GLfloat>{30.f};
3951
bool mGridAlign = false;
4052

src/apps/ch11_voxel/ch11_voxel/Scene.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,7 @@ std::string to_string(Scene::SceneControl::Mode aValue)
643643
default:
644644
throw std::logic_error{ "Unhandled mode." };
645645
}
646+
#undef STR
646647
}
647648

648649

src/apps/ch11_voxel/ch11_voxel/Scene.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,16 @@ struct Scene
148148
// We decode a sRGB 50% white (which is also perceptually ~50%)
149149
// to linear space for computation.
150150
.mAmbientColor = math::decode_sRGB(math::hdr::gWhite<float> * 0.25f),
151+
//.mAmbientColor = math::hdr::Rgb_f{0.f, 0.f, 0.f},
151152
.mDirectionalLights = {
152153
renderer::DirectionalLight_glsl{
153154
// Sponza: strong lighting of the first level
154-
.mDirection = math::UnitVec<3, float>{ {0.1f, -0.85f, 0.51f} },
155+
//.mDirection = math::UnitVec<3, float>{ {0.1f, -0.85f, 0.51f} },
155156
// Sponza: lighting down to the lower drapes
156-
//.mDirection = math::UnitVec<3, float>{ {0.1f, -0.94f, 0.325f} },
157+
.mDirection = math::UnitVec<3, float>{ {0.1f, -0.94f, 0.325f} },
157158
// TODO: decode the srgb value to have it show correctly in Imgui
158159
// (and have it perceptually proportional to the factor)
159-
.mColors = renderer::LightColors_glsl{} * 0.5,
160+
.mColors = renderer::LightColors_glsl{} * 2.5,
160161
},
161162
},
162163
.mPointLights = {

src/apps/ch11_voxel/ch11_voxel/ShaderConstants.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ namespace ad {
3838
result.emplace_back(
3939
"CLIENT_VOXEL_MODE_IRRADIANCE "
4040
+ std::to_string((GLuint)Scene::SceneControl::Mode::VoxelsIrradiance));
41+
result.emplace_back(
42+
"CLIENT_TONEMAPPING_REINHARD "
43+
+ std::to_string((GLuint)FrameGraph::FrameControl::ToneMapping::Reinhard));
44+
result.emplace_back(
45+
"CLIENT_TONEMAPPING_ACES "
46+
+ std::to_string((GLuint)FrameGraph::FrameControl::ToneMapping::Aces));
47+
result.emplace_back(
48+
"CLIENT_TONEMAPPING_ACESAPPROX "
49+
+ std::to_string((GLuint)FrameGraph::FrameControl::ToneMapping::AcesApprox));
4150
return result;
4251
}
4352

src/apps/ch11_voxel/ch11_voxel/resources/shaders/ch11_Pbr.frag

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "shaders/LightUtilities.glsl"
1010
#include "shaders/MaterialGenericBlock.glsl"
1111
#include "shaders/PbrUtilities.glsl"
12+
#include "shaders/ToneMapping.glsl"
1213
#include "shaders/ViewProjectionBlock.glsl"
1314

1415

@@ -48,12 +49,14 @@ uniform uint u_DiffuseUvChannel;
4849
uniform uint u_NormalUvChannel;
4950
uniform uint u_MraoUvChannel;
5051

51-
uniform ivec2 u_FramebufferSize;
52+
uniform uint u_MaterialIdx;
53+
5254
uniform bool u_ApplyAo = false;
5355
uniform bool u_ApplyEnvironment;
5456
uniform bool u_ApplyNormalMap = true;
55-
uniform uint u_MaterialIdx;
57+
uniform uint u_ToneMapping;
5658

59+
uniform ivec2 u_FramebufferSize;
5760
uniform float u_VoxelSize;
5861
uniform vec3 u_AabbMin;
5962

@@ -467,5 +470,17 @@ void main(void)
467470
//
468471
// Output
469472
//
473+
switch(u_ToneMapping)
474+
{
475+
case CLIENT_TONEMAPPING_REINHARD:
476+
fragmentColor = tonemapReinhard(fragmentColor);
477+
break;
478+
case CLIENT_TONEMAPPING_ACES:
479+
fragmentColor = tonemapAces(fragmentColor);
480+
case CLIENT_TONEMAPPING_ACESAPPROX:
481+
fragmentColor = tonemapAces_approx(fragmentColor);
482+
break;
483+
// Default is none
484+
}
470485
out_Color = correctGamma(vec4(fragmentColor, albedo.a));
471486
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#if !defined(TONEMAPPING_GLSL_INCLUDE_GUARD)
2+
#define TONEMAPPING_GLSL_INCLUDE_GUARD
3+
4+
5+
vec3 tonemapReinhard(vec3 aColor)
6+
{
7+
return aColor / (aColor + 1);
8+
}
9+
10+
//
11+
// ACES
12+
// see: https://github.com/TheRealMJP/BakingLab/blob/v1.0/BakingLab/ACES.hlsl
13+
// note: GLSL matrices are column major, so the literal value is transposed
14+
//
15+
16+
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
17+
const mat3 ACESInputMat = mat3(
18+
0.59719, 0.07600, 0.02840,
19+
0.35458, 0.90834, 0.13383,
20+
0.04823, 0.01566, 0.83777
21+
);
22+
23+
// ODT_SAT => XYZ => D60_2_D65 => sRGB
24+
const mat3 ACESOutputMat = mat3(
25+
1.60475, -0.10208, -0.00327,
26+
-0.53108, 1.10813, -0.07276,
27+
-0.07367, -0.00605, 1.07602
28+
);
29+
30+
vec3 RRTAndODTFit(vec3 v)
31+
{
32+
vec3 a = v * (v + 0.0245786f) - 0.000090537f;
33+
vec3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
34+
return a / b;
35+
}
36+
37+
vec3 tonemapAces(vec3 aColor)
38+
{
39+
aColor = ACESInputMat * aColor;
40+
aColor = RRTAndODTFit(aColor);
41+
aColor = ACESOutputMat * aColor;
42+
return clamp(aColor, 0, 1);
43+
}
44+
45+
vec3 tonemapAces_approx(vec3 v)
46+
{
47+
v *= 0.6f;
48+
float a = 2.51f;
49+
float b = 0.03f;
50+
float c = 2.43f;
51+
float d = 0.59f;
52+
float e = 0.14f;
53+
return clamp(
54+
(v*(a*v+b)) / (v*(c*v+d)+e),
55+
0, 1);
56+
}
57+
58+
59+
#endif //include guard

0 commit comments

Comments
 (0)