Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGLRenderer: Add support for AgX Tone Mapping #27366

Merged
merged 20 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/webgl_tonemapping.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
Reinhard: THREE.ReinhardToneMapping,
Cineon: THREE.CineonToneMapping,
ACESFilmic: THREE.ACESFilmicToneMapping,
AGX: THREE.AGXToneMapping,
Custom: THREE.CustomToneMapping
};

Expand Down
3 changes: 2 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export const LinearToneMapping = 1;
export const ReinhardToneMapping = 2;
export const CineonToneMapping = 3;
export const ACESFilmicToneMapping = 4;
export const CustomToneMapping = 5;
export const AGXToneMapping = 5;
export const CustomToneMapping = 6;
gkjohnson marked this conversation as resolved.
Show resolved Hide resolved
export const AttachedBindMode = 'attached';
export const DetachedBindMode = 'detached';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,77 @@ vec3 ACESFilmicToneMapping( vec3 color ) {

}

// AGX Tone Mapping implementation from
// https://iolite-engine.com/blog_posts/minimal_agx_implementation
// https://www.shadertoy.com/view/cd3XWr
// Mean error^2: 3.6705141e-06
vec3 agxDefaultContrastApprox( vec3 x ) {

vec3 x2 = x * x;
vec3 x4 = x2 * x2;

return + 15.5 * x4 * x2
- 40.14 * x4 * x
+ 31.96 * x4
- 6.868 * x2 * x
+ 0.4298 * x2
+ 0.1191 * x
- 0.00232;

}

vec3 agx( vec3 val ) {

const mat3 agx_mat = mat3(
0.842479062253094, 0.0423282422610123, 0.0423756549057051,
0.0784335999999992, 0.878468636469772, 0.0784336,
0.0792237451477643, 0.0791661274605434, 0.879142973793104
);

const float min_ev = -12.47393f;
const float max_ev = 4.026069f;

// Input transform (inset)
val = agx_mat * val;

// Log2 space encoding
val = clamp(log2(val), min_ev, max_ev);
val = (val - min_ev) / (max_ev - min_ev);

// Apply sigmoid function approximation
val = agxDefaultContrastApprox(val);

return val;

}

vec3 agxEotf( vec3 val ) {

const mat3 agx_mat_inv = mat3(
1.19687900512017, -0.0528968517574562, -0.0529716355144438,
-0.0980208811401368, 1.15190312990417, -0.0980434501171241,
-0.0990297440797205, -0.0989611768448433, 1.15107367264116
);

// Inverse input transform (outset)
val = agx_mat_inv * val;

// sRGB IEC 61966-2-1 2.2 Exponent Reference EOTF Display
// NOTE: We're linearizing the output here. Comment/adjust when
// *not* using a sRGB render target
val = pow(val, vec3(2.2));

return val;

}

vec3 AGXToneMapping( vec3 color ) {

color = agx( color );
color = agxEotf( color );
return color;

}

vec3 CustomToneMapping( vec3 color ) { return color; }
`;
6 changes: 5 additions & 1 deletion src/renderers/webgl/WebGLProgram.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { WebGLUniforms } from './WebGLUniforms.js';
import { WebGLShader } from './WebGLShader.js';
import { ShaderChunk } from '../shaders/ShaderChunk.js';
import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, CubeRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, CustomToneMapping, ReinhardToneMapping, LinearToneMapping, GLSL3, LinearSRGBColorSpace, SRGBColorSpace, LinearDisplayP3ColorSpace, DisplayP3ColorSpace, P3Primaries, Rec709Primaries } from '../../constants.js';
import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, CubeRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, AGXToneMapping, ACESFilmicToneMapping, CineonToneMapping, CustomToneMapping, ReinhardToneMapping, LinearToneMapping, GLSL3, LinearSRGBColorSpace, SRGBColorSpace, LinearDisplayP3ColorSpace, DisplayP3ColorSpace, P3Primaries, Rec709Primaries } from '../../constants.js';
import { ColorManagement } from '../../math/ColorManagement.js';

// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
Expand Down Expand Up @@ -120,6 +120,10 @@ function getToneMappingFunction( functionName, toneMapping ) {
toneMappingName = 'ACESFilmic';
break;

case AGXToneMapping:
toneMappingName = 'AGX';
break;

case CustomToneMapping:
toneMappingName = 'Custom';
break;
Expand Down
2 changes: 1 addition & 1 deletion test/unit/src/constants.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default QUnit.module( 'Constants', () => {
assert.equal( Constants.ReinhardToneMapping, 2, 'ReinhardToneMapping is equal to 2' );
assert.equal( Constants.CineonToneMapping, 3, 'CineonToneMapping is equal to 3' );
assert.equal( Constants.ACESFilmicToneMapping, 4, 'ACESFilmicToneMapping is equal to 4' );
assert.equal( Constants.CustomToneMapping, 5, 'CustomToneMapping is equal to 5' );
assert.equal( Constants.CustomToneMapping, 6, 'CustomToneMapping is equal to 6' );
gkjohnson marked this conversation as resolved.
Show resolved Hide resolved

assert.equal( Constants.AttachedBindMode, 'attached', 'AttachedBindMode is equal to attached' );
assert.equal( Constants.DetachedBindMode, 'detached', 'DetachedBindMode is equal to detached' );
Expand Down