3d-tiles-renderer
Version:
https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification
167 lines (110 loc) • 3.47 kB
JavaScript
const OVERLAY_PARAMS = Symbol( 'OVERLAY_PARAMS' );
// before compile can be used to chain shader adjustments. Returns the added uniforms used for fading.
export function wrapOverlaysMaterial( material, previousOnBeforeCompile ) {
// if the material has already been wrapped then return the params
if ( material[ OVERLAY_PARAMS ] ) {
return material[ OVERLAY_PARAMS ];
}
const params = {
layerMaps: { value: [] },
layerInfo: { value: [] },
};
material[ OVERLAY_PARAMS ] = params;
material.defines = {
...( material.defines || {} ),
LAYER_COUNT: 0,
};
material.onBeforeCompile = shader => {
if ( previousOnBeforeCompile ) {
previousOnBeforeCompile( shader );
}
shader.uniforms = {
...shader.uniforms,
...params,
};
shader.vertexShader = shader
.vertexShader
.replace( /void main\(\s*\)\s*{/, value => /* glsl */`
for ( int i = 0; i < 10; i ++ ) {
attribute vec3 layer_uv_UNROLLED_LOOP_INDEX;
varying vec3 v_layer_uv_UNROLLED_LOOP_INDEX;
}
${ value }
for ( int i = 0; i < 10; i ++ ) {
v_layer_uv_UNROLLED_LOOP_INDEX = layer_uv_UNROLLED_LOOP_INDEX;
}
` );
shader.fragmentShader = shader
.fragmentShader
.replace( /void main\(/, value => /* glsl */`
struct LayerInfo {
vec3 color;
float opacity;
int alphaMask;
int alphaInvert;
};
uniform sampler2D layerMaps[ LAYER_COUNT ];
uniform LayerInfo layerInfo[ LAYER_COUNT ];
for ( int i = 0; i < 10; i ++ ) {
varying vec3 v_layer_uv_UNROLLED_LOOP_INDEX;
}
${ value }
` )
.replace( /
${ value }
{
vec4 tint;
vec3 layerUV;
float layerOpacity;
float wOpacity;
float wDelta;
for ( int i = 0; i < 10; i ++ ) {
layerUV = v_layer_uv_UNROLLED_LOOP_INDEX;
tint = texture( layerMaps[ i ], layerUV.xy );
// discard texture outside 0, 1 on w - offset the stepped value by an epsilon to avoid cases
// where wDelta is near 0 (eg a flat surface) at the w boundary, resulting in artifacts on some
// hardware.
wDelta = max( fwidth( layerUV.z ), 1e-7 );
wOpacity =
smoothstep( - wDelta, 0.0, layerUV.z ) *
smoothstep( 1.0 + wDelta, 1.0, layerUV.z );
// apply tint & opacity
tint.rgb *= layerInfo[ i ].color;
tint.rgba *= layerInfo[ i ].opacity * wOpacity;
// invert the alpha
if ( layerInfo[ i ].alphaInvert > 0 ) {
tint.a = 1.0 - tint.a;
}
// apply the alpha across all existing layers if alpha mask is true
if ( layerInfo[ i ].alphaMask > 0 ) {
diffuseColor.a *= tint.a;
} else {
tint.rgb *= tint.a;
diffuseColor = tint + diffuseColor * ( 1.0 - tint.a );
}
}
}
` );
};
return params;
}