Buckets:
| ; | |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | |
| const THREE = require("three"); | |
| const constants = require("../_polyfill/constants.cjs"); | |
| class LineMaterial extends THREE.ShaderMaterial { | |
| constructor(parameters) { | |
| super({ | |
| type: "LineMaterial", | |
| uniforms: THREE.UniformsUtils.clone( | |
| THREE.UniformsUtils.merge([ | |
| THREE.UniformsLib.common, | |
| THREE.UniformsLib.fog, | |
| { | |
| worldUnits: { value: 1 }, | |
| linewidth: { value: 1 }, | |
| resolution: { value: new THREE.Vector2(1, 1) }, | |
| dashOffset: { value: 0 }, | |
| dashScale: { value: 1 }, | |
| dashSize: { value: 1 }, | |
| gapSize: { value: 1 } | |
| // todo FIX - maybe change to totalSize | |
| } | |
| ]) | |
| ), | |
| vertexShader: ( | |
| /* glsl */ | |
| ` | |
| #include <common> | |
| #include <fog_pars_vertex> | |
| #include <logdepthbuf_pars_vertex> | |
| #include <clipping_planes_pars_vertex> | |
| uniform float linewidth; | |
| uniform vec2 resolution; | |
| attribute vec3 instanceStart; | |
| attribute vec3 instanceEnd; | |
| #ifdef USE_COLOR | |
| #ifdef USE_LINE_COLOR_ALPHA | |
| varying vec4 vLineColor; | |
| attribute vec4 instanceColorStart; | |
| attribute vec4 instanceColorEnd; | |
| #else | |
| varying vec3 vLineColor; | |
| attribute vec3 instanceColorStart; | |
| attribute vec3 instanceColorEnd; | |
| #endif | |
| #endif | |
| #ifdef WORLD_UNITS | |
| varying vec4 worldPos; | |
| varying vec3 worldStart; | |
| varying vec3 worldEnd; | |
| #ifdef USE_DASH | |
| varying vec2 vUv; | |
| #endif | |
| #else | |
| varying vec2 vUv; | |
| #endif | |
| #ifdef USE_DASH | |
| uniform float dashScale; | |
| attribute float instanceDistanceStart; | |
| attribute float instanceDistanceEnd; | |
| varying float vLineDistance; | |
| #endif | |
| void trimSegment( const in vec4 start, inout vec4 end ) { | |
| // trim end segment so it terminates between the camera plane and the near plane | |
| // conservative estimate of the near plane | |
| float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column | |
| float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column | |
| float nearEstimate = - 0.5 * b / a; | |
| float alpha = ( nearEstimate - start.z ) / ( end.z - start.z ); | |
| end.xyz = mix( start.xyz, end.xyz, alpha ); | |
| } | |
| void main() { | |
| #ifdef USE_COLOR | |
| vLineColor = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd; | |
| #endif | |
| #ifdef USE_DASH | |
| vLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd; | |
| vUv = uv; | |
| #endif | |
| float aspect = resolution.x / resolution.y; | |
| // camera space | |
| vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 ); | |
| vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 ); | |
| #ifdef WORLD_UNITS | |
| worldStart = start.xyz; | |
| worldEnd = end.xyz; | |
| #else | |
| vUv = uv; | |
| #endif | |
| // special case for perspective projection, and segments that terminate either in, or behind, the camera plane | |
| // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space | |
| // but we need to perform ndc-space calculations in the shader, so we must address this issue directly | |
| // perhaps there is a more elegant solution -- WestLangley | |
| bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column | |
| if ( perspective ) { | |
| if ( start.z < 0.0 && end.z >= 0.0 ) { | |
| trimSegment( start, end ); | |
| } else if ( end.z < 0.0 && start.z >= 0.0 ) { | |
| trimSegment( end, start ); | |
| } | |
| } | |
| // clip space | |
| vec4 clipStart = projectionMatrix * start; | |
| vec4 clipEnd = projectionMatrix * end; | |
| // ndc space | |
| vec3 ndcStart = clipStart.xyz / clipStart.w; | |
| vec3 ndcEnd = clipEnd.xyz / clipEnd.w; | |
| // direction | |
| vec2 dir = ndcEnd.xy - ndcStart.xy; | |
| // account for clip-space aspect ratio | |
| dir.x *= aspect; | |
| dir = normalize( dir ); | |
| #ifdef WORLD_UNITS | |
| // get the offset direction as perpendicular to the view vector | |
| vec3 worldDir = normalize( end.xyz - start.xyz ); | |
| vec3 offset; | |
| if ( position.y < 0.5 ) { | |
| offset = normalize( cross( start.xyz, worldDir ) ); | |
| } else { | |
| offset = normalize( cross( end.xyz, worldDir ) ); | |
| } | |
| // sign flip | |
| if ( position.x < 0.0 ) offset *= - 1.0; | |
| float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) ); | |
| // don't extend the line if we're rendering dashes because we | |
| // won't be rendering the endcaps | |
| #ifndef USE_DASH | |
| // extend the line bounds to encompass endcaps | |
| start.xyz += - worldDir * linewidth * 0.5; | |
| end.xyz += worldDir * linewidth * 0.5; | |
| // shift the position of the quad so it hugs the forward edge of the line | |
| offset.xy -= dir * forwardOffset; | |
| offset.z += 0.5; | |
| #endif | |
| // endcaps | |
| if ( position.y > 1.0 || position.y < 0.0 ) { | |
| offset.xy += dir * 2.0 * forwardOffset; | |
| } | |
| // adjust for linewidth | |
| offset *= linewidth * 0.5; | |
| // set the world position | |
| worldPos = ( position.y < 0.5 ) ? start : end; | |
| worldPos.xyz += offset; | |
| // project the worldpos | |
| vec4 clip = projectionMatrix * worldPos; | |
| // shift the depth of the projected points so the line | |
| // segments overlap neatly | |
| vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd; | |
| clip.z = clipPose.z * clip.w; | |
| #else | |
| vec2 offset = vec2( dir.y, - dir.x ); | |
| // undo aspect ratio adjustment | |
| dir.x /= aspect; | |
| offset.x /= aspect; | |
| // sign flip | |
| if ( position.x < 0.0 ) offset *= - 1.0; | |
| // endcaps | |
| if ( position.y < 0.0 ) { | |
| offset += - dir; | |
| } else if ( position.y > 1.0 ) { | |
| offset += dir; | |
| } | |
| // adjust for linewidth | |
| offset *= linewidth; | |
| // adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ... | |
| offset /= resolution.y; | |
| // select end | |
| vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd; | |
| // back to clip space | |
| offset *= clip.w; | |
| clip.xy += offset; | |
| #endif | |
| gl_Position = clip; | |
| vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation | |
| #include <logdepthbuf_vertex> | |
| #include <clipping_planes_vertex> | |
| #include <fog_vertex> | |
| } | |
| ` | |
| ), | |
| fragmentShader: ( | |
| /* glsl */ | |
| ` | |
| uniform vec3 diffuse; | |
| uniform float opacity; | |
| uniform float linewidth; | |
| #ifdef USE_DASH | |
| uniform float dashOffset; | |
| uniform float dashSize; | |
| uniform float gapSize; | |
| #endif | |
| varying float vLineDistance; | |
| #ifdef WORLD_UNITS | |
| varying vec4 worldPos; | |
| varying vec3 worldStart; | |
| varying vec3 worldEnd; | |
| #ifdef USE_DASH | |
| varying vec2 vUv; | |
| #endif | |
| #else | |
| varying vec2 vUv; | |
| #endif | |
| #include <common> | |
| #include <fog_pars_fragment> | |
| #include <logdepthbuf_pars_fragment> | |
| #include <clipping_planes_pars_fragment> | |
| #ifdef USE_COLOR | |
| #ifdef USE_LINE_COLOR_ALPHA | |
| varying vec4 vLineColor; | |
| #else | |
| varying vec3 vLineColor; | |
| #endif | |
| #endif | |
| vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) { | |
| float mua; | |
| float mub; | |
| vec3 p13 = p1 - p3; | |
| vec3 p43 = p4 - p3; | |
| vec3 p21 = p2 - p1; | |
| float d1343 = dot( p13, p43 ); | |
| float d4321 = dot( p43, p21 ); | |
| float d1321 = dot( p13, p21 ); | |
| float d4343 = dot( p43, p43 ); | |
| float d2121 = dot( p21, p21 ); | |
| float denom = d2121 * d4343 - d4321 * d4321; | |
| float numer = d1343 * d4321 - d1321 * d4343; | |
| mua = numer / denom; | |
| mua = clamp( mua, 0.0, 1.0 ); | |
| mub = ( d1343 + d4321 * ( mua ) ) / d4343; | |
| mub = clamp( mub, 0.0, 1.0 ); | |
| return vec2( mua, mub ); | |
| } | |
| void main() { | |
| #include <clipping_planes_fragment> | |
| #ifdef USE_DASH | |
| if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps | |
| if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | |
| #endif | |
| float alpha = opacity; | |
| #ifdef WORLD_UNITS | |
| // Find the closest points on the view ray and the line segment | |
| vec3 rayEnd = normalize( worldPos.xyz ) * 1e5; | |
| vec3 lineDir = worldEnd - worldStart; | |
| vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd ); | |
| vec3 p1 = worldStart + lineDir * params.x; | |
| vec3 p2 = rayEnd * params.y; | |
| vec3 delta = p1 - p2; | |
| float len = length( delta ); | |
| float norm = len / linewidth; | |
| #ifndef USE_DASH | |
| #ifdef USE_ALPHA_TO_COVERAGE | |
| float dnorm = fwidth( norm ); | |
| alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm ); | |
| #else | |
| if ( norm > 0.5 ) { | |
| discard; | |
| } | |
| #endif | |
| #endif | |
| #else | |
| #ifdef USE_ALPHA_TO_COVERAGE | |
| // artifacts appear on some hardware if a derivative is taken within a conditional | |
| float a = vUv.x; | |
| float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | |
| float len2 = a * a + b * b; | |
| float dlen = fwidth( len2 ); | |
| if ( abs( vUv.y ) > 1.0 ) { | |
| alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 ); | |
| } | |
| #else | |
| if ( abs( vUv.y ) > 1.0 ) { | |
| float a = vUv.x; | |
| float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | |
| float len2 = a * a + b * b; | |
| if ( len2 > 1.0 ) discard; | |
| } | |
| #endif | |
| #endif | |
| vec4 diffuseColor = vec4( diffuse, alpha ); | |
| #ifdef USE_COLOR | |
| #ifdef USE_LINE_COLOR_ALPHA | |
| diffuseColor *= vLineColor; | |
| #else | |
| diffuseColor.rgb *= vLineColor; | |
| #endif | |
| #endif | |
| #include <logdepthbuf_fragment> | |
| gl_FragColor = diffuseColor; | |
| #include <tonemapping_fragment> | |
| #include <${constants.version >= 154 ? "colorspace_fragment" : "encodings_fragment"}> | |
| #include <fog_fragment> | |
| #include <premultiplied_alpha_fragment> | |
| } | |
| ` | |
| ), | |
| clipping: true | |
| // required for clipping support | |
| }); | |
| this.isLineMaterial = true; | |
| this.onBeforeCompile = function() { | |
| if (this.transparent) { | |
| this.defines.USE_LINE_COLOR_ALPHA = "1"; | |
| } else { | |
| delete this.defines.USE_LINE_COLOR_ALPHA; | |
| } | |
| }; | |
| Object.defineProperties(this, { | |
| color: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.diffuse.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.diffuse.value = value; | |
| } | |
| }, | |
| worldUnits: { | |
| enumerable: true, | |
| get: function() { | |
| return "WORLD_UNITS" in this.defines; | |
| }, | |
| set: function(value) { | |
| if (value === true) { | |
| this.defines.WORLD_UNITS = ""; | |
| } else { | |
| delete this.defines.WORLD_UNITS; | |
| } | |
| } | |
| }, | |
| linewidth: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.linewidth.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.linewidth.value = value; | |
| } | |
| }, | |
| dashed: { | |
| enumerable: true, | |
| get: function() { | |
| return Boolean("USE_DASH" in this.defines); | |
| }, | |
| set(value) { | |
| if (Boolean(value) !== Boolean("USE_DASH" in this.defines)) { | |
| this.needsUpdate = true; | |
| } | |
| if (value === true) { | |
| this.defines.USE_DASH = ""; | |
| } else { | |
| delete this.defines.USE_DASH; | |
| } | |
| } | |
| }, | |
| dashScale: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.dashScale.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.dashScale.value = value; | |
| } | |
| }, | |
| dashSize: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.dashSize.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.dashSize.value = value; | |
| } | |
| }, | |
| dashOffset: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.dashOffset.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.dashOffset.value = value; | |
| } | |
| }, | |
| gapSize: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.gapSize.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.gapSize.value = value; | |
| } | |
| }, | |
| opacity: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.opacity.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.opacity.value = value; | |
| } | |
| }, | |
| resolution: { | |
| enumerable: true, | |
| get: function() { | |
| return this.uniforms.resolution.value; | |
| }, | |
| set: function(value) { | |
| this.uniforms.resolution.value.copy(value); | |
| } | |
| }, | |
| alphaToCoverage: { | |
| enumerable: true, | |
| get: function() { | |
| return Boolean("USE_ALPHA_TO_COVERAGE" in this.defines); | |
| }, | |
| set: function(value) { | |
| if (Boolean(value) !== Boolean("USE_ALPHA_TO_COVERAGE" in this.defines)) { | |
| this.needsUpdate = true; | |
| } | |
| if (value === true) { | |
| this.defines.USE_ALPHA_TO_COVERAGE = ""; | |
| this.extensions.derivatives = true; | |
| } else { | |
| delete this.defines.USE_ALPHA_TO_COVERAGE; | |
| this.extensions.derivatives = false; | |
| } | |
| } | |
| } | |
| }); | |
| this.setValues(parameters); | |
| } | |
| } | |
| exports.LineMaterial = LineMaterial; | |
| //# sourceMappingURL=LineMaterial.cjs.map | |
Xet Storage Details
- Size:
- 13.8 kB
- Xet hash:
- a582f2c5dea9573f398c868dc584766a488bd5b67798fb74ed6cd877887c3643
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.