Skip to content

Commit

Permalink
Add support for fog, toneMapping, colorSpace conversion and logarithm…
Browse files Browse the repository at this point in the history
…icDepthBuffer to (m)sdf shaders
  • Loading branch information
mrxz committed Dec 11, 2023
1 parent 4e53a98 commit 85bf174
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 82 deletions.
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;
}
});

0 comments on commit 85bf174

Please sign in to comment.