Skip to content

marcofugaro/webgl-iridescence-twerk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webgl-iridescence-twerk

Some cool ass iridescent effect

Built with threejs-modern-app.

Highlights

  • The iridescence effects boils down to colors mapped to the fresnel effect. I explored three ways of doing this:
  1. Use the mod() function to map the whole HSL color wheel to the fresnel value. The full code is here.
// circle the whole hue wheel,
// the function looks like this /|/|/|/|/
float f = mod(iridescence, 1.0);

vec3 iridescentColor = hsl2rgb(f, 1.0, 0.5);
  1. Alternate between two colors with a ping-pong function. The full code is here.
// alternate between two colors,
// the function looks like this /\/\/\/\/
float f = abs(1.0 - mod(iridescence, 2.0));

vec3 iridescentColor = mix(firstColor, secondColor, f);
  1. Cycle between more than two colors using weights.
float f = iridescence;

// the step values
float step1 = 0.0;
float step2 = 0.33;
float step3 = 0.66;
float step4 = 1.0;

// the step colors
vec3 firstColor = vec3(...);
vec3 secondColor = vec3(...);
vec3 thirdColor = vec3(...);
vec3 fourthColor = vec3(...); // this must be the same of the first color to prevent a harsh color change

// this is a gradient step
// first color is the front one, the last color is the perpendicular one
vec3 iridescentColor = mix(firstColor, secondColor, smoothstep(step1, step2, f));
iridescentColor = mix(iridescentColor, thirdColor, smoothstep(step2, step3, f));
iridescentColor = mix(iridescentColor, fourthColor, smoothstep(step3, step4, f));

This is similar to the ColorRamp node in Blender.

  • The normals after the vertex shader displacement in the hills were calculated using this method. Relevant code is here.
// http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts
vec3 orthogonal(vec3 v) {
  return normalize(abs(v.x) > abs(v.z) ? vec3(-v.y, v.x, 0.0)
  : vec3(0.0, -v.z, v.y));
}

// the function which defines the displacement
float frequency = 0.4;
float speed = 0.05;
float displace(vec3 point) {
  // distance from center
  float distance = hypot(point.xz);
  float amplitude = pow(distance, 2.0) * 0.05;
  return (noise(vec3(point.xz * frequency, timeFixed * speed)) * 0.5 + 0.5) * amplitude;
}

// ...

vec3 displacedPosition = position + normal * displace(position);

float offset = 0.01;
vec3 tangent = orthogonal(normal);
vec3 bitangent = normalize(cross(normal, tangent));
vec3 neighbour1 = position + tangent * offset;
vec3 neighbour2 = position + bitangent * offset;
vec3 displacedNeighbour1 = neighbour1 + normal * displace(neighbour1);
vec3 displacedNeighbour2 = neighbour2 + normal * displace(neighbour2);

// https://i.ya-webdesign.com/images/vector-normals-tangent-16.png
vec3 displacedTangent = displacedNeighbour1 - displacedPosition;
vec3 displacedBitangent = displacedNeighbour2 - displacedPosition;

// https://upload.wikimedia.org/wikipedia/commons/d/d2/Right_hand_rule_cross_product.svg
vec3 displacedNormal = normalize(cross(displacedTangent, displacedBitangent));
  • The model was downloaded from threedscans.com, I then t-posed it in Blender:
Before After

After that, I used Mixamo to attach the animation to the mesh.

Usage

Once you installed the dependencies running yarn, these are the available commands:

  • yarn start starts a server locally
  • yarn build builds the project for production, ready to be deployed from the build/ folder

All the build tools logic is in the package.json and webpack.config.js.

About

🕺 Some cool ass iridescent effect

Topics

Resources

License

Stars

Watchers

Forks

Languages