I am working on a web game and using three.js to do the 3d of the game. I am building a city and I want the buildings to look exactly like the picture below.
I want them to be a base material, without textures or colors because I will add colors later depending on the building status (like the game below).
This is what I have right now:
As you can see, I just have a bunch of different-sized boxes, with no details at all. How would I achieve the details seen in the game?
This is my current code:
export default function Map() {
const RenderBuildings = () => {
const buildings = []
for (let i = 0; i < 10; i++) {
buildings.push(<Box color="#dad3cb" width={1} height={1} depth={1} />)
}
return buildings
}
return (
<Canvas>
<CameraController />
<ambientLight intensity={1} />
<Ground color="#b0aa9d" width={40} height={1} depth={40} />
{RenderBuildings()}
</Canvas>
)
}
export const Box = (props: Props) => {
const { color, width, height, depth, ...rest } = props
const mesh = useRef<THREE.Mesh>()
const boxRef = useRef<THREE.Mesh>()
useEffect(() => {
if (!mesh.current) return
const _mesh = mesh.current
_mesh.position.x = Math.floor(Math.random() * 20)
_mesh.position.z = Math.floor(Math.random() * 20)
_mesh.scale.x =
Math.random() * Math.random() * Math.random() * Math.random() * 5 + 3
_mesh.scale.z = _mesh.scale.x
_mesh.scale.y =
Math.random() * Math.random() * Math.random() * _mesh.scale.x * 5 + 3
}, [mesh])
useEffect(() => {
if (!boxRef.current) return
const _boxRef = boxRef.current
_boxRef.applyMatrix4(new Matrix4().makeTranslation(0, 0.5, 0))
}, [boxRef])
return (
<mesh {...rest} ref={mesh}>
<boxGeometry args={[width, height, depth]} ref={boxRef} />
<meshToonMaterial color={color} />
</mesh>
)
}
Your first step should be to look at lighting your scene. This will allow for better depth to your buildings. A hemisphere light may be your best bet: https://threejs.org/examples/#webgl_lights_hemisphere. You can learn more about lights here: https://threejs.org/manual/#en/lights.
Next, take a look at geometry. You want those buildings to have some level of detail at the geometry level. You can use primitives like these: https://threejs.org/manual/#en/primitives or build a model in any modelling software and import it in. At that point, maybe make a few models and then instance them randomly.
Depending on how you do geometry, you will need to pick an appropriate material: https://threejs.org/manual/#en/materials. This should give you plenty of options.
I would also add in a bit of animation to keep things lively: https://threejs.org/examples/#webgl_animation_keyframes
Finally, a bit of fog always helps for ambiance: https://threejs.org/manual/#en/fog
Some more inspiration: https://demos.littleworkshop.fr/infinitown
Ultimately, building a scene like this is going to be a labour of love. There are no easy shortcuts. Keep at it!