Hello everyone,
I’ve been working on my very first Three.js scene for a while now, and I plan to keep going as I learn more.
At this point, I’d really appreciate any pro/amateur tips or critiques.
What I’ve done so far:
- I mostly used pre-made assets, but I’ve optimized them by reducing vertex counts, changing textures, and making other tweaks.
- The point particle system is completely built from scratch by me. The flame particle effect is adapted from this source, ported in GLSL2, and further improved.
- Shadows are fully dynamic with customizable options, nothing is baked, which impacts performance and requires further optimization.
- I’ve also added some post-processing effects like bloom and antialiasing (basic for now).
- The scene is Souls-like themed, originally inspired by the Three.js Journey - Haunted House scene.
- Trees, bushes, and graves are randomly generated, and their counts can be adjusted through the settings panel.
- I also created a themed UI and an some text in the style of Souls-like or Elden Ring.
About Techs:
The project is built with TypeScript, mainly for better error handling and type safety (for future sanity ).
It’s currently developed using Vite + Three.js, which really helps simplify the workflow.
The UI is made with CSS, and the dev panel is handled via lil-gui.
There’s no physics engine or else for now…
Future plans:
My first goal is to expand the scene with procedural generation, using the same meshes and models but with more variety in terrain shapes, powered by a procedural shader. I’ve already tried to limit the visible area of the scene using fog.
I’m also aiming to turn this into a playable, browser-based Souls-like game. I know there’s still a long road ahead, basic player controls and physics aren’t too difficult, but animations, enemy behavior, and especially optimization are the real challenges.
I’ve started working on performance optimization by providing different quality presets for mobile and desktop, but there’s still a lot to improve.
For example, I tried using “InstancedMesh” for trees and other randomly generated objects several times, but in my case, it actually increased draw calls instead of reducing them. I suspect that’s because frustum culling doesn’t work effectively with instanced meshes, and proper optimization in that area likely requires more advanced tweaking. That’s why I’m currently cloning each mesh and placing them randomly.
I’m open to any kind of critique, advice, or ideas. If you have time, feel free to critique the code structure, implementantions or just share your thoughts on how the scene looks from the end user’s perspective.
Thanks for reading this far!
———————————-
Update:
Reworked bonfire model, visually improved it a bit and optimized it. Fixed a bug in the random mesh spawn positioner (it was stupid mistake), and improved spawn logic, no longer clears all meshes, now spawns only the diff of random mesh counts. So count options became intensity control.
I would really appreciate any feedback on performance. So far, I’ve only tested on a Linux desktop with a gaming setup and on an Android mobile device. I’m curious how it performs on laptops with integrated gpu and on other systems.