<html>
<head>
<title>My first three.js app</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
</script>
</body>
</html>
const commonVertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
const edgesVertexShader = `
varying vec2 vUv;
varying float show;
uniform sampler2D tDepth;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
float oldDepth = texture2D(tDepth, gl_Position.xy).r;
float currentDepth = gl_Position.z;
if(currentDepth <= (oldDepth + 0.0001)) {
show = 1.0;
} else {
show = 0.0;
}
// show = 1.0;
}`;
const edgesFragmentShader = `
#include <packing>
varying vec2 vUv;
varying float show;
uniform sampler2D tDepth;
uniform float cameraNear;
uniform float cameraFar;
uniform float width;
uniform float height;
void main() {
vec2 clipCoord = vec2(gl_FragCoord.x / width , gl_FragCoord.y / height);
float oldDepth = texture2D(tDepth, clipCoord).r;
float currentDepth = gl_FragCoord.z;
bool showFrag = currentDepth <= (oldDepth + 0.0001);
//if (show == 1.0) {
if (showFrag) {
gl_FragColor = vec4(1,0,0,0);
} else {
discard;
}
}
`;
const frameFragmentShader = `
#include <packing>
varying vec2 vUv;
uniform sampler2D tDiffuse;
void main() {
gl_FragColor = texture2D(tDiffuse, vUv);
}
`;
function addEdges(mesh, scene) {
if (!(mesh instanceof THREE.Mesh)) return;
const edges = new THREE.EdgesGeometry(mesh.geometry, 15);
const line = new THREE.LineSegments(edges, new THREE.ShaderMaterial({
defines: {},
uniforms: {
tDepth: { value: target.depthTexture },
cameraNear: { value: camera.near },
cameraFar: { value: camera.far },
width: { value: window.innerWidth },
height: { value: window.innerHeight }
},
vertexShader: edgesVertexShader,
fragmentShader: edgesFragmentShader
}));
scene.add(line);
}
function createFrameScene() {
window.frameCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
window.frameScene = new THREE.Scene();
const quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2));
quad.frustumCulled = false; // Avoid getting clipped
window.frameMaterial = new THREE.ShaderMaterial({
defines: {},
uniforms: {
tDiffuse: { value: target.texture }
},
vertexShader: commonVertexShader,
fragmentShader: frameFragmentShader,
});
quad.material = frameMaterial;
frameScene.add(quad);
}
function initScene(obj) {
window.scene = new THREE.Scene();
window.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
5
);
camera.position.copy(new THREE.Vector3(0.5874745675273501, 0.6554984701940583, 1.18064672475596));
camera.rotation.copy(new THREE.Euler(-0.5452435447847281, 0.43509835311327705, 0.2503109179406694));
window.edgesScene = new THREE.Scene();
obj.traverse(mesh => {
if (mesh.type !== 'Mesh') return;
addEdges(mesh, edgesScene);
});
scene.add(obj);
}
function createTargets() {
window.target = new THREE.WebGLRenderTarget(
window.innerWidth,
window.innerHeight,
{
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
stencilBuffer: false
}
);
target.depthTexture = new THREE.DepthTexture();
target.depthTexture.type = THREE.UnsignedIntType;
window.renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.autoClear = false;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
var animate = function() {
requestAnimationFrame(animate);
renderer.clearTarget(target, true, true, true);
renderer.clear(true, true, true);
renderer.render(scene, camera, target);
renderer.setRenderTarget(undefined);
// renderer.clear(true, true, true);
renderer.clearDepth();
renderer.render(edgesScene, camera);
};
function start(obj) {
createTargets();
initScene(obj);
createFrameScene();
animate();
}
var g = new THREE.BoxGeometry(1, 1, 1);
var m = new THREE.MeshBasicMaterial({color: 0xd4d400});
var mesh = new THREE.Mesh(g, m);
start(mesh)
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.