1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource npm:hono@3/jsx */
import { Hono } from "npm:hono";
const app = new Hono();
app.get("/", async (c) => {
return c.html(`
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Teardrop Directional Fabric Warp Effect</title>
<style>
body {
margin: 0;
overflow: hidden;
background: black;
}
canvas {
width: 100%;
height: 100%
}
#debug {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: monospace;
}
</style>
</head>
<body>
<div id="debug"></div>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D tDiffuse;
uniform vec2 uClickPoint;
uniform vec2 uDragVector;
uniform vec2 uResolution;
uniform float uWarpStrength;
varying vec2 vUv;
const float MAX_DRAG_LENGTH = 120.0; // Maximum drag length
const float INTENSITY_RANGE = 500.0; // Range over which the effect intensifies
vec3 warpColor(vec2 uv) {
vec2 p = uv * uResolution;
vec2 l = uClickPoint;
vec2 v = uDragVector;
float dragLength = length(v);
// Calculate intensity factor
float intensityFactor = smoothstep(MAX_DRAG_LENGTH - INTENSITY_RANGE, MAX_DRAG_LENGTH, dragLength);
// Normalize drag vector to max length if it exceeds
vec2 normalizedV = (dragLength > MAX_DRAG_LENGTH) ? (v / dragLength) * MAX_DRAG_LENGTH : v;
// Apply intensity to normalized drag vector
vec2 effectiveV = normalizedV * (1.0 + intensityFactor);
float maxDistance = 190.0 * (length(effectiveV) / 100.0);
vec2 m = -effectiveV * pow(clamp(1.0 - length(l - p) / maxDistance, 0.0, 1.0), 2.0) * 1.2 * uWarpStrength;
vec3 c = vec3(0.0);
for (float i = 0.0; i < 10.0; i++) {
float s = 0.175 + 0.005 * i;
c.r += texture(tDiffuse, (p + s * m) / uResolution).r;
c.g += texture(tDiffuse, (p + (s + 0.025) * m) / uResolution).g;
c.b += texture(tDiffuse, (p + (s + 0.05) * m) / uResolution).b;
}
return c / 10.0;
}
void main() {
vec3 color = (length(uDragVector) > 0.0) ? warpColor(vUv) : texture(tDiffuse, vUv).rgb;
gl_FragColor = vec4(color, 1.0);
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
if (typeof THREE === 'undefined') {
console.error('THREE is not defined. Make sure Three.js is loaded correctly.');
return;
}
let scene, camera, renderer, material;
let clickPoint = new THREE.Vector2();
let currentPoint = new THREE.Vector2();
let dragVector = new THREE.Vector2();
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
July 17, 2024