(function (global, factory) { if (typeof define === "function" && define.amd) { define(["exports", "three", "./Pass.js", "../shaders/CopyShader.js"], factory); } else if (typeof exports !== "undefined") { factory(exports, require("three"), require("./Pass.js"), require("../shaders/CopyShader.js")); } else { var mod = { exports: {} }; factory(mod.exports, global.three, global.Pass, global.CopyShader); global.OutlinePass = mod.exports; } })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three, _Pass2, _CopyShader) { "use strict"; Object.defineProperty(_exports, "__esModule", { value: true }); _exports.OutlinePass = void 0; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } var OutlinePass = /*#__PURE__*/function (_Pass) { _inherits(OutlinePass, _Pass); var _super = _createSuper(OutlinePass); function OutlinePass(resolution, scene, camera, selectedObjects) { var _this; _classCallCheck(this, OutlinePass); _this = _super.call(this); _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.edgeGlow = 0.0; _this.usePatternTexture = false; _this.edgeThickness = 1.0; _this.edgeStrength = 3.0; _this.downSampleRatio = 2; _this.pulsePeriod = 0; _this._visibilityCache = new Map(); _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); _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.name = 'OutlinePass.mask'; _this.renderTargetMaskBuffer.texture.generateMipmaps = false; _this.depthMaterial = new _three.MeshDepthMaterial(); _this.depthMaterial.side = _three.DoubleSide; _this.depthMaterial.depthPacking = _three.RGBADepthPacking; _this.depthMaterial.blending = _three.NoBlending; _this.prepareMaskMaterial = _this.getPrepareMaskMaterial(); _this.prepareMaskMaterial.side = _three.DoubleSide; _this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ(_this.prepareMaskMaterial.fragmentShader, _this.renderCamera); _this.renderTargetDepthBuffer = new _three.WebGLRenderTarget(_this.resolution.x, _this.resolution.y, pars); _this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth'; _this.renderTargetDepthBuffer.texture.generateMipmaps = false; _this.renderTargetMaskDownSampleBuffer = new _three.WebGLRenderTarget(resx, resy, pars); _this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample'; _this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false; _this.renderTargetBlurBuffer1 = new _three.WebGLRenderTarget(resx, resy, pars); _this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1'; _this.renderTargetBlurBuffer1.texture.generateMipmaps = false; _this.renderTargetBlurBuffer2 = new _three.WebGLRenderTarget(Math.round(resx / 2), Math.round(resy / 2), pars); _this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2'; _this.renderTargetBlurBuffer2.texture.generateMipmaps = false; _this.edgeDetectionMaterial = _this.getEdgeDetectionMaterial(); _this.renderTargetEdgeBuffer1 = new _three.WebGLRenderTarget(resx, resy, pars); _this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1'; _this.renderTargetEdgeBuffer1.texture.generateMipmaps = false; _this.renderTargetEdgeBuffer2 = new _three.WebGLRenderTarget(Math.round(resx / 2), Math.round(resy / 2), pars); _this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2'; _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'].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; // Overlay material _this.overlayMaterial = _this.getOverlayMaterial(); // copy material if (_CopyShader.CopyShader === undefined) console.error('THREE.OutlinePass relies on CopyShader'); var copyShader = _CopyShader.CopyShader; _this.copyUniforms = _three.UniformsUtils.clone(copyShader.uniforms); _this.copyUniforms['opacity'].value = 1.0; _this.materialCopy = new _three.ShaderMaterial({ uniforms: _this.copyUniforms, vertexShader: copyShader.vertexShader, fragmentShader: copyShader.fragmentShader, blending: _three.NoBlending, depthTest: false, depthWrite: false, transparent: true }); _this.enabled = true; _this.needsSwap = false; _this._oldClearColor = new _three.Color(); _this.oldClearAlpha = 1; _this.fsQuad = new _Pass2.FullScreenQuad(null); _this.tempPulseColor1 = new _three.Color(); _this.tempPulseColor2 = new _three.Color(); _this.textureMatrix = new _three.Matrix4(); function replaceDepthToViewZ(string, camera) { var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic'; return string.replace(/DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ'); } return _this; } _createClass(OutlinePass, [{ key: "dispose", value: function dispose() { this.renderTargetMaskBuffer.dispose(); this.renderTargetDepthBuffer.dispose(); this.renderTargetMaskDownSampleBuffer.dispose(); this.renderTargetBlurBuffer1.dispose(); this.renderTargetBlurBuffer2.dispose(); this.renderTargetEdgeBuffer1.dispose(); this.renderTargetEdgeBuffer2.dispose(); } }, { key: "setSize", value: function setSize(width, height) { this.renderTargetMaskBuffer.setSize(width, height); this.renderTargetDepthBuffer.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'].value.set(resx, resy); resx = Math.round(resx / 2); resy = Math.round(resy / 2); this.renderTargetBlurBuffer2.setSize(resx, resy); this.renderTargetEdgeBuffer2.setSize(resx, resy); this.separableBlurMaterial2.uniforms['texSize'].value.set(resx, resy); } }, { key: "changeVisibilityOfSelectedObjects", value: function changeVisibilityOfSelectedObjects(bVisible) { var cache = this._visibilityCache; function gatherSelectedMeshesCallBack(object) { if (object.isMesh) { if (bVisible === true) { object.visible = cache.get(object); } else { cache.set(object, object.visible); object.visible = bVisible; } } } for (var i = 0; i < this.selectedObjects.length; i++) { var selectedObject = this.selectedObjects[i]; selectedObject.traverse(gatherSelectedMeshesCallBack); } } }, { key: "changeVisibilityOfNonSelectedObjects", value: function changeVisibilityOfNonSelectedObjects(bVisible) { var cache = this._visibilityCache; var selectedMeshes = []; function gatherSelectedMeshesCallBack(object) { if (object.isMesh) selectedMeshes.push(object); } for (var i = 0; i < this.selectedObjects.length; i++) { var selectedObject = this.selectedObjects[i]; selectedObject.traverse(gatherSelectedMeshesCallBack); } function VisibilityChangeCallBack(object) { if (object.isMesh || object.isSprite) { // only meshes and sprites are supported by OutlinePass var bFound = false; for (var _i = 0; _i < selectedMeshes.length; _i++) { var selectedObjectId = selectedMeshes[_i].id; if (selectedObjectId === object.id) { bFound = true; break; } } if (bFound === false) { var visibility = object.visible; if (bVisible === false || cache.get(object) === true) { object.visible = bVisible; } cache.set(object, visibility); } } else if (object.isPoints || object.isLine) { // the visibilty of points and lines is always set to false in order to // not affect the outline computation if (bVisible === true) { object.visible = cache.get(object); // restore } else { cache.set(object, object.visible); object.visible = bVisible; } } } this.renderScene.traverse(VisibilityChangeCallBack); } }, { key: "updateTextureMatrix", value: function updateTextureMatrix() { this.textureMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0); this.textureMatrix.multiply(this.renderCamera.projectionMatrix); this.textureMatrix.multiply(this.renderCamera.matrixWorldInverse); } }, { key: "render", value: function render(renderer, writeBuffer, readBuffer, deltaTime, maskActive) { if (this.selectedObjects.length > 0) { renderer.getClearColor(this._oldClearColor); this.oldClearAlpha = renderer.getClearAlpha(); var oldAutoClear = renderer.autoClear; renderer.autoClear = false; if (maskActive) renderer.state.buffers.stencil.setTest(false); renderer.setClearColor(0xffffff, 1); // Make selected objects invisible this.changeVisibilityOfSelectedObjects(false); var currentBackground = this.renderScene.background; this.renderScene.background = null; // 1. Draw Non Selected objects in the depth buffer this.renderScene.overrideMaterial = this.depthMaterial; renderer.setRenderTarget(this.renderTargetDepthBuffer); renderer.clear(); renderer.render(this.renderScene, this.renderCamera); // Make selected objects visible this.changeVisibilityOfSelectedObjects(true); this._visibilityCache.clear(); // 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.renderScene.overrideMaterial = this.prepareMaskMaterial; this.prepareMaskMaterial.uniforms['cameraNearFar'].value.set(this.renderCamera.near, this.renderCamera.far); this.prepareMaskMaterial.uniforms['depthTexture'].value = this.renderTargetDepthBuffer.texture; this.prepareMaskMaterial.uniforms['textureMatrix'].value = this.textureMatrix; renderer.setRenderTarget(this.renderTargetMaskBuffer); renderer.clear(); renderer.render(this.renderScene, this.renderCamera); this.renderScene.overrideMaterial = null; this.changeVisibilityOfNonSelectedObjects(true); this._visibilityCache.clear(); this.renderScene.background = currentBackground; // 2. Downsample to Half resolution this.fsQuad.material = this.materialCopy; this.copyUniforms['tDiffuse'].value = this.renderTargetMaskBuffer.texture; renderer.setRenderTarget(this.renderTargetMaskDownSampleBuffer); renderer.clear(); this.fsQuad.render(renderer); 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; this.tempPulseColor1.multiplyScalar(scalar); this.tempPulseColor2.multiplyScalar(scalar); } // 3. Apply Edge Detection Pass this.fsQuad.material = this.edgeDetectionMaterial; this.edgeDetectionMaterial.uniforms['maskTexture'].value = this.renderTargetMaskDownSampleBuffer.texture; this.edgeDetectionMaterial.uniforms['texSize'].value.set(this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height); this.edgeDetectionMaterial.uniforms['visibleEdgeColor'].value = this.tempPulseColor1; this.edgeDetectionMaterial.uniforms['hiddenEdgeColor'].value = this.tempPulseColor2; renderer.setRenderTarget(this.renderTargetEdgeBuffer1); renderer.clear(); this.fsQuad.render(renderer); // 4. Apply Blur on Half res this.fsQuad.material = this.separableBlurMaterial1; this.separableBlurMaterial1.uniforms['colorTexture'].value = this.renderTargetEdgeBuffer1.texture; this.separableBlurMaterial1.uniforms['direction'].value = OutlinePass.BlurDirectionX; this.separableBlurMaterial1.uniforms['kernelRadius'].value = this.edgeThickness; renderer.setRenderTarget(this.renderTargetBlurBuffer1); renderer.clear(); this.fsQuad.render(renderer); this.separableBlurMaterial1.uniforms['colorTexture'].value = this.renderTargetBlurBuffer1.texture; this.separableBlurMaterial1.uniforms['direction'].value = OutlinePass.BlurDirectionY; renderer.setRenderTarget(this.renderTargetEdgeBuffer1); renderer.clear(); this.fsQuad.render(renderer); // Apply Blur on quarter res this.fsQuad.material = this.separableBlurMaterial2; this.separableBlurMaterial2.uniforms['colorTexture'].value = this.renderTargetEdgeBuffer1.texture; this.separableBlurMaterial2.uniforms['direction'].value = OutlinePass.BlurDirectionX; renderer.setRenderTarget(this.renderTargetBlurBuffer2); renderer.clear(); this.fsQuad.render(renderer); this.separableBlurMaterial2.uniforms['colorTexture'].value = this.renderTargetBlurBuffer2.texture; this.separableBlurMaterial2.uniforms['direction'].value = OutlinePass.BlurDirectionY; renderer.setRenderTarget(this.renderTargetEdgeBuffer2); renderer.clear(); this.fsQuad.render(renderer); // Blend it additively over the input texture this.fsQuad.material = this.overlayMaterial; this.overlayMaterial.uniforms['maskTexture'].value = this.renderTargetMaskBuffer.texture; this.overlayMaterial.uniforms['edgeTexture1'].value = this.renderTargetEdgeBuffer1.texture; this.overlayMaterial.uniforms['edgeTexture2'].value = this.renderTargetEdgeBuffer2.texture; this.overlayMaterial.uniforms['patternTexture'].value = this.patternTexture; this.overlayMaterial.uniforms['edgeStrength'].value = this.edgeStrength; this.overlayMaterial.uniforms['edgeGlow'].value = this.edgeGlow; this.overlayMaterial.uniforms['usePatternTexture'].value = this.usePatternTexture; if (maskActive) renderer.state.buffers.stencil.setTest(true); renderer.setRenderTarget(readBuffer); this.fsQuad.render(renderer); renderer.setClearColor(this._oldClearColor, this.oldClearAlpha); renderer.autoClear = oldAutoClear; } if (this.renderToScreen) { this.fsQuad.material = this.materialCopy; this.copyUniforms['tDiffuse'].value = readBuffer.texture; renderer.setRenderTarget(null); this.fsQuad.render(renderer); } } }, { key: "getPrepareMaskMaterial", value: function getPrepareMaskMaterial() { return new _three.ShaderMaterial({ uniforms: { 'depthTexture': { value: null }, 'cameraNearFar': { value: new _three.Vector2(0.5, 0.5) }, 'textureMatrix': { value: null } }, vertexShader: "#include \n\t\t\t\t#include \n\n\t\t\t\tvarying vec4 projTexCoord;\n\t\t\t\tvarying vec4 vPosition;\n\t\t\t\tuniform mat4 textureMatrix;\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t\tvPosition = mvPosition;\n\t\t\t\t\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n\t\t\t\t\tprojTexCoord = textureMatrix * worldPosition;\n\n\t\t\t\t}", fragmentShader: "#include \n\t\t\t\tvarying vec4 vPosition;\n\t\t\t\tvarying vec4 projTexCoord;\n\t\t\t\tuniform sampler2D depthTexture;\n\t\t\t\tuniform vec2 cameraNearFar;\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tfloat depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));\n\t\t\t\t\tfloat viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );\n\t\t\t\t\tfloat depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;\n\t\t\t\t\tgl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);\n\n\t\t\t\t}" }); } }, { key: "getEdgeDetectionMaterial", value: function getEdgeDetectionMaterial() { return new _three.ShaderMaterial({ uniforms: { '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) } }, vertexShader: "varying vec2 vUv;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}", fragmentShader: "varying vec2 vUv;\n\n\t\t\t\tuniform sampler2D maskTexture;\n\t\t\t\tuniform vec2 texSize;\n\t\t\t\tuniform vec3 visibleEdgeColor;\n\t\t\t\tuniform vec3 hiddenEdgeColor;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec2 invSize = 1.0 / texSize;\n\t\t\t\t\tvec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\n\t\t\t\t\tvec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\n\t\t\t\t\tvec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\n\t\t\t\t\tvec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\n\t\t\t\t\tvec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\n\t\t\t\t\tfloat diff1 = (c1.r - c2.r)*0.5;\n\t\t\t\t\tfloat diff2 = (c3.r - c4.r)*0.5;\n\t\t\t\t\tfloat d = length( vec2(diff1, diff2) );\n\t\t\t\t\tfloat a1 = min(c1.g, c2.g);\n\t\t\t\t\tfloat a2 = min(c3.g, c4.g);\n\t\t\t\t\tfloat visibilityFactor = min(a1, a2);\n\t\t\t\t\tvec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\n\t\t\t\t\tgl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\n\t\t\t\t}" }); } }, { key: "getSeperableBlurMaterial", value: function getSeperableBlurMaterial(maxRadius) { return new _three.ShaderMaterial({ defines: { 'MAX_RADIUS': maxRadius }, uniforms: { 'colorTexture': { value: null }, 'texSize': { value: new _three.Vector2(0.5, 0.5) }, 'direction': { value: new _three.Vector2(0.5, 0.5) }, 'kernelRadius': { value: 1.0 } }, vertexShader: "varying vec2 vUv;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}", fragmentShader: "#include \n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tuniform sampler2D colorTexture;\n\t\t\t\tuniform vec2 texSize;\n\t\t\t\tuniform vec2 direction;\n\t\t\t\tuniform float kernelRadius;\n\n\t\t\t\tfloat gaussianPdf(in float x, in float sigma) {\n\t\t\t\t\treturn 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec2 invSize = 1.0 / texSize;\n\t\t\t\t\tfloat weightSum = gaussianPdf(0.0, kernelRadius);\n\t\t\t\t\tvec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;\n\t\t\t\t\tvec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\n\t\t\t\t\tvec2 uvOffset = delta;\n\t\t\t\t\tfor( int i = 1; i <= MAX_RADIUS; i ++ ) {\n\t\t\t\t\t\tfloat w = gaussianPdf(uvOffset.x, kernelRadius);\n\t\t\t\t\t\tvec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\n\t\t\t\t\t\tvec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\n\t\t\t\t\t\tdiffuseSum += ((sample1 + sample2) * w);\n\t\t\t\t\t\tweightSum += (2.0 * w);\n\t\t\t\t\t\tuvOffset += delta;\n\t\t\t\t\t}\n\t\t\t\t\tgl_FragColor = diffuseSum/weightSum;\n\t\t\t\t}" }); } }, { key: "getOverlayMaterial", value: function getOverlayMaterial() { return new _three.ShaderMaterial({ uniforms: { 'maskTexture': { value: null }, 'edgeTexture1': { value: null }, 'edgeTexture2': { value: null }, 'patternTexture': { value: null }, 'edgeStrength': { value: 1.0 }, 'edgeGlow': { value: 1.0 }, 'usePatternTexture': { value: 0.0 } }, vertexShader: "varying vec2 vUv;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}", fragmentShader: "varying vec2 vUv;\n\n\t\t\t\tuniform sampler2D maskTexture;\n\t\t\t\tuniform sampler2D edgeTexture1;\n\t\t\t\tuniform sampler2D edgeTexture2;\n\t\t\t\tuniform sampler2D patternTexture;\n\t\t\t\tuniform float edgeStrength;\n\t\t\t\tuniform float edgeGlow;\n\t\t\t\tuniform bool usePatternTexture;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec4 edgeValue1 = texture2D(edgeTexture1, vUv);\n\t\t\t\t\tvec4 edgeValue2 = texture2D(edgeTexture2, vUv);\n\t\t\t\t\tvec4 maskColor = texture2D(maskTexture, vUv);\n\t\t\t\t\tvec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\n\t\t\t\t\tfloat visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\n\t\t\t\t\tvec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\n\t\t\t\t\tvec4 finalColor = edgeStrength * maskColor.r * edgeValue;\n\t\t\t\t\tif(usePatternTexture)\n\t\t\t\t\t\tfinalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\n\t\t\t\t\tgl_FragColor = finalColor;\n\t\t\t\t}", blending: _three.AdditiveBlending, depthTest: false, depthWrite: false, transparent: true }); } }]); return OutlinePass; }(_Pass2.Pass); _exports.OutlinePass = OutlinePass; OutlinePass.BlurDirectionX = new _three.Vector2(1.0, 0.0); OutlinePass.BlurDirectionY = new _three.Vector2(0.0, 1.0); });