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

Add support for fog, toneMapping, colorSpace conversion and logarithmicDepthBuffer to (m)sdf shaders #5409

Merged
merged 1 commit into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions src/shaders/msdf.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
var registerShader = require('../core/shader').registerShader;
var THREE = require('../lib/three');

var VERTEX_SHADER = [
'in vec2 uv;',
'in vec3 position;',
'uniform mat4 projectionMatrix;',
'uniform mat4 modelViewMatrix;',
'#include <common>',
'#include <fog_pars_vertex>',
'#include <logdepthbuf_pars_vertex>',

'out vec2 vUV;',

'void main(void) {',
' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
' vUV = uv;',
' #include <begin_vertex>',
' #include <project_vertex>',
' #include <logdepthbuf_vertex>',
' #include <fog_vertex>',
'}'
].join('\n');

var FRAGMENT_SHADER = [
'precision highp float;',
'#include <common>',
'#include <fog_pars_fragment>',
'#include <logdepthbuf_pars_fragment>',

'uniform bool negate;',
'uniform float alphaTest;',
'uniform float opacity;',
'uniform sampler2D map;',
'uniform vec3 color;',
'in vec2 vUV;',
'out vec4 fragColor;',

'float median(float r, float g, float b) {',
' return max(min(r, g), min(max(r, g), b));',
Expand Down Expand Up @@ -50,7 +57,12 @@ var FRAGMENT_SHADER = [

' // Do modified alpha test.',
' if (alpha < alphaTest * MODIFIED_ALPHATEST) { discard; return; }',
' fragColor = vec4(color.xyz, alpha * opacity);',
' gl_FragColor = vec4(color.xyz, alpha * opacity);',

' #include <logdepthbuf_fragment>',
' #include <tonemapping_fragment>',
' #include <colorspace_fragment>',
' #include <fog_fragment>',
'}'
].join('\n');

Expand All @@ -67,9 +79,21 @@ module.exports.Shader = registerShader('msdf', {
opacity: {type: 'number', is: 'uniform', default: 1.0}
},

raw: true,

vertexShader: VERTEX_SHADER,

fragmentShader: FRAGMENT_SHADER
fragmentShader: FRAGMENT_SHADER,

init: function (data) {
this.uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib.fog,
this.initVariables(data, 'uniform')
]);
this.material = new THREE.ShaderMaterial({
uniforms: this.uniforms,
vertexShader: this.vertexShader,
fragmentShader: this.fragmentShader,
fog: true
});
return this.material;
}
});
138 changes: 67 additions & 71 deletions src/shaders/sdf.js
Original file line number Diff line number Diff line change
@@ -1,95 +1,79 @@
var registerShader = require('../core/shader').registerShader;
var THREE = require('../lib/three');

var VERTEX_SHADER = [
'in vec2 uv;',
'in vec3 position;',
'uniform mat4 projectionMatrix;',
'uniform mat4 modelViewMatrix;',
'#include <common>',
'#include <fog_pars_vertex>',
'#include <logdepthbuf_pars_vertex>',

'out vec2 vUV;',

'void main(void) {',
' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
' vUV = uv;',
' #include <begin_vertex>',
' #include <project_vertex>',
' #include <logdepthbuf_vertex>',
' #include <fog_vertex>',
'}'
].join('\n');

var FRAGMENT_SHADER = [
'precision highp float;',
'#include <common>',
'#include <fog_pars_fragment>',
'#include <logdepthbuf_pars_fragment>',

'uniform float alphaTest;',
'uniform float opacity;',
'uniform sampler2D map;',
'uniform vec3 color;',
'in vec2 vUV;',
'out vec4 fragColor;',

'#ifdef GL_OES_standard_derivatives',
' float contour(float width, float value) {',
' return smoothstep(0.5 - value, 0.5 + value, width);',
' }',
'#else',
' float aastep(float value, float afwidth) {',
' return smoothstep(0.5 - afwidth, 0.5 + afwidth, value);',
' }',
'#endif',
'float contour(float width, float value) {',
' return smoothstep(0.5 - value, 0.5 + value, width);',
'}',

// FIXME: Experimentally determined constants.
'#define BIG_ENOUGH 0.001',
'#define MODIFIED_ALPHATEST (0.02 * isBigEnough / BIG_ENOUGH)',
'#define ALL_SMOOTH 0.4',
'#define ALL_ROUGH 0.02',
'#define DISCARD_ALPHA (alphaTest / (2.2 - 1.2 * ratio))',

'void main() {',
// When we have derivatives and can get texel size for supersampling.
' #ifdef GL_OES_standard_derivatives',
' vec2 uv = vUV;',
' vec4 texColor = texture(map, uv);',
' float dist = texColor.a;',
' float width = fwidth(dist);',
' float alpha = contour(dist, width);',
' float dscale = 0.353505;',

' vec2 duv = dscale * (dFdx(uv) + dFdy(uv));',
' float isBigEnough = max(abs(duv.x), abs(duv.y));',

// When texel is too small, blend raw alpha value rather than supersampling.
// FIXME: experimentally determined constant
' if (isBigEnough > BIG_ENOUGH) {',
' float ratio = BIG_ENOUGH / isBigEnough;',
' alpha = ratio * alpha + (1.0 - ratio) * dist;',
' }',

// Otherwise do weighted supersampling.
// FIXME: why this weighting?
' if (isBigEnough <= BIG_ENOUGH) {',
' vec4 box = vec4 (uv - duv, uv + duv);',
' alpha = (alpha + 0.5 * (',
' contour(texture(map, box.xy).a, width)',
' + contour(texture(map, box.zw).a, width)',
' + contour(texture(map, box.xw).a, width)',
' + contour(texture(map, box.zy).a, width)',
' )) / 3.0;',
' }',
' vec2 uv = vUV;',
' vec4 texColor = texture(map, uv);',
' float dist = texColor.a;',
' float width = fwidth(dist);',
' float alpha = contour(dist, width);',
' float dscale = 0.353505;',

' vec2 duv = dscale * (dFdx(uv) + dFdy(uv));',
' float isBigEnough = max(abs(duv.x), abs(duv.y));',

// When texel is too small, blend raw alpha value rather than supersampling.
// FIXME: experimentally determined constant
' if (isBigEnough > BIG_ENOUGH) {',
' float ratio = BIG_ENOUGH / isBigEnough;',
' alpha = ratio * alpha + (1.0 - ratio) * dist;',
' }',

// Otherwise do weighted supersampling.
// FIXME: why this weighting?
' if (isBigEnough <= BIG_ENOUGH) {',
' vec4 box = vec4 (uv - duv, uv + duv);',
' alpha = (alpha + 0.5 * (',
' contour(texture(map, box.xy).a, width)',
' + contour(texture(map, box.zw).a, width)',
' + contour(texture(map, box.xw).a, width)',
' + contour(texture(map, box.zy).a, width)',
' )) / 3.0;',
' }',

// Do modified alpha test.
' if (alpha < alphaTest * MODIFIED_ALPHATEST) { discard; return; }',

' #else',
// When we don't have derivatives, use approximations.
' vec4 texColor = texture(map, vUV);',
' float value = texColor.a;',
// FIXME: if we understood font pixel dimensions, this could probably be improved
' float afwidth = (1.0 / 32.0) * (1.4142135623730951 / (2.0 * gl_FragCoord.w));',
' float alpha = aastep(value, afwidth);',

// Use gl_FragCoord.w to guess when we should blend.
// FIXME: If we understood font pixel dimensions, this could probably be improved.
' float ratio = (gl_FragCoord.w >= ALL_SMOOTH) ? 1.0 : (gl_FragCoord.w < ALL_ROUGH) ? 0.0 : (gl_FragCoord.w - ALL_ROUGH) / (ALL_SMOOTH - ALL_ROUGH);',
' if (alpha < alphaTest) { if (ratio >= 1.0) { discard; return; } alpha = 0.0; }',
' alpha = alpha * ratio + (1.0 - ratio) * value;',
' if (ratio < 1.0 && alpha <= DISCARD_ALPHA) { discard; return; }',
' #endif',

' fragColor = vec4(color, opacity * alpha);',
' if (alpha < alphaTest * MODIFIED_ALPHATEST) { discard; return; }',

' gl_FragColor = vec4(color, opacity * alpha);',
' #include <logdepthbuf_fragment>',
' #include <tonemapping_fragment>',
' #include <colorspace_fragment>',
' #include <fog_fragment>',
'}'
].join('\n');

Expand All @@ -105,9 +89,21 @@ module.exports.Shader = registerShader('sdf', {
opacity: {type: 'number', is: 'uniform', default: 1.0}
},

raw: true,

vertexShader: VERTEX_SHADER,

fragmentShader: FRAGMENT_SHADER
fragmentShader: FRAGMENT_SHADER,

init: function (data) {
this.uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib.fog,
this.initVariables(data, 'uniform')
]);
this.material = new THREE.ShaderMaterial({
uniforms: this.uniforms,
vertexShader: this.vertexShader,
fragmentShader: this.fragmentShader,
fog: true
});
return this.material;
}
});
Loading