JSFiddle - React, Tailwind, and code Playground

by SQShu

HTML

<!DOCTYPE html>
<html>
<head>
  <style>
    * {
        user-select: none;
    }

    body {
        background-color: #000;
        margin: 0;
        padding: 0;
        overflow: hidden;
    }
    
    h2 {
        position: absolute;
      	margin-left: 20px;
      /*	border: 1px solid white; */
        padding-left: 16px;
        padding-right:16px;
      	padding-top: 4px;
      	padding-bottom: 4px;
      	color: black;
        background-color: rgba(255,255,255,0.47);


      }
  </style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js"></script>
</head>
<body>

      <h2>W8_GLSL_beat heart_SSQ</h2>

  <!--Reference to the works of ilithya | https://codepen.io/ilithya/pen/ExyPMLJ -->


  
<div id="container"></div>

<input id='audiofile' type='file' accept="audio/*">
<canvas id="canvas"></canvas>
<i id="loading">Upload your music...</i>

<script id="vertex" type="x-shader/x-vertex">
	void main() {    
      gl_Position = vec4(position, 1.0); 
    }
</script>

<script id="fragment" type="x-shader/x-vertex">
precision mediump float;
	
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
#define M_PI 3.14159265358979323846



void main() {

	vec2 uv = (gl_FragCoord.xy - u_resolution * 0.5) / u_resolution.yy;
    
    vec2 st = u_mouse.xy/u_resolution.xy;
    
    // Centerings 定位中心點
	uv += vec2(1.3, 1.0); 

	// Create one circle 創建一個圓 
	float circle = distance(uv, vec2(0.5)) * (abs(sin(u_time))/2.0+0.5); // radius 控制半徑
	float dm = abs(sin(u_time * M_PI));  // rate 控制跳動速率
	
    
    // Create light 創建光效
	vec3 light = vec3(0.5-tan(sin(circle*0.5+dm)), 0.5-acos(tan(circle*500.0+dm)), 0.0);
    
    
    // Mix hue&rgb 混合顏色和色相
	vec3 color1 = mix(light, vec3(8.0), 0.5-circle);   
	vec3 hue = mix(vec3(1.0, 1.0, 1.0), vec3(0.0, 0.0, 0.0), (st.y+abs(sin(u_time)))*0.5);
	vec3 color2 = mix(color1, hue, abs(uv.x-0.1));
	
    // Final shader  最後著色器渲染
	gl_FragColor = vec4(color1*color2, 0.5);
}
</script>
<script></script> ...

CSS

html, body {
  margin: 0;
  background-color: #000000;
  font-family: 'Helvatica', sans-serif;
  color: #FFFFFF;
}
canvas {
  display: block;
}
input {
  position: absolute;
  top: 20px;
  left: 40px;
}
i {
  position: absolute;
  top: 50%;
  width: 100%;
  text-align: center;
}
body.loaded i {
  display: none;
}

JavaScript

let camera, scene, renderer, clock;
let uniforms;

function init() {
  const container = document.getElementById("container");

  clock = new THREE.Clock();
  camera = new THREE.Camera();
  camera.position.z = 1;

  // 創建Three場景
  scene = new THREE.Scene();

  // 聲明幾何體
  const geometry = new THREE.BoxGeometry(2, 2, 2);

  // 數值統一化
  uniforms = {
    u_time: {
      type: "f",
      value: 1.0
    },
    u_resolution: {
      type: "v2",
      value: new THREE.Vector2()
    },
  };

  // 聲明材質,著色器材料
  const material = new THREE.ShaderMaterial({
    uniforms,
    vertexShader: document.getElementById("vertex").textContent,
    fragmentShader: document.getElementById("fragment").textContent
  });

  // 聲明網格
  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  // renderer渲染器渲染
  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);

  container.appendChild(renderer.domElement);

  onWindowResize();
  window.addEventListener("resize", onWindowResize);
}

function onWindowResize() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  uniforms.u_resolution.value.x = renderer.domElement.width;
  uniforms.u_resolution.value.y = renderer.domElement.height;
}

function render() {
  uniforms.u_time.value = clock.getElapsedTime();
  renderer.render(scene, camera);
}

function animate() {
  render();
  requestAnimationFrame(animate);
}

init();
animate();