2019-06-06 21:13:51 +08:00

126 lines
3.8 KiB
JavaScript

/**
* @author spidersharma / http://eduperiment.com/
*/
THREE.OutlinePass = function (resolution, scene, camera, selectedObjects) {
this.renderScene = scene;
this.renderCamera = camera;
this.selectedObjects = selectedObjects;
THREE.Pass.call(this);
this.resolution = new THREE.Vector2(resolution.x, resolution.y);
var pars = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
antialias: true,
};
this.renderTargetMaskBuffer = new THREE.WebGLRenderTarget(this.resolution.x, this.resolution.y, pars);
this.renderTargetMaskBuffer.texture.generateMipmaps = false;
this.edgeDetectionMaterial = this.getEdgeDetectionMaterial();
this.renderTargetEdgeBuffer1 = new THREE.WebGLRenderTarget(this.resolution.x, this.resolution.y, pars);
this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
var copyShader = THREE.CopyShader;
this.copyUniforms = THREE.UniformsUtils.clone(copyShader.uniforms);
this.materialCopy = new THREE.ShaderMaterial({
uniforms: this.copyUniforms,
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
blending: THREE.NoBlending,
depthTest: false,
depthWrite: false,
transparent: true
});
this.oldClearColor = new THREE.Color();
this.oldClearAlpha = 1;
this.camera = new THREE.OrthographicCamera(-this.resolution.x / 2, this.resolution.x / 2, this.resolution.y / 2, -this.resolution.y / 2, 0, 1);
this.scene = new THREE.Scene();
this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(this.resolution.x, this.resolution.y), null);
this.quad.frustumCulled = false;
this.scene.add(this.quad);
};
THREE.OutlinePass.prototype = Object.assign(Object.create(THREE.Pass.prototype), {
constructor: THREE.OutlinePass,
render: function (renderer, writeBuffer, readBuffer, deltaTime) {
this.oldClearColor.copy(renderer.getClearColor());
this.oldClearAlpha = renderer.getClearAlpha();
renderer.setClearColor(0xffffff, 1);
renderer.setRenderTarget(this.renderTargetMaskBuffer);
renderer.clear();
renderer.render(this.renderScene, this.renderCamera);
// 3. Apply Edge Detection Pass
this.quad.material = this.edgeDetectionMaterial;
this.edgeDetectionMaterial.uniforms["maskTexture"].value = this.renderTargetMaskBuffer.texture;
this.edgeDetectionMaterial.uniforms["texSize"].value.set(this.resolution.x, this.resolution.y);
renderer.setRenderTarget(this.renderTargetEdgeBuffer1);
renderer.clear();
renderer.render(this.scene, this.camera);
renderer.setClearColor(this.oldClearColor, this.oldClearAlpha);
this.quad.material = this.materialCopy;
this.copyUniforms["tDiffuse"].value = this.renderTargetEdgeBuffer1.texture;
renderer.setRenderTarget(null);
renderer.render(this.scene, this.camera);
},
getEdgeDetectionMaterial: function () {
return new THREE.ShaderMaterial({
uniforms: {
"maskTexture": {
value: null
},
"texSize": {
value: new THREE.Vector2(0.5, 0.5)
},
"edgeColor": {
value: new THREE.Vector3(1.0, 0.0, 0.0)
},
},
vertexShader: "varying vec2 vUv;\n\
void main() {\n\
vUv = uv;\n\
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
}",
fragmentShader: "varying vec2 vUv;\
uniform sampler2D maskTexture;\
uniform vec2 texSize;\
uniform vec3 edgeColor;\
\
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) );\
gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\
}"
});
}
});