At Codrops, we love sharing inventive journeys from the net improvement group. On this article, Axel Croizé takes us by the important thing steps of constructing his first browser-based 3D sport prototype. Impressed by Bruno Simon’s playful portfolio, Axel brings his thought to life utilizing Three.js, shaders, and physics engines. Whereas the venture continues to be in progress, his story affords a captivating glimpse into how curiosity and creativity can spark interactive internet experiences.
On this article, I’ll stroll you thru the method of creating my first 3D sport prototype—from the preliminary idea to establishing the surroundings and including interactive parts. I’ll share a number of the instruments and methods I used, the challenges I confronted, and the way the venture is shaping up. Although it’s nonetheless a piece in progress, I hope this breakdown will likely be useful if you happen to’re fascinated by beginning the same venture however aren’t positive the place to start.
How the concept got here to life
Like most internet builders who uncover Bruno Simon’s portfolio for the primary time, I used to be deeply impressed by his playful and artistic method whereas staying true to the rules of internet design.

“Searching” and “visiting” a web site tackle an entire new that means in his richly immersive 3D surroundings, the place you will need to bodily navigate to discover his initiatives.
Being a novice in utilizing 3D on the net, I rapidly determined to enroll in his Three.js Journey course.
Since I didn’t but have a portfolio, I assumed it will be wonderful to create an surroundings the place customers would take pleasure in exploring and discovering my initiatives. As somebody who loves nature and animals and was impressed by video games like Journey or Zelda, the concept of embodying an animal exploring an unlimited surroundings got here to me rapidly.
Whereas I finally took a special method for my portfolio, the idea for my first sport prototype was born.
Design and Improvement Phases
By the tip of the course, I had already accomplished a number of small inventive initiatives utilizing shaders. I had found the ability of physics engines like Cannon.js or Rapier, the convenience of utilizing Three.js with React by way of React-Three-Fiber (R3F), and the invaluable helpers from Drei, a part of the pmndrs collective.
I used to be well-equipped to sort out this venture, which had been simmering in my thoughts for a while.
Arrange
I created a brand new React venture, put in the R3F and Drei libraries, and added the Rapier physics engine by way of pmndrs/react-three-rapier (sure, one other one thans to pmndrs).
I then generated a terrain by making a top map array utilizing a noise algorithm to realize a natural-looking hill reduction.

For the character, among the many free animated 3D fashions obtainable on-line for testing, I discovered a “low poly” fox that fitted completely with my venture.
Lastly, I added a Sky element, a really useful helper supplied by the Drei library.

Physics
Subsequent, I wanted to outline the context of “bodily our bodies” in order that the fox may transfer on the terrain. The fox was outlined as a cellular bodily physique topic to gravity, whereas the bottom was a static bodily physique.
<Physics
debug
gravity={[0, -9.81, 0]}
>
<Terrain foxPosition={foxPosition} />
<Fox
place={[0, 2.5, 0]}
orbitControlsRef={orbitControlsRef}
onPositionUpdate={updateFoxPosition}
/>
</Physics>

Then, I programmed directional controls for the keyboard to maneuver the fox on the terrain. I utilized a driving drive primarily based on the fox’s orientation, guaranteeing it moved coherently with its path relative to the digital camera.
Digital camera
By default, a Three.js digital camera added to the scene is static. Controls permit customers to maneuver it to view completely different angles of the scene.
For my sport, I wished the controls to imitate an journey sport: one joystick (or the arrow keys) for transferring the character and one other joystick for rotating the digital camera across the character.
const translation = foxBody.present.translation();
const targetPosition = new THREE.Vector3(
translation.x,
translation.y,
translation.z
);
orbitControlsRef.present.goal.lerp(targetPosition, 0.05);
// ...
<OrbitControls
ref={orbitControlsRef}
minDistance={1}
maxDistance={4}
maxPolarAngle={Math.PI / 2.5}
minPolarAngle={Math.PI / 2.5}
enablePan={false}
enableZoom={true}
enableDamping={true}
dampingFactor={0.05}
zoomSpeed={0.5}
rotateSpeed={0.5}
keyEvents={false}
/>
Grass
At this stage, I had a fox transferring throughout different terrain, nevertheless it was removed from a satisfying journey expertise.
To create lush hills, I wanted so as to add grass to my terrain. Luckily, I discovered a venture that completely demonstrated the impact I wished.

James supplied the code for his venture in vanilla Three.js. I remoted the grass and its oscillation logic and tailored it for React-Three-Fiber. I then utilized the grass throughout the terrain.
To maintain the code organized, I separated the terrain’s heightmap calculation from the grass creation, which consists of quite a few particular person blades. To make sure correct placement, I injected the identical heightmap knowledge into the grass logic.
<RigidBody kind="mounted" colliders={false} friction={1}>
<mesh receiveShadow ref={meshRef} materials={materials}>
<primitive object={terrainData.geometry} />
</mesh>
<HeightfieldCollider
args={[40, 40, terrainData.heights, terrainData.scale]}
restitution={0.2}
/>
<GrassField terrainData={terrainData} foxPosition={foxPosition} />
</RigidBody>
James’ venture included a passing cloud impact on the grass, which appeared nice however solely affected the grass and never the fox, detracting from realism. I eliminated it, retaining in thoughts that if I wished cloud shadows, I’d want a worldwide system with sky clouds affecting each the fox and the grass.
One other element is that the grass has its personal shade, however relying on its density, the bottom beneath may present by, creating an disagreeable distinction. To repair this, I used the identical texture for the grass shade on the terrain. By barely darkening the grass blade edges, the grass remained seen whereas mixing seamlessly with the bottom.


Upcoming Options
Now that the exploration prototype is full, these are the most important options that can go subsequent to make it an precise sport:
- Including a lore: Why is the fox there? Why are the hills so huge? Is there one thing extra?
- Exploration rewards: Putting collectible objects at varied factors within the sport linked to the lore, encouraging gamers to discover and study concerning the universe.
- Loading display
There are additionally a number of enhancements I’ve already thought of:
- Including factors of curiosity associated to the lore (a windmill, an enormous tree, a uniquely formed rock, and so forth.)
- Including a navigation device, akin to a mini-map or a compass
- Lighting enhancement
- Implementing a day/evening cycle
- Creating or buying a extra personalised fox asset
- Including stress-free background music and wind sound results
- Deciding on the sport’s conclusion
Conclusion
This bold venture would require numerous work, and I’m blissful to take my time with it.
You possibly can check out the WIP model right here. Management the fox with the WASD keys.
When you loved studying this, produce other enchancment concepts, or simply need to share your ideas, be at liberty to remark or attain out by way of my social media.
You may as well take a look at my portfolio web site, the place I’m open to suggestions and solutions.
Thanks for studying, and blissful coding!