An exploration of an built with three.js.

landscape_featured  - landscape featured - Interactive Animated Landscape | Codrops

Today we are going to explore a playful animated landscape with a psychedelic look. The idea is to show how an experimentation on art and design with a generative process can lead to interesting interactive visuals which can be used in a variety of mediums like , print, illustration, VJing, installations, games and many others. We made 3 variants of the landscape to show you how small changes in parameters can change a lot in visuals.

The demos are made with three.js and the animations and colors are controlled in a custom GLSL shader. For the letter animations we are using TweenMax.

The cool thing about doing this with WebGL is that it’s widely supported and with GLSL shaders we can animate thousands, even millions of vertices at 60 FPS on the major desktop and mobile web browsers.

If you’re not familiar with three.js and GLSL shaders, you can start by creating a scene and reading this introduction to Shaders.

Let’s go through the main build up of the demo.

Breaking down the demo

1. Creating terrain with a plane

Let’s make a basic three.js scene, place a plane with a nice amount of vertices, rotate it 90 degrees is the x-axis, and lift the camera a little bit:

interactive_landscape1_plane  - interactive landscape1 plane - Interactive Animated Landscape | Codrops

Create custom vertex and fragment shaders and bind them to a ShaderMaterial. The objective is to displace vertices up in the vertex shader with a perlin noise and multiply it with a height value:

// pseudo-code for noise implementation

vec3 coord = vec3(uv, 1.0)*10.0;
float noise = 1 + pnoise( vec3( coord.x, coord.y + time, coord.z ));

float height = h * noise;

// we apply height to z because the plane is rotated on x-axis
vec4 pos = vec4( position.x, position.y, height, 1.0 );

// output the final position
gl_Position = projectionMatrix * modelViewMatrix * pos;

interactive_landscape2_terrain  - interactive landscape2 terrain - Interactive Animated Landscape | Codrops

2. Create a road with some math

Now we’ll use a little bit of math. We’ll implement the formula below, where x is the vertex x-coordinate, h is the maximum height of terrain, c is the center of road and w is the width of road:

interactive_lanscape_formula  - interactive lanscape formula - Interactive Animated Landscape | Codrops

Playing with those variables, we can get different results, as we can see in the graphs:

interactive_lanscape_graph_h  - interactive lanscape graph h - Interactive Animated Landscape | Codrops

interactive_lanscape_graph_c  - interactive lanscape graph c - Interactive Animated Landscape | Codrops

interactive_lanscape_graph_w  - interactive lanscape graph w - Interactive Animated Landscape | Codrops

Now, applied in vertex-shader code, multiplied by the previously calculated noise it looks as follows:

// pseudo-code for formula implementation
float height = h * pow( abs( cos( uv.x + c ) ), w ) * noise;

// we apply height to z because the plane is rotated on x-axis
vec4 pos = vec4( position.x, position.y, height, 1.0 );

// output the final position
gl_Position = projectionMatrix * modelViewMatrix * pos;

interactive_landscape1_road  - interactive landscape1 road - Interactive Animated Landscape | Codrops

To make a curved road, we use uv.y as angle and take the sin of it to oscillate the center along the y-axis (the plane is rotated on the x-axis, remember?).

interactive_landscape3_road_curve  - interactive landscape3 road curve - Interactive Animated Landscape | Codrops

3. Adding color layers

Let’s colorize the terrain with a nice trick. First, create a color pallete image like this one:

interactive_landscape_pallete1  - interactive landscape pallete1 - Interactive Animated Landscape | Codrops

And then we’ll use it as a lookup texture in the fragment shader, getting the color value from the height calculated in the vertex shader as texture uv.y coordinate:

// pseudo-code for getting the color
vec2 coord = vec2( 0.0, normalize( height ) );
vec4 color = texture2D( palleteTexture, coord );

gl_FragColor = color

interactive_landscape4_colors_layers  - interactive landscape4 colors layers - Interactive Animated Landscape | Codrops

4. Having fun adding interactivity

Now we’ve done the heaviest part, it’s easy to use mouse, touch or whatever input you want, to control the formula’s variables and get interesting forms of interactivity:

// JS pseudo-code in the render loop for uniforms manipulation with mouse
terrain.material.uniforms.c.value = (mouseX / window.innerWidth - 0.5) * 0.1;
terrain.material.uniforms.w.value = (mouseY / window.innerHeight - 0.5) * 4;

5. Final touches

Let’s adjust the camera position, add a nice color pallete, fog, a sky background, and we are done!

interactive_landscape1_final  - interactive landscape1 final - Interactive Animated Landscape | Codrops

We hope you enjoy this walk-through and find the experiment inspirational!

References and Credits


Source link


Please enter your comment!
Please enter your name here