Ocean School — Technical Case Study

Image for post
Image for post

Introduction

1. Building the platform

Image for post
Image for post
Background with WebGL enabled
Image for post
Image for post
Background with WebGL disabled

2. Crafting the worlds of Ocean School

Image for post
Image for post
Heightmap and diffuse textures used to generate terrains
Image for post
Image for post
Trees map used to generate vegetations
//offset attribute for each instance
attribute vec3 aOffset;
...vec3 transformed = position;// offset the wind movement for each instance of flag
float offset = aOffset.x * aOffset.z;
// increase intensity according to distance from the poll
float yIntensity = uv.x * 0.1;
float zIntensity = uv.x * 0.4;
// compute noise values on y and z axis
float ny = noise2d(position.xy + time + offset) * yIntensity;
float nz = noise2d(position.xz + time * 1.5 + offset) * zIntensity;
// apply wind to position
vec3 wind = vec3(ny, ny, nz);
transformed += wind;
// offset attribute for each instance
attribute vec3 aOffset;
...vec3 transformed = position;// offset the floating movement for each instance of buoy
float floatingOffset = aOffset.x * aOffset.z;
// apply a sinus function on y axis to create floating movement
transformed.y += sin(time * 2. + floatingOffset) * 0.1;
Image for post
Image for post
4 clouds textures merged in a single one
attribute float aTextureIndex; // either 0, 1, 2, 3...// compute uv offset from texture attribute
float tx = 0.5 * mod(aTextureIndex, 2.);
float ty = 0.5 * step(2., aTextureIndex);
vUv = vec2(uv.x * 0.5 + tx, uv.y * 0.5 + ty);
Image for post
Image for post
Final worlds

3. Going deeper underwater

Image for post
Image for post
Different stages of field growth in a single texture
Image for post
Image for post
uniform float maxZ; // maximum z position on the model
uniform float minZ; // minimum z position on the model
...// compute total length of the model
float lengthZ = abs(minZ) + maxZ; // total z length of the model
// compute a value going from 0 (the head) to 1 (the tail)
float progressZ = ( position.z + abs(minZ) ) / lengthZ) * 0.5;
// compute a rotation around the head
float headRotation = sin(aTime) * 0.02;
transformed.x += headRotation * progressZ;
// compute a rotation around y axis on center of the model
float yawPivotAngle = sin(aTime) * 0.1;
float yawPivot = rotationMatrix(vec3(0., 1., 0.), angle);
transformed = ( yawPivot * vec4(transformed, 1.)).xyz;
// compute sin along y to create a spine rotation
float spineAmp = 0.08 * abs(position.z);
float spineRoll = sin(position.y * 50. + aTime) * spineAmp;
transformed.x += spineRoll * progressZ;
// compute sin along z to create the tail yaw rotation
float tailYawAmp = 0.05;
float tailYaw = sin(progressZ * PI + PI * 0.5 + aTime) * tailYawAmp;
transformed.x += tailYaw * progressZ;
// compute instance scale
transformed *= scale;
// compute instance rotation
transformed = applyQuaternionToVector(aOrientation, transformed);
// compute instance offset
transformed += aOffset;
let rotation = new THREE.Matrix4();
let orientation = new THREE.Quaternion();
let velocity = new THREE.Vector3();
let timeElapsed = 0;
// get a random value between 200ms and 800ms
let delta = getDelta();
// get a random acceleration on x, y, z axis
let acceleration = getAcceleration();
function onUpdate(deltaTime) {
const prevPos = position;
// compute movement
acceleration.divideScalar(deceleration);
velocity.add(acceleration);
position.add(velocity);
// compute rotation so the fish looks at its new direction
rotation.lookAt(position, prevPos, new THREE.Vector3(0, 1, 0));
orientation.setFromRotationMatrix(rotation);
timeElapsed += deltaTime; if ( timeElapsed > delta ) {
delta = getDelta();
acceleration = getAcceleration();
velocity = new THREE.Vector3();

timeElapsed = 0;
}
}
Image for post
Image for post
Underwater world

Conclusion

Studio de design et d'expériences interactives. Design and interactive experience studio.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store