ShadowEditor/web/test/StencilTest.html
2020-05-01 09:07:57 +08:00

160 lines
4.7 KiB
HTML

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>StencilTest</title>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 控制器
new THREE.OrbitControls(camera, renderer.domElement);
// 光源
var amlight = new THREE.AmbientLight(0xffffff, 0.4);
var dirlight = new THREE.DirectionalLight(0xffffff, 0.6);
dirlight.position.set(1, 2, 3);
scene.add(amlight);
scene.add(dirlight);
// 模型1
var mesh1 = null;
var loader = new THREE.JSONLoader();
loader.load('AMY.json', geometry => {
var material = new THREE.MeshPhongMaterial({ color: 0xffff00 });
mesh1 = new THREE.Mesh(geometry, material);
scene.add(mesh1);
});
// 模型2
var mesh2 = null;
loader.load('ATWO.json', geometry => {
var material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
mesh2 = new THREE.Mesh(geometry, material);
mesh2.rotation.x = Math.PI / 2;
scene.add(mesh2);
});
camera.position.z = 500;
renderer.autoClear = false;
// 线框
var wireframeMaterial = new THREE.MeshBasicMaterial({
wireframe: true
});
var context = renderer.getContext();
var state = renderer.state;
// three.js有bug
state.buffers.stencil.setTest = function () {
};
var animate = function () {
requestAnimationFrame(animate);
if (!mesh1 || !mesh2) {
return;
}
renderer.clear();
// 绘制模板
state.enable(context.STENCIL_TEST);
state.buffers.stencil.setTest(true);
state.buffers.stencil.setClear(0x00);
state.buffers.color.setMask(false);
state.buffers.depth.setMask(false);
state.buffers.stencil.setMask(0xff);
state.buffers.color.setLocked(true);
state.buffers.depth.setLocked(true);
state.buffers.stencil.setLocked(true);
state.buffers.stencil.setOp(context.REPLACE, context.REPLACE, context.REPLACE);
scene.remove(mesh1);
scene.remove(mesh2);
scene.add(mesh1);
state.buffers.stencil.setLocked(false);
state.buffers.stencil.setMask(0b1);
state.buffers.stencil.setLocked(true);
state.buffers.stencil.setFunc(context.ALWAYS, 0b1, 0b1);
renderer.render(scene, camera);
scene.remove(mesh1);
scene.remove(mesh2);
scene.add(mesh2);
state.buffers.stencil.setLocked(false);
state.buffers.stencil.setMask(0b10);
state.buffers.stencil.setLocked(true);
state.buffers.stencil.setFunc(context.ALWAYS, 0b10, 0b10);
renderer.render(scene, camera);
scene.remove(mesh1);
scene.remove(mesh2);
scene.add(mesh1);
scene.add(mesh2);
// 绘制相交物体
state.buffers.color.setLocked(false);
state.buffers.depth.setLocked(false);
state.buffers.stencil.setLocked(false);
state.buffers.color.setMask(true);
state.buffers.depth.setMask(true);
state.buffers.stencil.setMask(0xff);
state.buffers.stencil.setLocked(true);
state.buffers.stencil.setOp(context.KEEP, context.KEEP, context.KEEP);
state.buffers.stencil.setFunc(context.EQUAL, 3, 0b11);
renderer.render(scene, camera);
// 绘制线框
state.buffers.stencil.setFunc(context.NOTEQUAL, 3, 0b11);
scene.overrideMaterial = wireframeMaterial;
renderer.render(scene, camera);
scene.overrideMaterial = null;
// 还原初始状态
state.buffers.stencil.setLocked(false);
state.disable(context.STENCIL_TEST);
};
animate();
</script>
</body>
</html>