How to achieve in Cesium that, after setting a 3D object to be transparent, it can still occlude objects behind it? Below is an example I created using Three.js, similar to the effect of colorWrite = false in Three.js. Here is my code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js Invisible Occluder Example</title>
<style>
body {
margin: 0;
background-color: blanchedalmond;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="800" height="600"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene, Camera, Renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({
canvas: myCanvas,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Geometry for the front object
var geometry1 = new THREE.SphereGeometry(1, 64, 64);
// Create a material that only writes to the depth buffer
const material1 = new THREE.MeshBasicMaterial({
colorWrite: false // Disable color writing
});
const cube1 = new THREE.Mesh(geometry1, material1);
scene.add(cube1);
// Geometry and Material for the back object
const geometry2 = new THREE.BoxGeometry(2, 2, 2);
const material2 = new THREE.MeshBasicMaterial({ color: 0x0000ff, transparent: true, opacity: 0.5 });
const cube2 = new THREE.Mesh(geometry2, material2);
cube2.position.set(1, 1, -1); // Position the back object behind the front object
scene.add(cube2);
camera.position.z = 5;
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Rotate the cubes for better visibility
cube1.rotation.x += 0.01;
cube1.rotation.y += 0.01;
cube2.rotation.x += 0.01;
cube2.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cesium Simple Geometry</title>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.88/Build/Cesium/Cesium.js"></script>
<style>
@import url("https://cesium.com/downloads/cesiumjs/releases/1.88/Build/Cesium/Widgets/widgets.css");
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background: transparent;
}
#cesiumContainer,
canvas {
position: absolute;
top: 0;
left: 0;
background: transparent;
}
body {
background-color: #4d7554;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: false, // Disable default imagery
baseLayerPicker: false, // Hide the base layer picker
terrainProvider: false, // Disable terrain
geocoder: false, // Disable geocoder
homeButton: false, // Disable home button
sceneModePicker: false, // Disable scene mode picker
navigationHelpButton: false, // Disable navigation help button
animation: false, // Disable animation widget
timeline: false, // Disable timeline widget
skyBox: false, // Disable skyBox
skyAtmosphere: false,// Disable skyAtmosphere
scene3DOnly: true,
shadows: false,
orderIndependentTranslucency: false, // 禁用顺序无关半透明
contextOptions: {
webgl: {
alpha: true, // 使WebGL上下文支持透明
// stencil: true, // 禁用模板缓冲区
// powerPreference: 'high-performance' // 设置电源偏好
}
}
// context: context,
});
// viewer.scene.backgroundColor = new Cesium.Color(255, 255, 0, 0);
viewer.scene.backgroundColor = Cesium.Color.TRANSPARENT;
// Create a custom shader to only write to the depth buffer
const customShader = new Cesium.CustomShader({
fragmentShaderText: `
void main() {
// Do nothing, just write to depth buffer
gl_FragColor = vec4(0.0);
}
`,
translucent: true
});
// Add an invisible occluding box with the custom shader
const invisibleOccluder = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 100),
box: {
dimensions: new Cesium.Cartesian3(100.0, 100.0, 100.0),
material: new Cesium.Material({
fabric: {
type: 'Color',
uniforms: {
color: new Cesium.Color(1.0, 1.0, 1.0, 0.0)
}
}
}),
shadows: Cesium.ShadowMode.DISABLED,
customShader: customShader
}
});
// Add a visible box behind the invisible occluder
const visibleBox = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.5985, 40.03883, 50),
box: {
dimensions: new Cesium.Cartesian3(50.0, 50.0, 50.0),
material: Cesium.Color.BLUE
}
});
// Set the viewer to focus on the entities
viewer.zoomTo(viewer.entities);
</script>
</body>
</html>