Skip to content

Commit dc20e8e

Browse files
mvaligurskyMartin Valigursky
and
Martin Valigursky
authored
Vignette support in the Compose render pass (#5867)
* Color grab pass can be used for custom render pass rendering * Vignette support in the Compose render pass * vignette in linear space --------- Co-authored-by: Martin Valigursky <[email protected]>
1 parent 286f92a commit dc20e8e

File tree

2 files changed

+129
-4
lines changed

2 files changed

+129
-4
lines changed

examples/src/examples/graphics/post-processing.mjs

+69
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,51 @@ function controls({ observer, ReactPCUI, React, jsx, fragment }) {
112112
precision: 2
113113
})
114114
)
115+
),
116+
jsx(Panel, { headerText: 'Vignette' },
117+
jsx(LabelGroup, { text: 'enabled' },
118+
jsx(BooleanInput, {
119+
type: 'toggle',
120+
binding: new BindingTwoWay(),
121+
link: { observer, path: 'data.vignette.enabled' }
122+
})
123+
),
124+
jsx(LabelGroup, { text: 'inner' },
125+
jsx(SliderInput, {
126+
binding: new BindingTwoWay(),
127+
link: { observer, path: 'data.vignette.inner' },
128+
min: 0,
129+
max: 3,
130+
precision: 2
131+
})
132+
),
133+
jsx(LabelGroup, { text: 'outer' },
134+
jsx(SliderInput, {
135+
binding: new BindingTwoWay(),
136+
link: { observer, path: 'data.vignette.outer' },
137+
min: 0,
138+
max: 3,
139+
precision: 2
140+
})
141+
),
142+
jsx(LabelGroup, { text: 'curvature' },
143+
jsx(SliderInput, {
144+
binding: new BindingTwoWay(),
145+
link: { observer, path: 'data.vignette.curvature' },
146+
min: 0.01,
147+
max: 10,
148+
precision: 2
149+
})
150+
),
151+
jsx(LabelGroup, { text: 'intensity' },
152+
jsx(SliderInput, {
153+
binding: new BindingTwoWay(),
154+
link: { observer, path: 'data.vignette.intensity' },
155+
min: 0,
156+
max: 1,
157+
precision: 2
158+
})
159+
)
115160
)
116161
);
117162
}
@@ -458,6 +503,23 @@ async function example({ canvas, deviceType, assetPath, glslangPath, twgslPath,
458503
composePass.gradingEnabled = value;
459504
}
460505
}
506+
if (pathArray[1] === 'vignette') {
507+
if (pathArray[2] === 'enabled') {
508+
composePass.vignetteEnabled = value;
509+
}
510+
if (pathArray[2] === 'inner') {
511+
composePass.vignetteInner = value;
512+
}
513+
if (pathArray[2] === 'outer') {
514+
composePass.vignetteOuter = value;
515+
}
516+
if (pathArray[2] === 'curvature') {
517+
composePass.vignetteCurvature = value;
518+
}
519+
if (pathArray[2] === 'intensity') {
520+
composePass.vignetteIntensity = value;
521+
}
522+
}
461523
});
462524

463525
data.set('data', {
@@ -477,6 +539,13 @@ async function example({ canvas, deviceType, assetPath, glslangPath, twgslPath,
477539
saturation: 1,
478540
brightness: 1,
479541
contrast: 1
542+
},
543+
vignette: {
544+
enabled: false,
545+
inner: 0.5,
546+
outer: 1.0,
547+
curvature: 0.5,
548+
intensity: 0.3
480549
}
481550
});
482551

extras/render-passes/render-pass-compose.js

+60-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const fragmentShader = `
1818
uniform vec3 brightnessContrastSaturation;
1919
2020
// for all parameters, 1.0 is the no-change value
21-
vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con)
21+
vec3 contrastSaturationBrightness(vec3 color, float brt, float sat, float con)
2222
{
2323
color = color * brt;
2424
float grey = dot(color, vec3(0.3, 0.59, 0.11));
@@ -28,6 +28,29 @@ const fragmentShader = `
2828
2929
#endif
3030
31+
#ifdef VIGNETTE
32+
33+
uniform vec4 vignetterParams;
34+
35+
float vignette(vec2 uv) {
36+
37+
float inner = vignetterParams.x;
38+
float outer = vignetterParams.y;
39+
float curvature = vignetterParams.z;
40+
float intensity = vignetterParams.w;
41+
42+
// edge curvature
43+
vec2 curve = pow(abs(uv * 2.0 -1.0), vec2(1.0 / curvature));
44+
45+
// distance to edge
46+
float edge = pow(length(curve), curvature);
47+
48+
// gradient and intensity
49+
return 1.0 - intensity * smoothstep(inner, outer, edge);
50+
}
51+
52+
#endif
53+
3154
void main() {
3255
vec4 scene = texture2D(sceneTexture, uv0);
3356
vec3 result = scene.rgb;
@@ -38,10 +61,15 @@ const fragmentShader = `
3861
#endif
3962
4063
#ifdef GRADING
41-
result = ContrastSaturationBrightness(result, brightnessContrastSaturation.x, brightnessContrastSaturation.z, brightnessContrastSaturation.y);
64+
result = contrastSaturationBrightness(result, brightnessContrastSaturation.x, brightnessContrastSaturation.z, brightnessContrastSaturation.y);
4265
#endif
4366
4467
result = toneMap(result);
68+
69+
#ifdef VIGNETTE
70+
result *= vignette(uv0);
71+
#endif
72+
4573
result = gammaCorrectOutput(result);
4674
4775
gl_FragColor = vec4(result, scene.a);
@@ -67,6 +95,16 @@ class RenderPassCompose extends RenderPassShaderQuad {
6795

6896
_shaderDirty = true;
6997

98+
_vignetteEnabled = false;
99+
100+
vignetteInner = 0.5;
101+
102+
vignetteOuter = 1.0;
103+
104+
vignetteCurvature = 0.5;
105+
106+
vignetteIntensity = 0.3;
107+
70108
_key = '';
71109

72110
constructor(graphicsDevice) {
@@ -76,6 +114,7 @@ class RenderPassCompose extends RenderPassShaderQuad {
76114
this.bloomTextureId = graphicsDevice.scope.resolve('bloomTexture');
77115
this.bloomIntensityId = graphicsDevice.scope.resolve('bloomIntensity');
78116
this.bcsId = graphicsDevice.scope.resolve('brightnessContrastSaturation');
117+
this.vignetterParamsId = graphicsDevice.scope.resolve('vignetterParams');
79118
}
80119

81120
set bloomTexture(value) {
@@ -100,6 +139,17 @@ class RenderPassCompose extends RenderPassShaderQuad {
100139
return this._gradingEnabled;
101140
}
102141

142+
set vignetteEnabled(value) {
143+
if (this._vignetteEnabled !== value) {
144+
this._vignetteEnabled = value;
145+
this._shaderDirty = true;
146+
}
147+
}
148+
149+
get vignetteEnabled() {
150+
return this._vignetteEnabled;
151+
}
152+
103153
set toneMapping(value) {
104154
if (this._toneMapping !== value) {
105155
this._toneMapping = value;
@@ -136,14 +186,16 @@ class RenderPassCompose extends RenderPassShaderQuad {
136186

137187
const key = `${this.toneMapping}` +
138188
`-${this.bloomTexture ? 'bloom' : 'nobloom'}` +
139-
`-${this.gradingEnabled ? 'grading' : 'nograding'}`;
189+
`-${this.gradingEnabled ? 'grading' : 'nograding'}` +
190+
`-${this.vignetteEnabled ? 'vignette' : 'novignette'}`;
140191

141192
if (this._key !== key) {
142193
this._key = key;
143194

144195
const defines =
145196
(this.bloomTexture ? `#define BLOOM\n` : '') +
146-
(this.gradingEnabled ? `#define GRADING\n` : '');
197+
(this.gradingEnabled ? `#define GRADING\n` : '') +
198+
(this.vignetteEnabled ? `#define VIGNETTE\n` : '');
147199

148200
const fsChunks =
149201
shaderChunks.decodePS +
@@ -168,6 +220,10 @@ class RenderPassCompose extends RenderPassShaderQuad {
168220
this.bcsId.setValue([this.gradingBrightness, this.gradingContrast, this.gradingSaturation]);
169221
}
170222

223+
if (this._vignetteEnabled) {
224+
this.vignetterParamsId.setValue([this.vignetteInner, this.vignetteOuter, this.vignetteCurvature, this.vignetteIntensity]);
225+
}
226+
171227
super.execute();
172228
}
173229
}

0 commit comments

Comments
 (0)