canvas{
width: 100%;
height: 100%;
}
View Compiled
if (!Detector.webgl) Detector.addGetWebGLMessage();
let scene = null;
let normal = null;
let outline = null;
let outScene = null;
let maskScene = null;
let light = null;
let renderer = null;
let composer = null;
let camera1 = null;
let camera2 = null;
let camera3 = null;
let mesh1 = null;
let mesh2 = null;
let mesh3 = null;
let bg_mesh = null;
let renderTarget = null;
let screenWidth = window.innerWidth;
let screenHeight = window.innerHeight;
const clock = new THREE.Clock;
let elapsedTime = 0;
let frameCount = 0;
const init = function() {
// SCENE
scene = new THREE.Scene;
maskScene = new THREE.Scene;
outScene = new THREE.Scene;
setModel();
// SCENE CAMERA
camera1 = new THREE.PerspectiveCamera(40, screenWidth/screenHeight, 1, 1000);
camera1.position.set(0, 0, 10);
scene.add(camera1);
camera2 = new THREE.PerspectiveCamera(40, screenWidth/screenHeight, 1, 1000);
camera2.position.set(0, 0, 10);
outScene.add(camera2);
camera3 = new THREE.PerspectiveCamera(40, screenWidth/screenHeight, 1, 1000);
camera3.position.set(0, 0, 10);
maskScene.add(camera3);
scene.background = new THREE.Color( 0xffffff );
// RENDERER
renderer = new THREE.WebGLRenderer({
width: screenWidth,
height: screenHeight,
antialias: true
});
renderer.setSize(screenWidth, screenHeight);
renderer.setClearColor(0x000000);
renderer.autoClear = false;
renderer.gammaInput = true;
renderer.gammaOutput = true;
document.body.appendChild(renderer.domElement);
// POSTPROCESSING
const renderTargetParameters = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
stencilBuffer: true
};
renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters);
composer = new THREE.EffectComposer(renderer);
composer.renderTarget1.stencilBuffer = true;
composer.renderTarget2.stencilBuffer = true;
normal = new THREE.RenderPass(scene, camera1);
outline = new THREE.RenderPass(outScene, camera2);
outline.clear = false;
const mask = new THREE.MaskPass(maskScene, camera3);
mask.inverse = false;
const clearMask = new THREE.ClearMaskPass;
const copyPass = new THREE.ShaderPass(THREE.CopyShader);
copyPass.renderToScreen = true;
composer.addPass(normal);
composer.addPass(mask);
composer.addPass(outline);
composer.addPass(clearMask);
composer.addPass(copyPass);
// EVENTS
return window.addEventListener('resize', onWindowResize, false);
};
var setModel = function() {
var box_mask_1 = new THREE.CircleGeometry( 2, 4 );
var box_mask_2 = new THREE.CircleGeometry( 2, 4 );
var singleGeometry_mask = new THREE.Geometry();
var boxMesh_mask_1 = new THREE.Mesh(box_mask_1);
boxMesh_mask_1.position.z = 1;
var boxMesh_mask_2 = new THREE.Mesh(box_mask_2);
boxMesh_mask_2.rotation.y = Math.PI;
boxMesh_mask_2.position.z = -1;
boxMesh_mask_1.updateMatrix(); // as needed
singleGeometry_mask.merge(boxMesh_mask_1.geometry, boxMesh_mask_1.matrix);
boxMesh_mask_2.updateMatrix(); // as needed
singleGeometry_mask.merge(boxMesh_mask_2.geometry, boxMesh_mask_2.matrix);
var box_1_1 = new THREE.CircleGeometry( 2, 4 );
var box_1_2 = new THREE.CircleGeometry( 2, 4 );
var singleGeometry_1 = new THREE.Geometry();
var boxMesh_1_1 = new THREE.Mesh(box_1_1);
boxMesh_1_1.position.z = -1;
var boxMesh_1_2 = new THREE.Mesh(box_1_2);
boxMesh_1_2.rotation.y = Math.PI;
boxMesh_1_2.position.z = 1;
boxMesh_1_1.updateMatrix();
singleGeometry_1.merge(boxMesh_1_1.geometry, boxMesh_1_1.matrix);
boxMesh_1_2.updateMatrix();
singleGeometry_1.merge(boxMesh_1_2.geometry, boxMesh_1_2.matrix);
var box_2_1 = new THREE.CircleGeometry( 2, 4 );
var box_2_2 = new THREE.CircleGeometry( 2, 4 );
var singleGeometry_2 = new THREE.Geometry();
var boxMesh_2_1 = new THREE.Mesh(box_2_1);
boxMesh_2_1.position.z = -1;
var boxMesh_2_2 = new THREE.Mesh(box_2_2);
boxMesh_2_2.rotation.y = Math.PI;
boxMesh_2_2.position.z = 1;
boxMesh_2_1.updateMatrix();
singleGeometry_2.merge(boxMesh_2_1.geometry, boxMesh_2_1.matrix);
boxMesh_2_2.updateMatrix();
singleGeometry_2.merge(boxMesh_2_2.geometry, boxMesh_2_2.matrix);
const matColor = new THREE.MeshBasicMaterial({
color: 0x000000});
mesh1 = new THREE.Mesh(singleGeometry_1, matColor); // geometry, matColor);
scene.add(mesh1);
// flat mask
const matFlat = new THREE.MeshBasicMaterial({
color: 0x000000});
mesh2 = new THREE.Mesh(singleGeometry_mask, matFlat);
maskScene.add(mesh2);
const matColor2 = new THREE.MeshBasicMaterial({
color: 0xffffff});
mesh3 = new THREE.Mesh(singleGeometry_2, matColor2);
outScene.add(mesh3);
const matColor3 = new THREE.MeshBasicMaterial({
color: 0x000000});
bg_mesh = new THREE.Mesh(new THREE.CircleGeometry( 100, 4 ), matColor3);
outScene.add(bg_mesh);
bg_mesh.position.set(0, 0, -10);
};
var onWindowResize = function() {
screenWidth = window.innerWidth;
screenHeight = window.innerHeight;
camera1.aspect = screenWidth / screenHeight;
camera2.aspect = camera1.aspect;
camera3.aspect = camera1.aspect;
camera1.updateProjectionMatrix();
camera2.updateProjectionMatrix();
camera3.updateProjectionMatrix();
return renderer.setSize(screenWidth, screenHeight);
};
var animate = function() {
updateFps();
requestAnimationFrame(animate);
return render();
};
var render = function() {
const now = Date.now();
const delta = clock.getDelta();
if (mesh1) {
mesh1.rotation.y += 0.015;
mesh2.rotation.y = mesh1.rotation.y;
mesh3.rotation.y = mesh1.rotation.y;
}
return composer.render();
};
var updateFps = function() {
elapsedTime += clock.getDelta();
frameCount++;
if (elapsedTime >= 1) {
$('#fps').html(frameCount);
frameCount = 0;
return elapsedTime = 0;
}
};
init();
animate();
This Pen doesn't use any external CSS resources.