|
@@ -15,131 +15,129 @@ import {
|
|
Vector3,
|
|
Vector3,
|
|
WebGLRenderTarget
|
|
WebGLRenderTarget
|
|
} from '../../../build/three.module.js';
|
|
} from '../../../build/three.module.js';
|
|
-import { Pass } from '../postprocessing/Pass.js';
|
|
|
|
|
|
+import { Pass, FullScreenQuad } from '../postprocessing/Pass.js';
|
|
import { CopyShader } from '../shaders/CopyShader.js';
|
|
import { CopyShader } from '../shaders/CopyShader.js';
|
|
|
|
|
|
-var OutlinePass = function ( resolution, scene, camera, selectedObjects ) {
|
|
|
|
-
|
|
|
|
- this.renderScene = scene;
|
|
|
|
- this.renderCamera = camera;
|
|
|
|
- this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
|
|
|
|
- this.visibleEdgeColor = new Color( 1, 1, 1 );
|
|
|
|
- this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 );
|
|
|
|
- this.edgeGlow = 0.0;
|
|
|
|
- this.usePatternTexture = false;
|
|
|
|
- this.edgeThickness = 1.0;
|
|
|
|
- this.edgeStrength = 3.0;
|
|
|
|
- this.downSampleRatio = 2;
|
|
|
|
- this.pulsePeriod = 0;
|
|
|
|
|
|
+class OutlinePass extends Pass {
|
|
|
|
|
|
- this._visibilityCache = new Map();
|
|
|
|
|
|
+ constructor( resolution, scene, camera, selectedObjects ) {
|
|
|
|
|
|
- Pass.call( this );
|
|
|
|
|
|
+ super();
|
|
|
|
|
|
- this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );
|
|
|
|
|
|
+ this.renderScene = scene;
|
|
|
|
+ this.renderCamera = camera;
|
|
|
|
+ this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
|
|
|
|
+ this.visibleEdgeColor = new Color( 1, 1, 1 );
|
|
|
|
+ this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 );
|
|
|
|
+ this.edgeGlow = 0.0;
|
|
|
|
+ this.usePatternTexture = false;
|
|
|
|
+ this.edgeThickness = 1.0;
|
|
|
|
+ this.edgeStrength = 3.0;
|
|
|
|
+ this.downSampleRatio = 2;
|
|
|
|
+ this.pulsePeriod = 0;
|
|
|
|
|
|
- var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
|
|
|
|
|
|
+ this._visibilityCache = new Map();
|
|
|
|
|
|
- var resx = Math.round( this.resolution.x / this.downSampleRatio );
|
|
|
|
- var resy = Math.round( this.resolution.y / this.downSampleRatio );
|
|
|
|
|
|
|
|
- this.maskBufferMaterial = new MeshBasicMaterial( { color: 0xffffff } );
|
|
|
|
- this.maskBufferMaterial.side = DoubleSide;
|
|
|
|
- this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
|
|
|
|
- this.renderTargetMaskBuffer.texture.name = 'OutlinePass.mask';
|
|
|
|
- this.renderTargetMaskBuffer.texture.generateMipmaps = false;
|
|
|
|
|
|
+ this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );
|
|
|
|
|
|
- this.depthMaterial = new MeshDepthMaterial();
|
|
|
|
- this.depthMaterial.side = DoubleSide;
|
|
|
|
- this.depthMaterial.depthPacking = RGBADepthPacking;
|
|
|
|
- this.depthMaterial.blending = NoBlending;
|
|
|
|
|
|
+ const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
|
|
|
|
|
|
- this.prepareMaskMaterial = this.getPrepareMaskMaterial();
|
|
|
|
- this.prepareMaskMaterial.side = DoubleSide;
|
|
|
|
- this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
|
|
|
|
|
|
+ const resx = Math.round( this.resolution.x / this.downSampleRatio );
|
|
|
|
+ const resy = Math.round( this.resolution.y / this.downSampleRatio );
|
|
|
|
|
|
- this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
|
|
|
|
- this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth';
|
|
|
|
- this.renderTargetDepthBuffer.texture.generateMipmaps = false;
|
|
|
|
|
|
+ this.maskBufferMaterial = new MeshBasicMaterial( { color: 0xffffff } );
|
|
|
|
+ this.maskBufferMaterial.side = DoubleSide;
|
|
|
|
+ this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
|
|
|
|
+ this.renderTargetMaskBuffer.texture.name = 'OutlinePass.mask';
|
|
|
|
+ this.renderTargetMaskBuffer.texture.generateMipmaps = false;
|
|
|
|
|
|
- this.renderTargetMaskDownSampleBuffer = new WebGLRenderTarget( resx, resy, pars );
|
|
|
|
- this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample';
|
|
|
|
- this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false;
|
|
|
|
|
|
+ this.depthMaterial = new MeshDepthMaterial();
|
|
|
|
+ this.depthMaterial.side = DoubleSide;
|
|
|
|
+ this.depthMaterial.depthPacking = RGBADepthPacking;
|
|
|
|
+ this.depthMaterial.blending = NoBlending;
|
|
|
|
|
|
- this.renderTargetBlurBuffer1 = new WebGLRenderTarget( resx, resy, pars );
|
|
|
|
- this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1';
|
|
|
|
- this.renderTargetBlurBuffer1.texture.generateMipmaps = false;
|
|
|
|
- this.renderTargetBlurBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
|
|
|
|
- this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2';
|
|
|
|
- this.renderTargetBlurBuffer2.texture.generateMipmaps = false;
|
|
|
|
|
|
+ this.prepareMaskMaterial = this.getPrepareMaskMaterial();
|
|
|
|
+ this.prepareMaskMaterial.side = DoubleSide;
|
|
|
|
+ this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
|
|
|
|
|
|
- this.edgeDetectionMaterial = this.getEdgeDetectionMaterial();
|
|
|
|
- this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, pars );
|
|
|
|
- this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1';
|
|
|
|
- this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
|
|
|
|
- this.renderTargetEdgeBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
|
|
|
|
- this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2';
|
|
|
|
- this.renderTargetEdgeBuffer2.texture.generateMipmaps = false;
|
|
|
|
|
|
+ this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
|
|
|
|
+ this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth';
|
|
|
|
+ this.renderTargetDepthBuffer.texture.generateMipmaps = false;
|
|
|
|
|
|
- var MAX_EDGE_THICKNESS = 4;
|
|
|
|
- var MAX_EDGE_GLOW = 4;
|
|
|
|
|
|
+ this.renderTargetMaskDownSampleBuffer = new WebGLRenderTarget( resx, resy, pars );
|
|
|
|
+ this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample';
|
|
|
|
+ this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false;
|
|
|
|
|
|
- this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS );
|
|
|
|
- this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
|
|
|
|
- this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1;
|
|
|
|
- this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW );
|
|
|
|
- this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) );
|
|
|
|
- this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW;
|
|
|
|
|
|
+ this.renderTargetBlurBuffer1 = new WebGLRenderTarget( resx, resy, pars );
|
|
|
|
+ this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1';
|
|
|
|
+ this.renderTargetBlurBuffer1.texture.generateMipmaps = false;
|
|
|
|
+ this.renderTargetBlurBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
|
|
|
|
+ this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2';
|
|
|
|
+ this.renderTargetBlurBuffer2.texture.generateMipmaps = false;
|
|
|
|
|
|
- // Overlay material
|
|
|
|
- this.overlayMaterial = this.getOverlayMaterial();
|
|
|
|
|
|
+ this.edgeDetectionMaterial = this.getEdgeDetectionMaterial();
|
|
|
|
+ this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, pars );
|
|
|
|
+ this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1';
|
|
|
|
+ this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
|
|
|
|
+ this.renderTargetEdgeBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
|
|
|
|
+ this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2';
|
|
|
|
+ this.renderTargetEdgeBuffer2.texture.generateMipmaps = false;
|
|
|
|
|
|
- // copy material
|
|
|
|
- if ( CopyShader === undefined )
|
|
|
|
- console.error( 'THREE.OutlinePass relies on CopyShader' );
|
|
|
|
|
|
+ const MAX_EDGE_THICKNESS = 4;
|
|
|
|
+ const MAX_EDGE_GLOW = 4;
|
|
|
|
|
|
- var copyShader = CopyShader;
|
|
|
|
|
|
+ this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS );
|
|
|
|
+ this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
|
|
|
|
+ this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1;
|
|
|
|
+ this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW );
|
|
|
|
+ this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) );
|
|
|
|
+ this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW;
|
|
|
|
|
|
- this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );
|
|
|
|
- this.copyUniforms[ 'opacity' ].value = 1.0;
|
|
|
|
|
|
+ // Overlay material
|
|
|
|
+ this.overlayMaterial = this.getOverlayMaterial();
|
|
|
|
|
|
- this.materialCopy = new ShaderMaterial( {
|
|
|
|
- uniforms: this.copyUniforms,
|
|
|
|
- vertexShader: copyShader.vertexShader,
|
|
|
|
- fragmentShader: copyShader.fragmentShader,
|
|
|
|
- blending: NoBlending,
|
|
|
|
- depthTest: false,
|
|
|
|
- depthWrite: false,
|
|
|
|
- transparent: true
|
|
|
|
- } );
|
|
|
|
|
|
+ // copy material
|
|
|
|
+ if ( CopyShader === undefined ) console.error( 'THREE.OutlinePass relies on CopyShader' );
|
|
|
|
|
|
- this.enabled = true;
|
|
|
|
- this.needsSwap = false;
|
|
|
|
|
|
+ const copyShader = CopyShader;
|
|
|
|
|
|
- this._oldClearColor = new Color();
|
|
|
|
- this.oldClearAlpha = 1;
|
|
|
|
|
|
+ this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );
|
|
|
|
+ this.copyUniforms[ 'opacity' ].value = 1.0;
|
|
|
|
|
|
- this.fsQuad = new Pass.FullScreenQuad( null );
|
|
|
|
|
|
+ this.materialCopy = new ShaderMaterial( {
|
|
|
|
+ uniforms: this.copyUniforms,
|
|
|
|
+ vertexShader: copyShader.vertexShader,
|
|
|
|
+ fragmentShader: copyShader.fragmentShader,
|
|
|
|
+ blending: NoBlending,
|
|
|
|
+ depthTest: false,
|
|
|
|
+ depthWrite: false,
|
|
|
|
+ transparent: true
|
|
|
|
+ } );
|
|
|
|
|
|
- this.tempPulseColor1 = new Color();
|
|
|
|
- this.tempPulseColor2 = new Color();
|
|
|
|
- this.textureMatrix = new Matrix4();
|
|
|
|
|
|
+ this.enabled = true;
|
|
|
|
+ this.needsSwap = false;
|
|
|
|
|
|
- function replaceDepthToViewZ( string, camera ) {
|
|
|
|
|
|
+ this._oldClearColor = new Color();
|
|
|
|
+ this.oldClearAlpha = 1;
|
|
|
|
|
|
- var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
|
|
|
|
|
|
+ this.fsQuad = new FullScreenQuad( null );
|
|
|
|
|
|
- return string.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' );
|
|
|
|
|
|
+ this.tempPulseColor1 = new Color();
|
|
|
|
+ this.tempPulseColor2 = new Color();
|
|
|
|
+ this.textureMatrix = new Matrix4();
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ function replaceDepthToViewZ( string, camera ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
|
|
|
|
|
|
-OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
+ return string.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' );
|
|
|
|
|
|
- constructor: OutlinePass,
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- dispose: function () {
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dispose() {
|
|
|
|
|
|
this.renderTargetMaskBuffer.dispose();
|
|
this.renderTargetMaskBuffer.dispose();
|
|
this.renderTargetDepthBuffer.dispose();
|
|
this.renderTargetDepthBuffer.dispose();
|
|
@@ -149,15 +147,15 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
this.renderTargetEdgeBuffer1.dispose();
|
|
this.renderTargetEdgeBuffer1.dispose();
|
|
this.renderTargetEdgeBuffer2.dispose();
|
|
this.renderTargetEdgeBuffer2.dispose();
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- setSize: function ( width, height ) {
|
|
|
|
|
|
+ setSize( width, height ) {
|
|
|
|
|
|
this.renderTargetMaskBuffer.setSize( width, height );
|
|
this.renderTargetMaskBuffer.setSize( width, height );
|
|
this.renderTargetDepthBuffer.setSize( width, height );
|
|
this.renderTargetDepthBuffer.setSize( width, height );
|
|
|
|
|
|
- var resx = Math.round( width / this.downSampleRatio );
|
|
|
|
- var resy = Math.round( height / this.downSampleRatio );
|
|
|
|
|
|
+ let resx = Math.round( width / this.downSampleRatio );
|
|
|
|
+ let resy = Math.round( height / this.downSampleRatio );
|
|
this.renderTargetMaskDownSampleBuffer.setSize( resx, resy );
|
|
this.renderTargetMaskDownSampleBuffer.setSize( resx, resy );
|
|
this.renderTargetBlurBuffer1.setSize( resx, resy );
|
|
this.renderTargetBlurBuffer1.setSize( resx, resy );
|
|
this.renderTargetEdgeBuffer1.setSize( resx, resy );
|
|
this.renderTargetEdgeBuffer1.setSize( resx, resy );
|
|
@@ -171,11 +169,11 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( resx, resy );
|
|
this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( resx, resy );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- changeVisibilityOfSelectedObjects: function ( bVisible ) {
|
|
|
|
|
|
+ changeVisibilityOfSelectedObjects( bVisible ) {
|
|
|
|
|
|
- var cache = this._visibilityCache;
|
|
|
|
|
|
+ const cache = this._visibilityCache;
|
|
|
|
|
|
function gatherSelectedMeshesCallBack( object ) {
|
|
function gatherSelectedMeshesCallBack( object ) {
|
|
|
|
|
|
@@ -196,19 +194,19 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- for ( var i = 0; i < this.selectedObjects.length; i ++ ) {
|
|
|
|
|
|
+ for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
|
|
|
|
|
|
- var selectedObject = this.selectedObjects[ i ];
|
|
|
|
|
|
+ const selectedObject = this.selectedObjects[ i ];
|
|
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
|
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- changeVisibilityOfNonSelectedObjects: function ( bVisible ) {
|
|
|
|
|
|
+ changeVisibilityOfNonSelectedObjects( bVisible ) {
|
|
|
|
|
|
- var cache = this._visibilityCache;
|
|
|
|
- var selectedMeshes = [];
|
|
|
|
|
|
+ const cache = this._visibilityCache;
|
|
|
|
+ const selectedMeshes = [];
|
|
|
|
|
|
function gatherSelectedMeshesCallBack( object ) {
|
|
function gatherSelectedMeshesCallBack( object ) {
|
|
|
|
|
|
@@ -216,9 +214,9 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- for ( var i = 0; i < this.selectedObjects.length; i ++ ) {
|
|
|
|
|
|
+ for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
|
|
|
|
|
|
- var selectedObject = this.selectedObjects[ i ];
|
|
|
|
|
|
+ const selectedObject = this.selectedObjects[ i ];
|
|
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
|
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
|
|
|
|
|
}
|
|
}
|
|
@@ -229,11 +227,11 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
// only meshes and sprites are supported by OutlinePass
|
|
// only meshes and sprites are supported by OutlinePass
|
|
|
|
|
|
- var bFound = false;
|
|
|
|
|
|
+ let bFound = false;
|
|
|
|
|
|
- for ( var i = 0; i < selectedMeshes.length; i ++ ) {
|
|
|
|
|
|
+ for ( let i = 0; i < selectedMeshes.length; i ++ ) {
|
|
|
|
|
|
- var selectedObjectId = selectedMeshes[ i ].id;
|
|
|
|
|
|
+ const selectedObjectId = selectedMeshes[ i ].id;
|
|
|
|
|
|
if ( selectedObjectId === object.id ) {
|
|
if ( selectedObjectId === object.id ) {
|
|
|
|
|
|
@@ -246,7 +244,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
if ( bFound === false ) {
|
|
if ( bFound === false ) {
|
|
|
|
|
|
- var visibility = object.visible;
|
|
|
|
|
|
+ const visibility = object.visible;
|
|
|
|
|
|
if ( bVisible === false || cache.get( object ) === true ) {
|
|
if ( bVisible === false || cache.get( object ) === true ) {
|
|
|
|
|
|
@@ -280,9 +278,9 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
this.renderScene.traverse( VisibilityChangeCallBack );
|
|
this.renderScene.traverse( VisibilityChangeCallBack );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- updateTextureMatrix: function () {
|
|
|
|
|
|
+ updateTextureMatrix() {
|
|
|
|
|
|
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
|
|
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
|
|
0.0, 0.5, 0.0, 0.5,
|
|
0.0, 0.5, 0.0, 0.5,
|
|
@@ -291,15 +289,15 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
this.textureMatrix.multiply( this.renderCamera.projectionMatrix );
|
|
this.textureMatrix.multiply( this.renderCamera.projectionMatrix );
|
|
this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse );
|
|
this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
|
|
|
|
|
|
+ render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
|
|
|
|
|
|
if ( this.selectedObjects.length > 0 ) {
|
|
if ( this.selectedObjects.length > 0 ) {
|
|
|
|
|
|
renderer.getClearColor( this._oldClearColor );
|
|
renderer.getClearColor( this._oldClearColor );
|
|
this.oldClearAlpha = renderer.getClearAlpha();
|
|
this.oldClearAlpha = renderer.getClearAlpha();
|
|
- var oldAutoClear = renderer.autoClear;
|
|
|
|
|
|
+ const oldAutoClear = renderer.autoClear;
|
|
|
|
|
|
renderer.autoClear = false;
|
|
renderer.autoClear = false;
|
|
|
|
|
|
@@ -310,7 +308,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
// Make selected objects invisible
|
|
// Make selected objects invisible
|
|
this.changeVisibilityOfSelectedObjects( false );
|
|
this.changeVisibilityOfSelectedObjects( false );
|
|
|
|
|
|
- var currentBackground = this.renderScene.background;
|
|
|
|
|
|
+ const currentBackground = this.renderScene.background;
|
|
this.renderScene.background = null;
|
|
this.renderScene.background = null;
|
|
|
|
|
|
// 1. Draw Non Selected objects in the depth buffer
|
|
// 1. Draw Non Selected objects in the depth buffer
|
|
@@ -353,7 +351,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
if ( this.pulsePeriod > 0 ) {
|
|
if ( this.pulsePeriod > 0 ) {
|
|
|
|
|
|
- var scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2;
|
|
|
|
|
|
+ const scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2;
|
|
this.tempPulseColor1.multiplyScalar( scalar );
|
|
this.tempPulseColor1.multiplyScalar( scalar );
|
|
this.tempPulseColor2.multiplyScalar( scalar );
|
|
this.tempPulseColor2.multiplyScalar( scalar );
|
|
|
|
|
|
@@ -426,9 +424,9 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- getPrepareMaskMaterial: function () {
|
|
|
|
|
|
+ getPrepareMaskMaterial() {
|
|
|
|
|
|
return new ShaderMaterial( {
|
|
return new ShaderMaterial( {
|
|
|
|
|
|
@@ -438,51 +436,49 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
'textureMatrix': { value: null }
|
|
'textureMatrix': { value: null }
|
|
},
|
|
},
|
|
|
|
|
|
- vertexShader: [
|
|
|
|
- '#include <morphtarget_pars_vertex>',
|
|
|
|
- '#include <skinning_pars_vertex>',
|
|
|
|
|
|
+ vertexShader:
|
|
|
|
+ `#include <morphtarget_pars_vertex>
|
|
|
|
+ #include <skinning_pars_vertex>
|
|
|
|
|
|
- 'varying vec4 projTexCoord;',
|
|
|
|
- 'varying vec4 vPosition;',
|
|
|
|
- 'uniform mat4 textureMatrix;',
|
|
|
|
|
|
+ varying vec4 projTexCoord;
|
|
|
|
+ varying vec4 vPosition;
|
|
|
|
+ uniform mat4 textureMatrix;
|
|
|
|
|
|
- 'void main() {',
|
|
|
|
|
|
+ void main() {
|
|
|
|
|
|
- ' #include <skinbase_vertex>',
|
|
|
|
- ' #include <begin_vertex>',
|
|
|
|
- ' #include <morphtarget_vertex>',
|
|
|
|
- ' #include <skinning_vertex>',
|
|
|
|
- ' #include <project_vertex>',
|
|
|
|
|
|
+ #include <skinbase_vertex>
|
|
|
|
+ #include <begin_vertex>
|
|
|
|
+ #include <morphtarget_vertex>
|
|
|
|
+ #include <skinning_vertex>
|
|
|
|
+ #include <project_vertex>
|
|
|
|
|
|
- ' vPosition = mvPosition;',
|
|
|
|
- ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
|
|
|
|
- ' projTexCoord = textureMatrix * worldPosition;',
|
|
|
|
|
|
+ vPosition = mvPosition;
|
|
|
|
+ vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
|
|
|
|
+ projTexCoord = textureMatrix * worldPosition;
|
|
|
|
|
|
- '}'
|
|
|
|
- ].join( '\n' ),
|
|
|
|
|
|
+ }`,
|
|
|
|
|
|
- fragmentShader: [
|
|
|
|
- '#include <packing>',
|
|
|
|
- 'varying vec4 vPosition;',
|
|
|
|
- 'varying vec4 projTexCoord;',
|
|
|
|
- 'uniform sampler2D depthTexture;',
|
|
|
|
- 'uniform vec2 cameraNearFar;',
|
|
|
|
|
|
+ fragmentShader:
|
|
|
|
+ `#include <packing>
|
|
|
|
+ varying vec4 vPosition;
|
|
|
|
+ varying vec4 projTexCoord;
|
|
|
|
+ uniform sampler2D depthTexture;
|
|
|
|
+ uniform vec2 cameraNearFar;
|
|
|
|
|
|
- 'void main() {',
|
|
|
|
|
|
+ void main() {
|
|
|
|
|
|
- ' float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));',
|
|
|
|
- ' float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );',
|
|
|
|
- ' float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;',
|
|
|
|
- ' gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);',
|
|
|
|
|
|
+ float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));
|
|
|
|
+ float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );
|
|
|
|
+ float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;
|
|
|
|
+ gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);
|
|
|
|
|
|
- '}'
|
|
|
|
- ].join( '\n' )
|
|
|
|
|
|
+ }`
|
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- getEdgeDetectionMaterial: function () {
|
|
|
|
|
|
+ getEdgeDetectionMaterial() {
|
|
|
|
|
|
return new ShaderMaterial( {
|
|
return new ShaderMaterial( {
|
|
|
|
|
|
@@ -494,40 +490,42 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
},
|
|
},
|
|
|
|
|
|
vertexShader:
|
|
vertexShader:
|
|
- 'varying vec2 vUv;\n\
|
|
|
|
- void main() {\n\
|
|
|
|
- vUv = uv;\n\
|
|
|
|
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
|
|
|
|
- }',
|
|
|
|
|
|
+ `varying vec2 vUv;
|
|
|
|
+
|
|
|
|
+ void main() {
|
|
|
|
+ vUv = uv;
|
|
|
|
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
|
|
+ }`,
|
|
|
|
|
|
fragmentShader:
|
|
fragmentShader:
|
|
- 'varying vec2 vUv;\
|
|
|
|
- uniform sampler2D maskTexture;\
|
|
|
|
- uniform vec2 texSize;\
|
|
|
|
- uniform vec3 visibleEdgeColor;\
|
|
|
|
- uniform vec3 hiddenEdgeColor;\
|
|
|
|
- \
|
|
|
|
- void main() {\n\
|
|
|
|
- vec2 invSize = 1.0 / texSize;\
|
|
|
|
- vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\
|
|
|
|
- vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\
|
|
|
|
- vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\
|
|
|
|
- vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\
|
|
|
|
- vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\
|
|
|
|
- float diff1 = (c1.r - c2.r)*0.5;\
|
|
|
|
- float diff2 = (c3.r - c4.r)*0.5;\
|
|
|
|
- float d = length( vec2(diff1, diff2) );\
|
|
|
|
- float a1 = min(c1.g, c2.g);\
|
|
|
|
- float a2 = min(c3.g, c4.g);\
|
|
|
|
- float visibilityFactor = min(a1, a2);\
|
|
|
|
- vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\
|
|
|
|
- gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\
|
|
|
|
- }'
|
|
|
|
|
|
+ `varying vec2 vUv;
|
|
|
|
+
|
|
|
|
+ uniform sampler2D maskTexture;
|
|
|
|
+ uniform vec2 texSize;
|
|
|
|
+ uniform vec3 visibleEdgeColor;
|
|
|
|
+ uniform vec3 hiddenEdgeColor;
|
|
|
|
+
|
|
|
|
+ void main() {
|
|
|
|
+ vec2 invSize = 1.0 / texSize;
|
|
|
|
+ vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);
|
|
|
|
+ vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);
|
|
|
|
+ vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);
|
|
|
|
+ vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);
|
|
|
|
+ vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);
|
|
|
|
+ float diff1 = (c1.r - c2.r)*0.5;
|
|
|
|
+ float diff2 = (c3.r - c4.r)*0.5;
|
|
|
|
+ float d = length( vec2(diff1, diff2) );
|
|
|
|
+ float a1 = min(c1.g, c2.g);
|
|
|
|
+ float a2 = min(c3.g, c4.g);
|
|
|
|
+ float visibilityFactor = min(a1, a2);
|
|
|
|
+ vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;
|
|
|
|
+ gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);
|
|
|
|
+ }`
|
|
} );
|
|
} );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- getSeperableBlurMaterial: function ( maxRadius ) {
|
|
|
|
|
|
+ getSeperableBlurMaterial( maxRadius ) {
|
|
|
|
|
|
return new ShaderMaterial( {
|
|
return new ShaderMaterial( {
|
|
|
|
|
|
@@ -543,44 +541,46 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
},
|
|
},
|
|
|
|
|
|
vertexShader:
|
|
vertexShader:
|
|
- 'varying vec2 vUv;\n\
|
|
|
|
- void main() {\n\
|
|
|
|
- vUv = uv;\n\
|
|
|
|
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
|
|
|
|
- }',
|
|
|
|
|
|
+ `varying vec2 vUv;
|
|
|
|
+
|
|
|
|
+ void main() {
|
|
|
|
+ vUv = uv;
|
|
|
|
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
|
|
+ }`,
|
|
|
|
|
|
fragmentShader:
|
|
fragmentShader:
|
|
- '#include <common>\
|
|
|
|
- varying vec2 vUv;\
|
|
|
|
- uniform sampler2D colorTexture;\
|
|
|
|
- uniform vec2 texSize;\
|
|
|
|
- uniform vec2 direction;\
|
|
|
|
- uniform float kernelRadius;\
|
|
|
|
- \
|
|
|
|
- float gaussianPdf(in float x, in float sigma) {\
|
|
|
|
- return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\
|
|
|
|
- }\
|
|
|
|
- void main() {\
|
|
|
|
- vec2 invSize = 1.0 / texSize;\
|
|
|
|
- float weightSum = gaussianPdf(0.0, kernelRadius);\
|
|
|
|
- vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;\
|
|
|
|
- vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\
|
|
|
|
- vec2 uvOffset = delta;\
|
|
|
|
- for( int i = 1; i <= MAX_RADIUS; i ++ ) {\
|
|
|
|
- float w = gaussianPdf(uvOffset.x, kernelRadius);\
|
|
|
|
- vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\
|
|
|
|
- vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\
|
|
|
|
- diffuseSum += ((sample1 + sample2) * w);\
|
|
|
|
- weightSum += (2.0 * w);\
|
|
|
|
- uvOffset += delta;\
|
|
|
|
- }\
|
|
|
|
- gl_FragColor = diffuseSum/weightSum;\
|
|
|
|
- }'
|
|
|
|
|
|
+ `#include <common>
|
|
|
|
+ varying vec2 vUv;
|
|
|
|
+ uniform sampler2D colorTexture;
|
|
|
|
+ uniform vec2 texSize;
|
|
|
|
+ uniform vec2 direction;
|
|
|
|
+ uniform float kernelRadius;
|
|
|
|
+
|
|
|
|
+ float gaussianPdf(in float x, in float sigma) {
|
|
|
|
+ return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void main() {
|
|
|
|
+ vec2 invSize = 1.0 / texSize;
|
|
|
|
+ float weightSum = gaussianPdf(0.0, kernelRadius);
|
|
|
|
+ vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;
|
|
|
|
+ vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);
|
|
|
|
+ vec2 uvOffset = delta;
|
|
|
|
+ for( int i = 1; i <= MAX_RADIUS; i ++ ) {
|
|
|
|
+ float w = gaussianPdf(uvOffset.x, kernelRadius);
|
|
|
|
+ vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
|
|
|
|
+ vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
|
|
|
|
+ diffuseSum += ((sample1 + sample2) * w);
|
|
|
|
+ weightSum += (2.0 * w);
|
|
|
|
+ uvOffset += delta;
|
|
|
|
+ }
|
|
|
|
+ gl_FragColor = diffuseSum/weightSum;
|
|
|
|
+ }`
|
|
} );
|
|
} );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- getOverlayMaterial: function () {
|
|
|
|
|
|
+ getOverlayMaterial() {
|
|
|
|
|
|
return new ShaderMaterial( {
|
|
return new ShaderMaterial( {
|
|
|
|
|
|
@@ -595,34 +595,36 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
},
|
|
},
|
|
|
|
|
|
vertexShader:
|
|
vertexShader:
|
|
- 'varying vec2 vUv;\n\
|
|
|
|
- void main() {\n\
|
|
|
|
- vUv = uv;\n\
|
|
|
|
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
|
|
|
|
- }',
|
|
|
|
|
|
+ `varying vec2 vUv;
|
|
|
|
+
|
|
|
|
+ void main() {
|
|
|
|
+ vUv = uv;
|
|
|
|
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
|
|
+ }`,
|
|
|
|
|
|
fragmentShader:
|
|
fragmentShader:
|
|
- 'varying vec2 vUv;\
|
|
|
|
- uniform sampler2D maskTexture;\
|
|
|
|
- uniform sampler2D edgeTexture1;\
|
|
|
|
- uniform sampler2D edgeTexture2;\
|
|
|
|
- uniform sampler2D patternTexture;\
|
|
|
|
- uniform float edgeStrength;\
|
|
|
|
- uniform float edgeGlow;\
|
|
|
|
- uniform bool usePatternTexture;\
|
|
|
|
- \
|
|
|
|
- void main() {\
|
|
|
|
- vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\
|
|
|
|
- vec4 edgeValue2 = texture2D(edgeTexture2, vUv);\
|
|
|
|
- vec4 maskColor = texture2D(maskTexture, vUv);\
|
|
|
|
- vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\
|
|
|
|
- float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\
|
|
|
|
- vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\
|
|
|
|
- vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\
|
|
|
|
- if(usePatternTexture)\
|
|
|
|
- finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\
|
|
|
|
- gl_FragColor = finalColor;\
|
|
|
|
- }',
|
|
|
|
|
|
+ `varying vec2 vUv;
|
|
|
|
+
|
|
|
|
+ uniform sampler2D maskTexture;
|
|
|
|
+ uniform sampler2D edgeTexture1;
|
|
|
|
+ uniform sampler2D edgeTexture2;
|
|
|
|
+ uniform sampler2D patternTexture;
|
|
|
|
+ uniform float edgeStrength;
|
|
|
|
+ uniform float edgeGlow;
|
|
|
|
+ uniform bool usePatternTexture;
|
|
|
|
+
|
|
|
|
+ void main() {
|
|
|
|
+ vec4 edgeValue1 = texture2D(edgeTexture1, vUv);
|
|
|
|
+ vec4 edgeValue2 = texture2D(edgeTexture2, vUv);
|
|
|
|
+ vec4 maskColor = texture2D(maskTexture, vUv);
|
|
|
|
+ vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);
|
|
|
|
+ float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;
|
|
|
|
+ vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;
|
|
|
|
+ vec4 finalColor = edgeStrength * maskColor.r * edgeValue;
|
|
|
|
+ if(usePatternTexture)
|
|
|
|
+ finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);
|
|
|
|
+ gl_FragColor = finalColor;
|
|
|
|
+ }`,
|
|
blending: AdditiveBlending,
|
|
blending: AdditiveBlending,
|
|
depthTest: false,
|
|
depthTest: false,
|
|
depthWrite: false,
|
|
depthWrite: false,
|
|
@@ -631,7 +633,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-} );
|
|
|
|
|
|
+}
|
|
|
|
|
|
OutlinePass.BlurDirectionX = new Vector2( 1.0, 0.0 );
|
|
OutlinePass.BlurDirectionX = new Vector2( 1.0, 0.0 );
|
|
OutlinePass.BlurDirectionY = new Vector2( 0.0, 1.0 );
|
|
OutlinePass.BlurDirectionY = new Vector2( 0.0, 1.0 );
|