Recreating the Round City of Baghdad in the Browser
I’ve been working on a web-based recreation of 8th-century Baghdad—the famous "Round City."
My goal was to create a procedural, interactive environment that captures the scale of the Golden Age of Islam while keeping it performant enough to run in a browser.
⚙️ The Technical Challenge: Instanced Rendering
To populate the city with 4,000 unique-looking buildings without tanking the frame rate, I used InstancedMesh.
Instead of the GPU drawing 4,000 separate objects (which would mean 4,000 draw calls), it treats them as a single group. By using a "dummy" object to calculate positions, scales, and rotations, I can generate a massive city in milliseconds.
JavaScript Example
// Quick look at the logic
const cityBody = new THREE.InstancedMesh(geometry, material, 4000);
for (let i = 0; i < 4000; i++) {
const r = 250 + Math.random() * 800; // Radius logic
const a = Math.random() * Math.PI * 2; // Angle logic
dummy.position.set(Math.cos(a) * r, 0, Math.sin(a) * r);
dummy.updateMatrix();
cityBody.setMatrixAt(i, dummy.matrix);
}
🛡️ Fighting the "Z-Fighting"
One of the biggest headaches in 3D web dev is Z-fighting—that annoying flickering when two surfaces overlap.
I solved this by:
- Using a
logarithmicDepthBufferin the renderer - Giving the "lake" a physical thickness of
0.2instead of using a flat plane - Applying a tiny
0.05Y-offset to ensure the water sits just above the ground
📖 Narrative Interaction
A city is more than just boxes.
I added a narrative layer where clicking on a building pulls from a procedural array of residents—from Master Astrolabe Makers to Greek Translators.
It turns a technical demo into a living chronicle.
🌱 What’s Next?
I’m looking to add:
- More procedural greenery (palm trees)
- Basic AI for boats in the river
🔗 Links
- Source Code: https://github.com/bingkahu/build-a-city/tree/main#-baghdad-the-great-round-city
- Live Demo: https://bingkahu.github.io/build-a-city/
💡 Final Thoughts
Instanced rendering made this project possible, but I’m always looking for ways to push it further.
I’d love to hear your thoughts on how to optimize instanced meshes even further!
Top comments (0)