Skip to content

Commit f44d59a

Browse files
authored
Merge pull request #2547 from riccardobl/khxtonemap
KHR pbr neutral tonemap
2 parents 24d3649 + bbbb434 commit f44d59a

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

jme3-core/src/main/resources/Common/ShaderLib/Hdr.glsllib

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,30 @@ vec3 HDR_ToneMap(in vec3 color, in float lumAvg, in float a, in float white){
6262
vec3 HDR_ToneMap2(in vec3 color, in float lumAvg, in float a, in float white){
6363
float scale = a / (lumAvg + 0.001);
6464
return (vec3(scale) * color) / (color + vec3(1.0));
65+
}
66+
67+
// Based on https://github.com/KhronosGroup/ToneMapping/blob/main/PBR_Neutral/pbrNeutral.glsl
68+
// Input color is non-negative and resides in the Linear Rec. 709 color space.
69+
// Output color is also Linear Rec. 709, but in the [0, 1] range.
70+
vec3 HDR_KHRToneMap(in vec3 color, in vec3 exposure, in vec3 gamma) {
71+
color *= pow(vec3(2.0), exposure);
72+
73+
const float startCompression = 0.8 - 0.04;
74+
const float desaturation = 0.15;
75+
76+
float x = min(color.r, min(color.g, color.b));
77+
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
78+
color -= offset;
79+
80+
float peak = max(color.r, max(color.g, color.b));
81+
if (peak < startCompression) return color;
82+
83+
const float d = 1. - startCompression;
84+
float newPeak = 1. - d * d / (peak + d - startCompression);
85+
color *= newPeak / peak;
86+
87+
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
88+
color = mix(color, newPeak * vec3(1, 1, 1), g);
89+
color = pow(color, gamma);
90+
return color;
6591
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (c) 2009-2012 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
package com.jme3.post.filters;
33+
34+
import com.jme3.asset.AssetManager;
35+
import com.jme3.export.InputCapsule;
36+
import com.jme3.export.JmeExporter;
37+
import com.jme3.export.JmeImporter;
38+
import com.jme3.export.OutputCapsule;
39+
import com.jme3.material.Material;
40+
import com.jme3.math.Vector3f;
41+
import com.jme3.post.Filter;
42+
import com.jme3.renderer.RenderManager;
43+
import com.jme3.renderer.ViewPort;
44+
import java.io.IOException;
45+
46+
/**
47+
* Tone-mapping filter that uses khronos neutral pbr tone mapping curve.
48+
*/
49+
public class KHRToneMapFilter extends Filter {
50+
51+
private static final float DEFAULT_EXPOSURE = 0.0f;
52+
private static final float DEFAULT_GAMMA = 1.0f;
53+
54+
private final Vector3f exposure = new Vector3f(DEFAULT_EXPOSURE, DEFAULT_EXPOSURE, DEFAULT_EXPOSURE);
55+
private final Vector3f gamma = new Vector3f(DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA);
56+
57+
/**
58+
* Creates a tone-mapping filter with the default exposure and gamma.
59+
*/
60+
public KHRToneMapFilter() {
61+
super("KHRToneMapFilter");
62+
}
63+
64+
65+
@Override
66+
protected boolean isRequiresDepthTexture() {
67+
return false;
68+
}
69+
70+
@Override
71+
protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
72+
material = new Material(manager, "Common/MatDefs/Post/KHRToneMap.j3md");
73+
material.setVector3("Exposure", exposure);
74+
material.setVector3("Gamma", gamma);
75+
}
76+
77+
@Override
78+
protected Material getMaterial() {
79+
return material;
80+
}
81+
82+
/**
83+
* Set the exposure for the tone mapping.
84+
*
85+
* @param whitePoint The exposure vector.
86+
*/
87+
public void setExposure(Vector3f whitePoint) {
88+
this.exposure.set(whitePoint);
89+
}
90+
91+
/**
92+
* Get the exposure for the tone mapping.
93+
*
94+
* @return The exposure vector.
95+
*/
96+
public Vector3f getExposure() {
97+
return exposure;
98+
}
99+
100+
101+
/**
102+
* Set the gamma for the tone mapping.
103+
*
104+
* @param gamma The gamma vector.
105+
*/
106+
public void setGamma(Vector3f gamma) {
107+
this.gamma.set(gamma);
108+
}
109+
110+
/**
111+
* Get the gamma for the tone mapping.
112+
*
113+
* @return The gamma vector.
114+
*/
115+
public Vector3f getGamma() {
116+
return gamma;
117+
}
118+
119+
@Override
120+
public void write(JmeExporter ex) throws IOException {
121+
super.write(ex);
122+
OutputCapsule oc = ex.getCapsule(this);
123+
oc.write(exposure, "exposure", new Vector3f(DEFAULT_EXPOSURE, DEFAULT_EXPOSURE, DEFAULT_EXPOSURE));
124+
oc.write(gamma, "gamma", new Vector3f(DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA));
125+
}
126+
127+
@Override
128+
public void read(JmeImporter im) throws IOException {
129+
super.read(im);
130+
InputCapsule ic = im.getCapsule(this);
131+
exposure.set((Vector3f)ic.readSavable("exposure", new Vector3f(DEFAULT_EXPOSURE, DEFAULT_EXPOSURE, DEFAULT_EXPOSURE)));
132+
gamma.set((Vector3f)ic.readSavable("gamma", new Vector3f(DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA)));
133+
}
134+
135+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#extension GL_ARB_texture_multisample : enable
2+
#import "Common/ShaderLib/GLSLCompat.glsllib"
3+
#import "Common/ShaderLib/Hdr.glsllib"
4+
5+
6+
uniform vec3 m_Exposure;
7+
uniform vec3 m_Gamma;
8+
varying vec2 texCoord;
9+
10+
vec3 applyCurve(in vec3 x) {
11+
return HDR_KHRToneMap(x, m_Exposure, m_Gamma);
12+
}
13+
14+
15+
#ifdef NUM_SAMPLES
16+
17+
uniform sampler2DMS m_Texture;
18+
19+
vec4 applyToneMap() {
20+
ivec2 iTexC = ivec2(texCoord * vec2(textureSize(m_Texture)));
21+
vec4 color = vec4(0.0);
22+
for (int i = 0; i < NUM_SAMPLES; i++) {
23+
vec4 hdrColor = texelFetch(m_Texture, iTexC, i);
24+
vec3 ldrColor = applyCurve(hdrColor.rgb);
25+
color += vec4(ldrColor, hdrColor.a);
26+
}
27+
return color / float(NUM_SAMPLES);
28+
}
29+
30+
#else
31+
32+
uniform sampler2D m_Texture;
33+
34+
vec4 applyToneMap() {
35+
vec4 texVal = texture2D(m_Texture, texCoord);
36+
return vec4(applyCurve(texVal.rgb) , texVal.a);
37+
}
38+
39+
#endif
40+
41+
void main() {
42+
gl_FragColor = applyToneMap();
43+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
MaterialDef KHRToneMap {
2+
3+
MaterialParameters {
4+
Int BoundDrawBuffer
5+
Int NumSamples
6+
Int NumSamplesDepth
7+
Texture2D Texture
8+
Vector3 Gamma
9+
Vector3 Exposure
10+
}
11+
12+
Technique {
13+
VertexShader GLSL300 GLSL150 GLSL100: Common/MatDefs/Post/Post.vert
14+
FragmentShader GLSL300 GLSL150 GLSL100: Common/MatDefs/Post/KHRToneMap.frag
15+
16+
WorldParameters {
17+
}
18+
19+
Defines {
20+
BOUND_DRAW_BUFFER: BoundDrawBuffer
21+
NUM_SAMPLES : NumSamples
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)