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();