|
@@ -7,8 +7,8 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
this.renderScene = scene;
|
|
|
this.renderCamera = camera;
|
|
|
this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
|
|
|
- this.visibleEdgeColor = new THREE.Color(1, 1, 1);
|
|
|
- this.hiddenEdgeColor = new THREE.Color(0.1, 0.04, 0.02);
|
|
|
+ this.visibleEdgeColor = new THREE.Color( 1, 1, 1 );
|
|
|
+ this.hiddenEdgeColor = new THREE.Color( 0.1, 0.04, 0.02 );
|
|
|
this.edgeGlow = 0.0;
|
|
|
this.usePatternTexture = false;
|
|
|
this.edgeThickness = 1.0;
|
|
@@ -18,14 +18,14 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
|
|
|
THREE.Pass.call( this );
|
|
|
|
|
|
- this.resolution = ( resolution !== undefined ) ? new THREE.Vector2(resolution.x, resolution.y) : new THREE.Vector2(256, 256);
|
|
|
+ this.resolution = ( resolution !== undefined ) ? new THREE.Vector2( resolution.x, resolution.y ) : new THREE.Vector2( 256, 256 );
|
|
|
|
|
|
var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
|
|
|
|
|
|
- var resx = Math.round(this.resolution.x/this.downSampleRatio);
|
|
|
- var resy = Math.round(this.resolution.y/this.downSampleRatio);
|
|
|
+ var resx = Math.round( this.resolution.x / this.downSampleRatio );
|
|
|
+ var resy = Math.round( this.resolution.y / this.downSampleRatio );
|
|
|
|
|
|
- this.maskBufferMaterial = new THREE.MeshBasicMaterial({color:0xffffff});
|
|
|
+ this.maskBufferMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff } );
|
|
|
this.maskBufferMaterial.side = THREE.DoubleSide;
|
|
|
this.renderTargetMaskBuffer = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
|
|
|
this.renderTargetMaskBuffer.texture.generateMipmaps = false;
|
|
@@ -46,24 +46,24 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
|
|
|
this.renderTargetBlurBuffer1 = new THREE.WebGLRenderTarget( resx, resy, pars );
|
|
|
this.renderTargetBlurBuffer1.texture.generateMipmaps = false;
|
|
|
- this.renderTargetBlurBuffer2 = new THREE.WebGLRenderTarget( Math.round(resx/2), Math.round(resy/2), pars );
|
|
|
+ this.renderTargetBlurBuffer2 = new THREE.WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
|
|
|
this.renderTargetBlurBuffer2.texture.generateMipmaps = false;
|
|
|
|
|
|
this.edgeDetectionMaterial = this.getEdgeDetectionMaterial();
|
|
|
this.renderTargetEdgeBuffer1 = new THREE.WebGLRenderTarget( resx, resy, pars );
|
|
|
this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
|
|
|
- this.renderTargetEdgeBuffer2 = new THREE.WebGLRenderTarget( Math.round(resx/2), Math.round(resy/2), pars );
|
|
|
+ this.renderTargetEdgeBuffer2 = new THREE.WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
|
|
|
this.renderTargetEdgeBuffer2.texture.generateMipmaps = false;
|
|
|
|
|
|
var MAX_EDGE_THICKNESS = 4;
|
|
|
var MAX_EDGE_GLOW = 4;
|
|
|
|
|
|
- this.separableBlurMaterial1 = this.getSeperableBlurMaterial(MAX_EDGE_THICKNESS);
|
|
|
- this.separableBlurMaterial1.uniforms[ "texSize" ] = new THREE.Uniform( new THREE.Vector2(resx, resy) );
|
|
|
- this.separableBlurMaterial1.uniforms[ "kernelRadius" ] = new THREE.Uniform( 1 );
|
|
|
- this.separableBlurMaterial2 = this.getSeperableBlurMaterial(MAX_EDGE_GLOW);
|
|
|
- this.separableBlurMaterial2.uniforms[ "texSize" ] = new THREE.Uniform(new THREE.Vector2(Math.round(resx/2), Math.round(resy/2) ) );
|
|
|
- this.separableBlurMaterial2.uniforms[ "kernelRadius" ] = new THREE.Uniform( MAX_EDGE_GLOW) ;
|
|
|
+ this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS );
|
|
|
+ this.separableBlurMaterial1.uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy );
|
|
|
+ this.separableBlurMaterial1.uniforms[ "kernelRadius" ].value = 1;
|
|
|
+ this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW );
|
|
|
+ this.separableBlurMaterial2.uniforms[ "texSize" ].value = new THREE.Vector2( Math.round( resx / 2 ), Math.round( resy / 2 ) );
|
|
|
+ this.separableBlurMaterial2.uniforms[ "kernelRadius" ].value = MAX_EDGE_GLOW;
|
|
|
|
|
|
// Overlay material
|
|
|
this.overlayMaterial = this.getOverlayMaterial();
|
|
@@ -74,7 +74,7 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
|
|
|
var copyShader = THREE.CopyShader;
|
|
|
|
|
|
- this.copyUniforms = Object.assign( {}, copyShader.uniforms );
|
|
|
+ this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
|
|
|
this.copyUniforms[ "opacity" ].value = 1.0;
|
|
|
|
|
|
this.materialCopy = new THREE.ShaderMaterial( {
|
|
@@ -94,7 +94,7 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
this.oldClearAlpha = 1;
|
|
|
|
|
|
this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
|
|
|
- this.scene = new THREE.Scene();
|
|
|
+ this.scene = new THREE.Scene();
|
|
|
|
|
|
this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
|
|
|
this.scene.add( this.quad );
|
|
@@ -102,13 +102,15 @@ THREE.OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
this.tempPulseColor1 = new THREE.Color();
|
|
|
this.tempPulseColor2 = new THREE.Color();
|
|
|
this.textureMatrix = new THREE.Matrix4();
|
|
|
+
|
|
|
};
|
|
|
|
|
|
THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
|
|
|
|
|
|
constructor: THREE.OutlinePass,
|
|
|
|
|
|
- dispose: function() {
|
|
|
+ dispose: function () {
|
|
|
+
|
|
|
this.renderTargetMaskBuffer.dispose();
|
|
|
this.renderTargetDepthBuffer.dispose();
|
|
|
this.renderTargetMaskDownSampleBuffer.dispose();
|
|
@@ -116,93 +118,102 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
this.renderTargetBlurBuffer2.dispose();
|
|
|
this.renderTargetEdgeBuffer1.dispose();
|
|
|
this.renderTargetEdgeBuffer2.dispose();
|
|
|
+
|
|
|
},
|
|
|
|
|
|
setSize: function ( width, height ) {
|
|
|
|
|
|
- this.renderTargetMaskBuffer.setSize(width, height );
|
|
|
+ this.renderTargetMaskBuffer.setSize( width, height );
|
|
|
|
|
|
- var resx = Math.round(width/this.downSampleRatio);
|
|
|
- var resy = Math.round(height/this.downSampleRatio);
|
|
|
- this.renderTargetMaskDownSampleBuffer.setSize(resx, resy );
|
|
|
- this.renderTargetBlurBuffer1.setSize(resx, resy );
|
|
|
- this.renderTargetEdgeBuffer1.setSize(resx, resy );
|
|
|
- this.separableBlurMaterial1.uniforms[ "texSize" ] = new THREE.Uniform( new THREE.Vector2(resx, resy) );
|
|
|
+ var resx = Math.round( width / this.downSampleRatio );
|
|
|
+ var resy = Math.round( height / this.downSampleRatio );
|
|
|
+ this.renderTargetMaskDownSampleBuffer.setSize( resx, resy );
|
|
|
+ this.renderTargetBlurBuffer1.setSize( resx, resy );
|
|
|
+ this.renderTargetEdgeBuffer1.setSize( resx, resy );
|
|
|
+ this.separableBlurMaterial1.uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy );
|
|
|
|
|
|
- resx = Math.round(resx/2);
|
|
|
- resy = Math.round(resy/2);
|
|
|
+ resx = Math.round( resx / 2 );
|
|
|
+ resy = Math.round( resy / 2 );
|
|
|
|
|
|
- this.renderTargetBlurBuffer2.setSize(resx, resy );
|
|
|
- this.renderTargetEdgeBuffer2.setSize(resx, resy );
|
|
|
+ this.renderTargetBlurBuffer2.setSize( resx, resy );
|
|
|
+ this.renderTargetEdgeBuffer2.setSize( resx, resy );
|
|
|
+
|
|
|
+ this.separableBlurMaterial2.uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy );
|
|
|
|
|
|
- this.separableBlurMaterial2.uniforms[ "texSize" ] = new THREE.Uniform( new THREE.Vector2(resx, resy) );
|
|
|
},
|
|
|
|
|
|
- changeVisibilityOfSelectedObjects: function( bVisible ) {
|
|
|
+ changeVisibilityOfSelectedObjects: function ( bVisible ) {
|
|
|
|
|
|
- var gatherSelectedMeshesCallBack = function( object ) {
|
|
|
+ function gatherSelectedMeshesCallBack( object ) {
|
|
|
|
|
|
- if( object instanceof THREE.Mesh ) {
|
|
|
- object.visible = bVisible;
|
|
|
- }
|
|
|
- };
|
|
|
+ if ( object instanceof THREE.Mesh ) object.visible = bVisible;
|
|
|
|
|
|
- for( var i=0; i<this.selectedObjects.length; i++ ) {
|
|
|
+ }
|
|
|
|
|
|
- var selectedObject = this.selectedObjects[i];
|
|
|
+ for ( var i = 0; i < this.selectedObjects.length; i ++ ) {
|
|
|
|
|
|
+ var selectedObject = this.selectedObjects[ i ];
|
|
|
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- changeVisibilityOfNonSelectedObjects: function( bVisible ) {
|
|
|
+ changeVisibilityOfNonSelectedObjects: function ( bVisible ) {
|
|
|
|
|
|
var selectedMeshes = [];
|
|
|
|
|
|
- var gatherSelectedMeshesCallBack = function( object ) {
|
|
|
-
|
|
|
- if( object instanceof THREE.Mesh ) {
|
|
|
+ function gatherSelectedMeshesCallBack( object ) {
|
|
|
|
|
|
- selectedMeshes.push(object);
|
|
|
+ if ( object instanceof THREE.Mesh ) selectedMeshes.push( object );
|
|
|
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- for( var i=0; i<this.selectedObjects.length; i++ ) {
|
|
|
+ }
|
|
|
|
|
|
- var selectedObject = this.selectedObjects[i];
|
|
|
+ for ( var i = 0; i < this.selectedObjects.length; i ++ ) {
|
|
|
|
|
|
+ var selectedObject = this.selectedObjects[ i ];
|
|
|
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- var VisibilityChangeCallBack = function( object ) {
|
|
|
+ function VisibilityChangeCallBack( object ) {
|
|
|
|
|
|
- if( object instanceof THREE.Mesh ) {
|
|
|
+ if ( object instanceof THREE.Mesh ) {
|
|
|
|
|
|
var bFound = false;
|
|
|
|
|
|
- for( var i=0; i<selectedMeshes.length; i++ ) {
|
|
|
+ for ( var i = 0; i < selectedMeshes.length; i ++ ) {
|
|
|
+
|
|
|
+ var selectedObjectId = selectedMeshes[ i ].id;
|
|
|
|
|
|
- var selectedObjectId = selectedMeshes[i].id;
|
|
|
+ if ( selectedObjectId === object.id ) {
|
|
|
|
|
|
- if(selectedObjectId === object.id) {
|
|
|
bFound = true;
|
|
|
break;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|
|
|
- if(!bFound) {
|
|
|
+
|
|
|
+ if ( ! bFound ) {
|
|
|
+
|
|
|
var visibility = object.visible;
|
|
|
- if( !bVisible || object.bVisible )
|
|
|
- object.visible = bVisible;
|
|
|
+
|
|
|
+ if ( ! bVisible || object.bVisible ) object.visible = bVisible;
|
|
|
+
|
|
|
object.bVisible = visibility;
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
- };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
this.renderScene.traverse( VisibilityChangeCallBack );
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- updateTextureMatrix: function() {
|
|
|
+ updateTextureMatrix: function () {
|
|
|
|
|
|
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
|
|
|
0.0, 0.5, 0.0, 0.5,
|
|
@@ -215,8 +226,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
|
|
|
render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
|
|
|
|
|
|
- if(this.selectedObjects.length === 0 )
|
|
|
- return;
|
|
|
+ if ( this.selectedObjects.length === 0 ) return;
|
|
|
|
|
|
this.oldClearColor.copy( renderer.getClearColor() );
|
|
|
this.oldClearAlpha = renderer.getClearAlpha();
|
|
@@ -229,27 +239,27 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
renderer.setClearColor( 0xffffff, 1 );
|
|
|
|
|
|
// Make selected objects invisible
|
|
|
- this.changeVisibilityOfSelectedObjects(false);
|
|
|
+ this.changeVisibilityOfSelectedObjects( false );
|
|
|
|
|
|
// 1. Draw Non Selected objects in the depth buffer
|
|
|
this.renderScene.overrideMaterial = this.depthMaterial;
|
|
|
renderer.render( this.renderScene, this.renderCamera, this.renderTargetDepthBuffer, true );
|
|
|
|
|
|
// Make selected objects visible
|
|
|
- this.changeVisibilityOfSelectedObjects(true);
|
|
|
+ this.changeVisibilityOfSelectedObjects( true );
|
|
|
|
|
|
// Update Texture Matrix for Depth compare
|
|
|
this.updateTextureMatrix();
|
|
|
|
|
|
// Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
|
|
|
- this.changeVisibilityOfNonSelectedObjects(false);
|
|
|
+ this.changeVisibilityOfNonSelectedObjects( false );
|
|
|
this.renderScene.overrideMaterial = this.prepareMaskMaterial;
|
|
|
- this.prepareMaskMaterial.uniforms[ "cameraNearFar" ].value = new THREE.Vector2(this.renderCamera.near, this.renderCamera.far);
|
|
|
+ this.prepareMaskMaterial.uniforms[ "cameraNearFar" ].value = new THREE.Vector2( this.renderCamera.near, this.renderCamera.far );
|
|
|
this.prepareMaskMaterial.uniforms[ "depthTexture" ].value = this.renderTargetDepthBuffer.texture;
|
|
|
this.prepareMaskMaterial.uniforms[ "textureMatrix" ].value = this.textureMatrix;
|
|
|
renderer.render( this.renderScene, this.renderCamera, this.renderTargetMaskBuffer, true );
|
|
|
this.renderScene.overrideMaterial = null;
|
|
|
- this.changeVisibilityOfNonSelectedObjects(true);
|
|
|
+ this.changeVisibilityOfNonSelectedObjects( true );
|
|
|
|
|
|
// 2. Downsample to Half resolution
|
|
|
this.quad.material = this.materialCopy;
|
|
@@ -258,16 +268,19 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
|
|
|
this.tempPulseColor1.copy( this.visibleEdgeColor );
|
|
|
this.tempPulseColor2.copy( this.hiddenEdgeColor );
|
|
|
- if( this.pulsePeriod > 0 ) {
|
|
|
- var scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01/ this.pulsePeriod ) * ( 1.0 - 0.25 )/2;
|
|
|
+
|
|
|
+ if ( this.pulsePeriod > 0 ) {
|
|
|
+
|
|
|
+ var scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2;
|
|
|
this.tempPulseColor1.multiplyScalar( scalar );
|
|
|
this.tempPulseColor2.multiplyScalar( scalar );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// 3. Apply Edge Detection Pass
|
|
|
this.quad.material = this.edgeDetectionMaterial;
|
|
|
this.edgeDetectionMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskDownSampleBuffer.texture;
|
|
|
- this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2(this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height);
|
|
|
+ this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
|
|
|
this.edgeDetectionMaterial.uniforms[ "visibleEdgeColor" ].value = this.tempPulseColor1;
|
|
|
this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = this.tempPulseColor2;
|
|
|
renderer.render( this.scene, this.camera, this.renderTargetEdgeBuffer1, true );
|
|
@@ -308,16 +321,17 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
|
|
|
renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
|
|
|
renderer.autoClear = oldAutoClear;
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- getPrepareMaskMaterial: function() {
|
|
|
+ getPrepareMaskMaterial: function () {
|
|
|
|
|
|
return new THREE.ShaderMaterial( {
|
|
|
|
|
|
uniforms: {
|
|
|
"depthTexture": { value: null },
|
|
|
"cameraNearFar": { value: new THREE.Vector2( 0.5, 0.5 ) },
|
|
|
- "textureMatrix" : { value: new THREE.Matrix4() }
|
|
|
+ "textureMatrix": { value: new THREE.Matrix4() }
|
|
|
},
|
|
|
|
|
|
vertexShader:
|
|
@@ -348,9 +362,10 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);\
|
|
|
}"
|
|
|
} );
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- getEdgeDetectionMaterial: function() {
|
|
|
+ getEdgeDetectionMaterial: function () {
|
|
|
|
|
|
return new THREE.ShaderMaterial( {
|
|
|
|
|
@@ -358,7 +373,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
"maskTexture": { value: null },
|
|
|
"texSize": { value: new THREE.Vector2( 0.5, 0.5 ) },
|
|
|
"visibleEdgeColor": { value: new THREE.Vector3( 1.0, 1.0, 1.0 ) },
|
|
|
- "hiddenEdgeColor": { value: new THREE.Vector3( 1.0, 1.0, 1.0 ) }
|
|
|
+ "hiddenEdgeColor": { value: new THREE.Vector3( 1.0, 1.0, 1.0 ) },
|
|
|
},
|
|
|
|
|
|
vertexShader:
|
|
@@ -392,19 +407,20 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\
|
|
|
}"
|
|
|
} );
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- getSeperableBlurMaterial: function(maxRadius) {
|
|
|
+ getSeperableBlurMaterial: function ( maxRadius ) {
|
|
|
|
|
|
return new THREE.ShaderMaterial( {
|
|
|
|
|
|
defines: {
|
|
|
- "MAX_RADIUS" : maxRadius
|
|
|
+ "MAX_RADIUS": maxRadius,
|
|
|
},
|
|
|
|
|
|
uniforms: {
|
|
|
"colorTexture": { value: null },
|
|
|
- "texSize": { value: new THREE.Vector2( 0.5, 0.5 ) },
|
|
|
+ "texSize": { value: new THREE.Vector2( 0.5, 0.5 ) },
|
|
|
"direction": { value: new THREE.Vector2( 0.5, 0.5 ) },
|
|
|
"kernelRadius": { value: 1.0 }
|
|
|
},
|
|
@@ -444,9 +460,10 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\
|
|
|
}"
|
|
|
} );
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- getOverlayMaterial: function() {
|
|
|
+ getOverlayMaterial: function () {
|
|
|
|
|
|
return new THREE.ShaderMaterial( {
|
|
|
|
|
@@ -455,9 +472,9 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
"edgeTexture1": { value: null },
|
|
|
"edgeTexture2": { value: null },
|
|
|
"patternTexture": { value: null },
|
|
|
- "edgeStrength" : { value: 1.0 },
|
|
|
- "edgeGlow" : { value: 1.0 },
|
|
|
- "usePatternTexture" : { value: 0.0 }
|
|
|
+ "edgeStrength": { value: 1.0 },
|
|
|
+ "edgeGlow": { value: 1.0 },
|
|
|
+ "usePatternTexture": { value: 0.0 }
|
|
|
},
|
|
|
|
|
|
vertexShader:
|
|
@@ -489,12 +506,12 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
|
|
|
finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\
|
|
|
gl_FragColor = finalColor;\
|
|
|
}",
|
|
|
-
|
|
|
- blending: THREE.AdditiveBlending,
|
|
|
- depthTest: false,
|
|
|
- depthWrite: false,
|
|
|
- transparent: true
|
|
|
+ blending: THREE.AdditiveBlending,
|
|
|
+ depthTest: false,
|
|
|
+ depthWrite: false,
|
|
|
+ transparent: true
|
|
|
} );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
} );
|