Create Psychedelic jellyfish shader from single icosahedron from scratch using HTML, CSS and JavaScript.


Hello Developer, In this article I teach you how to create jellyfish psychedelic jellyfish shader from single icosahedron from scratch using HTML, CSS and JavaScript. Now let's get's started. 

HTML CODE HERE :-


<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Bihari Graphic Psychedelic Jellyfish </title>
  <link rel="stylesheet" href="./style.css">

</head>
<body>
<!-- partial:index.partial.html -->
<canvas id="canvas" />

<script type="x-shader" id="shader_vertex">
#define PI 3.1415926535897932384626433832795

const float TAU = PI * 2.0;

uniform float u_time;

varying vec3 v_mod_pos;
varying vec3 v_orig_pos;
varying float v_tail_bumps;
varying float v_head_swirl;
varying float v_head_bumps;

float get_area(float begin, float end, float value) {
  return step(begin, value) - step(end, value);
}

float get_normalized_range(float begin, float end, float value) {
  float range = end - begin;
  return value / range;
}

void main() {

  vec4 model_position = modelMatrix * vec4(position, 1.0);

  // the original position of the vertices
  vec3 orig_pos = model_position.xyz;
  // the modified position of the vertices
  vec3 mod_pos = model_position.xyz;

  // scale down bottom part
  mod_pos.xz *= 1.0 - smoothstep(0.05, -0.4, orig_pos.y) * 0.2;
  // pinch tail
  mod_pos.xz *= 1.0 - smoothstep(0.05, -1.0, orig_pos.y);
  // stretch tail
  mod_pos.y *= 1.0 + smoothstep(0.0, -1.0, orig_pos.y) * 2.0;

  // curl tail in beneath head
  float area_curled_under_head = smoothstep(0.1, 0.0, orig_pos.y) - smoothstep(-0.1, 0.0, orig_pos.y);
  float area_curled_under_head_position = clamp(get_normalized_range(0.1, -0.1, orig_pos.y), 0.0, 1.0);
  mod_pos.y += sin(area_curled_under_head_position * PI * 0.5) * area_curled_under_head * 0.5;

  float swim_speed = u_time * 2.0 + sin(u_time * 2.0 + PI) * 0.5 + snoise2(vec2(u_time * 0.02, 0.0));

  // entire swimming motion
  mod_pos.y += sin(swim_speed + mod_pos.y + PI * 0.4) * 0.15;

  // wiggly head swimming motion
  mod_pos.x += sin(swim_speed * 0.5 + mod_pos.y * 3.5) * 0.15 * clamp(orig_pos.y - 0.3, 0.0, 1.0) * smoothstep(-0.6,-0.4, orig_pos.y);
  mod_pos.z += cos(swim_speed * 0.5 + mod_pos.y * 3.7) * 0.15 * clamp(orig_pos.y - 0.3, 0.0, 1.0) * smoothstep(-0.6,-0.4, orig_pos.y);

  // head swimming motion
  float swimming_head_area = 1.0 - smoothstep(-0.2, -0.4, orig_pos.y);
  mod_pos.x *= 1.0 + sin(swim_speed + orig_pos.y) * (swimming_head_area * 0.15 + (0.1 * orig_pos.y));
  mod_pos.z *= 1.0 + sin(swim_speed + orig_pos.y) * (swimming_head_area * 0.15 + (0.1 * orig_pos.y));
  mod_pos.y *= 1.0 + sin(swim_speed + orig_pos.y + PI * 0.75) * swimming_head_area * 0.1;

  // head swirl
  float head_swirl_angle = atan(orig_pos.x, orig_pos.z);
  float head_swirl = head_swirl_angle;
  head_swirl += PI;
  head_swirl /= TAU;
  head_swirl = 0.5 + sin(head_swirl * TAU * 8.0) * 0.5;
  head_swirl *= smoothstep(1.0, 0.75, orig_pos.y) - smoothstep(0.4, 0.0, orig_pos.y);
  mod_pos *= 1.0 + 0.05 * head_swirl;
  v_head_swirl = head_swirl;

  // head bumps
  vec4 head_bumps_vector = vec4(orig_pos.xz * 8.0 * (2.0 - orig_pos.y), orig_pos.y * 4.0 + mod_pos.y * 0.25, swim_speed * 0.1);
  float head_bumps_noise = snoise4(head_bumps_vector);
  float head_bumps = abs(head_bumps_noise) * smoothstep(0.1, 0.125, orig_pos.y);
  v_head_bumps = head_bumps;
  mod_pos *= 1.0 + head_bumps * 0.025;

  // tail swimming motion
  float swimming_tail_area = smoothstep(-0.3, -1.0, orig_pos.y);
  mod_pos.y *= 1.0 + sin(swim_speed + orig_pos.y + PI) * swimming_tail_area * 0.1;

  float spin_amount = 0.5 + sin(swim_speed + orig_pos.y - PI) * 0.5;

  // spin tail
  mod_pos.x += sin(exp(orig_pos.y * 0.25) * PI * 24.0 + u_time * 4.0) * smoothstep(0.0, -1.0, orig_pos.y) * 0.3 * spin_amount;
  mod_pos.z += cos(exp(orig_pos.y * 0.25) * PI * 16.0 + u_time * 4.0) * smoothstep(0.0, -1.0, orig_pos.y) * 0.3 * spin_amount;

  float tail_noise_amount = smoothstep(0.0, -0.5, orig_pos.y);

  // make the spin more unpredictable and WaVy
  vec4 spin_noise_vector = vec4(mod_pos.xz + spin_amount, mod_pos.y + spin_amount + u_time * 0.5, u_time * 0.05);
  float spin_noise = snoise4(spin_noise_vector) * tail_noise_amount * mod_pos.y;
  mod_pos.xz *= 1.0 + spin_noise;

  // add some bumps to the tail
  vec4 tail_bump_vector = vec4(orig_pos.xz * 8.0, orig_pos.y * 2.0, u_time * 0.2);
  float tail_bump_noise = snoise4(tail_bump_vector);
  float tail_bumps = abs(tail_bump_noise * tail_noise_amount);
  mod_pos.x += sin(tail_bumps * PI) * 0.02;
  mod_pos.z += cos(tail_bumps * PI) * 0.02;

  // entire swimming motion
  mod_pos.y += sin(swim_speed + mod_pos.y + PI * 0.4) * 0.25;

  vec4 view_position = viewMatrix * vec4(mod_pos, 1.0);
  vec4 projected_position = projectionMatrix * view_position;

  gl_Position = projected_position;

  v_mod_pos = mod_pos;
  v_orig_pos = orig_pos;
  v_tail_bumps = tail_bumps;

}
</script>

<script type="x-shader" id="shader_fragment">
uniform float u_time;

varying vec3 v_mod_pos;
varying vec3 v_orig_pos;
varying float v_tail_bumps;
varying float v_head_swirl;
varying float v_head_bumps;

#define PI 3.1415926535897932384626433832795

const float TAU = PI * 2.0;

const vec3 center = vec3(0.0, 0.0, 0.0);

float get_area(float begin, float end, float value) {
  return step(begin, value) - step(end, value);
}
 
float get_normalized_range(float begin, float end, float value) {
  float range = end - begin;
  return value / range;
}

void main() {

  vec3 color = vec3(0.0, 0.0, 0.0);
  float alpha = 1.0;

  // head gradient
  float head_area = smoothstep(0.2, 0.25, v_orig_pos.y);
  float head_area_position = get_normalized_range(0.2, 1.0, v_orig_pos.y);
  float clamped_head_area_position = clamp(head_area_position, 0.0, 1.0);
  color += clamped_head_area_position;

  // threads
  // float threads_area = (
  //   smoothstep(0.1, 0.05, v_orig_pos.y) - 
  //   smoothstep(-0.05, -0.1, v_orig_pos.y)
  // );
  // float threads_area_position = get_normalized_range(-0.1, 0.1, v_orig_pos.y);
  // float clamped_threads_area_position = clamp(threads_area_position, 0.0, 1.0);
  // color += threads_area;
  
  color *= v_head_swirl * 0.75;
  color += v_head_bumps * 0.25;

  // threads
  float threads_area = smoothstep(0.15, 0.1, v_orig_pos.y) - smoothstep(0.0, -0.1, v_orig_pos.y);
  vec3 threads_vector = vec3(
    v_orig_pos.x * 16.0,
    v_orig_pos.z * 16.0,
    v_orig_pos.y
  );
  float threads_noise = (1.0 - abs(snoise3(threads_vector))) * threads_area * smoothstep(-0.1, 0.15, v_orig_pos.y);
  color += threads_noise * 0.5;

  color.b += threads_noise;
  color.g += threads_noise * sin(v_mod_pos.y) * threads_area;
  color.b += (smoothstep(0.75, 0.1, v_orig_pos.y) - smoothstep(0.1, 0.0, v_orig_pos.y)) * 0.25;

  // tail bump gradients
  float tail_bumps_area = smoothstep(0.0, -0.2, v_orig_pos.y);
  color += v_tail_bumps * 1.25 * smoothstep(-1.5, -0.5, v_mod_pos.y) * tail_bumps_area;


  // color.r += 0.2 + sin(v_orig_pos.y + u_time * 0.2) * 0.2;

  float lighten_on_top = smoothstep(-0.5, 1.5, max(0.0, v_mod_pos.y) * max(0.0, v_orig_pos.y));
  color.r += lighten_on_top * 0.8;
  color.g += lighten_on_top * 0.2;
  color.b += lighten_on_top * 0.4;

  color.r *= 1.0 + sin(smoothstep(0.5, 1.0, v_mod_pos.y) * PI) * 0.75;
  color.g *= 1.0 + sin(smoothstep(0.5, 1.0, v_mod_pos.y) * PI) * 0.25;

  color.b *= 1.0 + v_head_bumps * 2.0;
  color.g *= 1.0 + v_head_bumps * (1.65 + max(0.0, v_orig_pos.y));

  color.b += smoothstep(0.7, 0.0, distance(v_mod_pos.xz, v_orig_pos.xz)) * (v_tail_bumps + 2.0) * tail_bumps_area;
  color.g += smoothstep(0.5, 0.0, distance(v_mod_pos.xz, v_orig_pos.xz)) * (v_tail_bumps + 1.0) * tail_bumps_area;
  color.r += smoothstep(0.5, 0.0, distance(v_mod_pos.xz, v_orig_pos.xz)) * (v_tail_bumps * 4.0) * tail_bumps_area;

  color.rgb += v_mod_pos.y * 0.1 * tail_bumps_area;

  color.r += v_tail_bumps * 0.25;
  color.b += v_tail_bumps * 0.55;
  color.g += v_tail_bumps * 0.35;
  // color.b *= 1.0 + tail_bumps_area * abs(min(v_mod_pos.y, 0.0));
  // color.r -= tail_bumps_area * v_mod_pos.y * 0.5;
  // color.g *= 1.0 + tail_bumps_area * distance(v_mod_pos.xz, vec2(0.0,0.0));

  alpha = clamp(exp(color.b - 0.2), 0.0, 1.0);
  // alpha *= 1.0 - smoothstep(-0.3, -0.8, v_orig_pos.y) + tail_bumps_area * v_tail_bumps * 2.0;

  gl_FragColor = vec4(color, alpha);
}
</script>

<script type="x-shader" id="simplexNoise">
	
vec3 permute2(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }

float snoise2(vec2 v){
  const vec4 C = vec4(0.211324865405187, 0.366025403784439,
           -0.577350269189626, 0.024390243902439);
  vec2 i  = floor(v + dot(v, C.yy) );
  vec2 x0 = v -   i + dot(i, C.xx);
  vec2 i1;
  i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
  vec4 x12 = x0.xyxy + C.xxzz;
  x12.xy -= i1;
  i = mod(i, 289.0);
  vec3 p = permute2( permute2( i.y + vec3(0.0, i1.y, 1.0 ))
  + i.x + vec3(0.0, i1.x, 1.0 ));
  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy),
    dot(x12.zw,x12.zw)), 0.0);
  m = m*m ;
  m = m*m ;
  vec3 x = 2.0 * fract(p * C.www) - 1.0;
  vec3 h = abs(x) - 0.5;
  vec3 ox = floor(x + 0.5);
  vec3 a0 = x - ox;
  m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
  vec3 g;
  g.x  = a0.x  * x0.x  + h.x  * x0.y;
  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
  return 130.0 * dot(m, g);
}
	
	//	Simplex 3D Noise 
vec4 permute3(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}

float snoise3(vec3 v){ 
  const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
  const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);

// First corner
  vec3 i  = floor(v + dot(v, C.yyy) );
  vec3 x0 =   v - i + dot(i, C.xxx) ;

// Other corners
  vec3 g = step(x0.yzx, x0.xyz);
  vec3 l = 1.0 - g;
  vec3 i1 = min( g.xyz, l.zxy );
  vec3 i2 = max( g.xyz, l.zxy );

  //  x0 = x0 - 0. + 0.0 * C 
  vec3 x1 = x0 - i1 + 1.0 * C.xxx;
  vec3 x2 = x0 - i2 + 2.0 * C.xxx;
  vec3 x3 = x0 - 1. + 3.0 * C.xxx;

// Permutations
  i = mod(i, 289.0 ); 
  vec4 p = permute3( permute3( permute3( 
             i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
           + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 
           + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));

// Gradients
// ( N*N points uniformly over a square, mapped onto an octahedron.)
  float n_ = 1.0/7.0; // N=7
  vec3  ns = n_ * D.wyz - D.xzx;

  vec4 j = p - 49.0 * floor(p * ns.z *ns.z);  //  mod(p,N*N)

  vec4 x_ = floor(j * ns.z);
  vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)

  vec4 x = x_ *ns.x + ns.yyyy;
  vec4 y = y_ *ns.x + ns.yyyy;
  vec4 h = 1.0 - abs(x) - abs(y);

  vec4 b0 = vec4( x.xy, y.xy );
  vec4 b1 = vec4( x.zw, y.zw );

  vec4 s0 = floor(b0)*2.0 + 1.0;
  vec4 s1 = floor(b1)*2.0 + 1.0;
  vec4 sh = -step(h, vec4(0.0));

  vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
  vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;

  vec3 p0 = vec3(a0.xy,h.x);
  vec3 p1 = vec3(a0.zw,h.y);
  vec3 p2 = vec3(a1.xy,h.z);
  vec3 p3 = vec3(a1.zw,h.w);

//Normalise gradients
  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;

// Mix final noise value
  vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
  m = m * m;
  return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 
                                dot(p2,x2), dot(p3,x3) ) );
}
	
	//	Simplex 4D Noise 
vec4 permute4(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
float permute4(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}
vec4 taylorInvSqrt4(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
float taylorInvSqrt4(float r){return 1.79284291400159 - 0.85373472095314 * r;}

vec4 grad4(float j, vec4 ip){
  const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
  vec4 p,s;

  p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
  p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
  s = vec4(lessThan(p, vec4(0.0)));
  p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; 

  return p;
}

float snoise4(vec4 v){
  const vec2  C = vec2( 0.138196601125010504,  // (5 - sqrt(5))/20  G4
                        0.309016994374947451); // (sqrt(5) - 1)/4   F4
// First corner
  vec4 i  = floor(v + dot(v, C.yyyy) );
  vec4 x0 = v -   i + dot(i, C.xxxx);

// Other corners

// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
  vec4 i0;

  vec3 isX = step( x0.yzw, x0.xxx );
  vec3 isYZ = step( x0.zww, x0.yyz );
//  i0.x = dot( isX, vec3( 1.0 ) );
  i0.x = isX.x + isX.y + isX.z;
  i0.yzw = 1.0 - isX;

//  i0.y += dot( isYZ.xy, vec2( 1.0 ) );
  i0.y += isYZ.x + isYZ.y;
  i0.zw += 1.0 - isYZ.xy;

  i0.z += isYZ.z;
  i0.w += 1.0 - isYZ.z;

  // i0 now contains the unique values 0,1,2,3 in each channel
  vec4 i3 = clamp( i0, 0.0, 1.0 );
  vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
  vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );

  //  x0 = x0 - 0.0 + 0.0 * C 
  vec4 x1 = x0 - i1 + 1.0 * C.xxxx;
  vec4 x2 = x0 - i2 + 2.0 * C.xxxx;
  vec4 x3 = x0 - i3 + 3.0 * C.xxxx;
  vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;

// Permutations
  i = mod(i, 289.0); 
  float j0 = permute4( permute4( permute4( permute4(i.w) + i.z) + i.y) + i.x);
  vec4 j1 = permute4( permute4( permute4( permute4 (
             i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
           + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
           + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
           + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));
// Gradients
// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.

  vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;

  vec4 p0 = grad4(j0,   ip);
  vec4 p1 = grad4(j1.x, ip);
  vec4 p2 = grad4(j1.y, ip);
  vec4 p3 = grad4(j1.z, ip);
  vec4 p4 = grad4(j1.w, ip);

// Normalise gradients
  vec4 norm = taylorInvSqrt4(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;
  p4 *= taylorInvSqrt4(dot(p4,p4));

// Mix contributions from the five corners
  vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
  vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4)            ), 0.0);
  m0 = m0 * m0;
  m1 = m1 * m1;
  return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
               + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;

}

</script>
<!-- partial -->
  <script type="module" src="./script.js"></script>

</body>
</html>

CSS CODE HERE :-


html, body {
  margin: 0;
  overflow: hidden;
}

#canvas {
  display: block;
  width: 100vw;
  height: 100vh;
}

JavaScript CODE HERE :-


import * as THREE from "https://cdn.skypack.dev/three@0.133.1";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.133.1/examples/jsm/controls/OrbitControls";

const getAspectRatio = () => canvas.offsetWidth / canvas.offsetHeight;

const renderer = new THREE.WebGLRenderer({
  antialias: true,
  powerPreference: 'high-performance',
  canvas });


const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);

const camera = new THREE.PerspectiveCamera(45, getAspectRatio(), 0.01, 1000);
camera.position.set(0, -2, 8);
camera.lookAt(0, -1, 0);
scene.add(camera);

const controls = new OrbitControls(camera, canvas);

const geometry = new THREE.IcosahedronGeometry(1, 64);

const material = new THREE.ShaderMaterial({
  vertexShader: simplexNoise.textContent + shader_vertex.textContent,
  fragmentShader: simplexNoise.textContent + shader_fragment.textContent,
  uniforms: {
    u_time: { value: 0.0 } } });



const mesh = new THREE.Mesh(geometry, material);
mesh.position.y = .15;
scene.add(mesh);

const clock = new THREE.Clock();
clock.start();
const loop = () => {
  const delta = clock.getDelta();
  material.uniforms.u_time.value += delta;
  renderer.render(scene, camera);
  requestAnimationFrame(loop);
};
loop();

const update_size = () => {
  renderer.setSize(canvas.offsetWidth, canvas.offsetHeight, false);
  camera.aspect = getAspectRatio();
  camera.updateProjectionMatrix();
};

window.addEventListener('resize', update_size);

update_size();

Notes:
To get the password to download the code on Telegram join

Bihari Graphic:

BihariGraphic
Join our Telegram Channel and Discussion Group to get Daily Update's and Idea's

Comments

Popular posts from this blog

Download ATTACK MODE Shwetabh Gangwar Course For Free

What is SEO | Learn about SEO (Search Engine Optimization 2023

What is Valentine's Day? | Why Valentine's day we are celebrating