Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/marcofugaro/webgl-iridescence-twerk
🕺 Some cool ass iridescent effect
https://github.com/marcofugaro/webgl-iridescence-twerk
shaders threejs webgl
Last synced: 4 months ago
JSON representation
🕺 Some cool ass iridescent effect
- Host: GitHub
- URL: https://github.com/marcofugaro/webgl-iridescence-twerk
- Owner: marcofugaro
- License: mit
- Created: 2019-10-15T12:50:31.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-12-26T10:39:39.000Z (about 2 years ago)
- Last Synced: 2024-10-16T23:56:32.004Z (4 months ago)
- Topics: shaders, threejs, webgl
- Language: JavaScript
- Homepage: https://iridescent-twerk.com/
- Size: 17.1 MB
- Stars: 46
- Watchers: 3
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# webgl-iridescence-twerk
> Some cool ass iridescent effect
![](.github/screenshots/demo.png)
Built with [threejs-modern-app](https://github.com/marcofugaro/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](https://github.com/marcofugaro/webgl-iridescence-twerk/blob/4c962a58a11be75c9b2b34478c4ddd73ab672fe2/src/scene/Ephebe.js#L80-L91).
```c
// circle the whole hue wheel,
// the function looks like this /|/|/|/|/
float f = mod(iridescence, 1.0);vec3 iridescentColor = hsl2rgb(f, 1.0, 0.5);
```2. Alternate between two colors with a [ping-pong](https://docs.unity3d.com/ScriptReference/Mathf.PingPong.html) function. [The full code is here](https://github.com/marcofugaro/webgl-iridescence-twerk/blob/4c962a58a11be75c9b2b34478c4ddd73ab672fe2/src/scene/Hills.js#L126-L138).
```c
// alternate between two colors,
// the function looks like this /\/\/\/\/
float f = abs(1.0 - mod(iridescence, 2.0));vec3 iridescentColor = mix(firstColor, secondColor, f);
```3. Cycle between more than two colors using weights.
```c
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](https://discourse.threejs.org/t/calculating-vertex-normals-after-displacement-in-the-vertex-shader/16989). Relevant code is [here](https://github.com/marcofugaro/webgl-iridescence-twerk/blob/4c962a58a11be75c9b2b34478c4ddd73ab672fe2/src/scene/Hills.js#L66-L100).
```c
// 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](http://threedscans.com/museo-archeologico-nazionale/efebo/), I then t-posed it in Blender:
| Before | After |
| -------------------------------------------------- | -------------------------------------------------------- |
||
|
After that, I used [Mixamo](https://www.mixamo.com/) 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/` folderAll the build tools logic is in the `package.json` and `webpack.config.js`.
### [Read the full documentation for a more in-depth guide](https://github.com/marcofugaro/threejs-modern-app)