增加一个LED shader

This commit is contained in:
kura 2025-01-09 16:18:47 +08:00
parent c96d550001
commit 5bcd94a3d0
6 changed files with 256 additions and 0 deletions

View File

@ -19,6 +19,7 @@
"ant-design-vue": "4.x", "ant-design-vue": "4.x",
"highlight.js": "^11.11.1", "highlight.js": "^11.11.1",
"peerjs": "^1.5.4", "peerjs": "^1.5.4",
"three": "^0.172.0",
"vue": "^3.3.0", "vue": "^3.3.0",
"vue-i18n": "^9.1.9", "vue-i18n": "^9.1.9",
"vue-router": "^4.5.0" "vue-router": "^4.5.0"
@ -26,6 +27,7 @@
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.6.1", "@rushstack/eslint-patch": "^1.6.1",
"@types/node": "^20.10.6", "@types/node": "^20.10.6",
"@types/three": "^0.172.0",
"@types/wicg-file-system-access": "^2023.10.5", "@types/wicg-file-system-access": "^2023.10.5",
"@vitejs/plugin-basic-ssl": "^1.2.0", "@vitejs/plugin-basic-ssl": "^1.2.0",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",

View File

@ -0,0 +1,205 @@
<template>
<div>
<video
id="video"
src="/static/test.mp4"
style="display: none"
loop
crossorigin="anonymous"
></video>
<canvas id="canvas"></canvas>
<button @click="handleClick">播放</button>
</div>
</template>
<script setup lang="ts">
import * as THREE from "three";
import { onMounted, onUnmounted } from "vue";
const handleClick = () => {
const video = document.getElementById("video") as HTMLVideoElement;
video.play();
};
//
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
onMounted(async () => {
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#canvas"),
});
renderer.setSize(window.innerWidth, window.innerHeight);
//
const video = document.getElementById("video") as HTMLVideoElement;
//
const videoTexture = new THREE.VideoTexture(video);
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
videoTexture.format = THREE.RGBFormat;
//
try {
await video.play();
} catch (err) {
console.error("视频播放失败:", err);
}
//
const geometry = new THREE.PlaneGeometry(10, 10, 200, 200);
// ShaderMaterial
const material = new THREE.ShaderMaterial({
vertexShader: `
varying vec2 vUv;
varying float vDist;
varying float vRandom;
uniform vec2 mouse;
uniform float radius;
uniform float time;
uniform float drag;
//
float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void main() {
vUv = uv;
vec3 pos = position;
//
float rand = random(pos.xy) * 2.0 - 1.0;
vRandom = rand;
//
float disperseFactor = sin(time * 0.5) * 0.00001;
vec3 disperseDir = vec3(
rand * disperseFactor,
rand * disperseFactor,
0
);
//
vec2 mouseDir = pos.xy - mouse;
float dist = length(mouseDir);
if (dist < radius) {
float force = (radius - dist) / radius;
pos.xy += normalize(mouseDir) * force * 0.5;
}
//
pos += disperseDir;
//
gl_PointSize = 3.0 * (1.0 + random(pos.xy));
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
gl_Position = projectionMatrix * mvPosition;
vDist = dist;
}`,
fragmentShader: `
uniform sampler2D mainTexture;
varying vec2 vUv;
varying float vDist;
varying float vRandom;
uniform float time;
void main() {
//
float mosaicSize = 1000.0;
vec2 mosaicUv = floor(vUv * mosaicSize) / mosaicSize;
//
float jitter = sin(time * 2.0 + vRandom * 6.28) * 0.000001;
mosaicUv += vec2(jitter);
vec4 texColor = texture2D(mainTexture, mosaicUv);
//
float distortionFactor = 1.0 - vDist * 0.05;
float alpha = 0.9 + 0.1 * sin(time * 2.0 + vRandom * 6.28);
//
float edgeFade = 1.0 - length(gl_PointCoord - vec2(0.5)) * 2.0;
edgeFade = smoothstep(0.0, 0.5, edgeFade);
gl_FragColor = vec4(texColor.rgb * distortionFactor, texColor.a * alpha * edgeFade);
}`,
uniforms: {
mainTexture: { value: videoTexture },
mouse: { value: new THREE.Vector2(0, 0) },
radius: { value: 0.5 },
time: { value: 0 },
drag: { value: 0.98 },
},
transparent: true,
side: THREE.DoubleSide,
depthWrite: false,
blending: THREE.AdditiveBlending,
});
//
const points = new THREE.Points(geometry, material);
scene.add(points);
//
const mouse = new THREE.Vector2();
const rect = renderer.domElement.getBoundingClientRect();
document.addEventListener("mousemove", (event) => {
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
material.uniforms.mouse.value.set(mouse.x * 5, mouse.y * 5);
});
//
function animate() {
requestAnimationFrame(animate);
if (video.readyState === video.HAVE_ENOUGH_DATA) {
videoTexture.needsUpdate = true;
}
material.uniforms.time.value += 0.016;
renderer.render(scene, camera);
}
animate();
//
window.addEventListener("resize", () => {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
});
});
//
onUnmounted(() => {
const video = document.getElementById("video") as HTMLVideoElement;
video.pause();
video.src = "";
video.load();
});
</script>
<style scoped>
canvas {
width: 100vw;
height: 100vh;
display: block;
}
</style>

View File

@ -1,11 +1,13 @@
import { createRouter, createWebHashHistory } from "vue-router"; import { createRouter, createWebHashHistory } from "vue-router";
import Index from "../pages/file/index.vue"; import Index from "../pages/file/index.vue";
import Voice from "../pages/voice/webrtcVoice.vue"; import Voice from "../pages/voice/webrtcVoice.vue";
import PointShader from "../pages/pointShader/pointShader.vue";
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
routes: [ routes: [
{ path: "/", component: Index }, { path: "/", component: Index },
{ path: "/voice", component: Voice }, { path: "/voice", component: Voice },
{ path: "/pointShader", component: PointShader },
], ],
}); });

BIN
static/jl.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
static/test.mp4 Normal file

Binary file not shown.

View File

@ -394,6 +394,11 @@
core-js "^3.15.1" core-js "^3.15.1"
nanopop "^2.1.0" nanopop "^2.1.0"
"@tweenjs/tween.js@~23.1.3":
version "23.1.3"
resolved "https://registry.npmmirror.com/@tweenjs/tween.js/-/tween.js-23.1.3.tgz#eff0245735c04a928bb19c026b58c2a56460539d"
integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==
"@types/json-schema@^7.0.12": "@types/json-schema@^7.0.12":
version "7.0.15" version "7.0.15"
resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
@ -411,6 +416,28 @@
resolved "https://registry.npmmirror.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" resolved "https://registry.npmmirror.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
"@types/stats.js@*":
version "0.17.3"
resolved "https://registry.npmmirror.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935"
integrity sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==
"@types/three@^0.172.0":
version "0.172.0"
resolved "https://registry.npmmirror.com/@types/three/-/three-0.172.0.tgz#5094852dfa781d2fe1c65eb1b4985a4aa99858b7"
integrity sha512-LrUtP3FEG26Zg5WiF0nbg8VoXiKokBLTcqM2iLvM9vzcfEiYmmBAPGdBgV0OYx9fvWlY3R/3ERTZcD9X5sc0NA==
dependencies:
"@tweenjs/tween.js" "~23.1.3"
"@types/stats.js" "*"
"@types/webxr" "*"
"@webgpu/types" "*"
fflate "~0.8.2"
meshoptimizer "~0.18.1"
"@types/webxr@*":
version "0.5.20"
resolved "https://registry.npmmirror.com/@types/webxr/-/webxr-0.5.20.tgz#b16b681af314ec011b2e8221b0a072d691c04953"
integrity sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==
"@types/wicg-file-system-access@^2023.10.5": "@types/wicg-file-system-access@^2023.10.5":
version "2023.10.5" version "2023.10.5"
resolved "https://registry.npmmirror.com/@types/wicg-file-system-access/-/wicg-file-system-access-2023.10.5.tgz#14b3c25eb4d914b5734795bdea71da229f918b9d" resolved "https://registry.npmmirror.com/@types/wicg-file-system-access/-/wicg-file-system-access-2023.10.5.tgz#14b3c25eb4d914b5734795bdea71da229f918b9d"
@ -661,6 +688,11 @@
resolved "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.1.3.tgz#4a61dbd29783d01ddab504276dcf0c2b6988654f" resolved "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.1.3.tgz#4a61dbd29783d01ddab504276dcf0c2b6988654f"
integrity sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg== integrity sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==
"@webgpu/types@*":
version "0.1.52"
resolved "https://registry.npmmirror.com/@webgpu/types/-/types-0.1.52.tgz#239995418d86de927269aca54cbadfbee04eb03a"
integrity sha512-eI883Nlag2hGIkhXxAnq8s4APpqXWuPL3Gbn2ghiU12UjLvfCbVqHK4XfXl3eLRTatqcMmeK7jws7IwWsGfbzw==
acorn-jsx@^5.3.2: acorn-jsx@^5.3.2:
version "5.3.2" version "5.3.2"
resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
@ -1175,6 +1207,11 @@ fastq@^1.6.0:
dependencies: dependencies:
reusify "^1.0.4" reusify "^1.0.4"
fflate@~0.8.2:
version "0.8.2"
resolved "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea"
integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
file-entry-cache@^6.0.1: file-entry-cache@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@ -1542,6 +1579,11 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
meshoptimizer@~0.18.1:
version "0.18.1"
resolved "https://registry.npmmirror.com/meshoptimizer/-/meshoptimizer-0.18.1.tgz#cdb90907f30a7b5b1190facd3b7ee6b7087797d8"
integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==
micromatch@^4.0.4, micromatch@^4.0.5, micromatch@~4.0.8: micromatch@^4.0.4, micromatch@^4.0.5, micromatch@~4.0.8:
version "4.0.8" version "4.0.8"
resolved "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" resolved "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
@ -2012,6 +2054,11 @@ text-table@^0.2.0:
resolved "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" resolved "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
three@^0.172.0:
version "0.172.0"
resolved "https://registry.npmmirror.com/three/-/three-0.172.0.tgz#6944a72f8439e8f7e4b034c8539ec82f5ebe0082"
integrity sha512-6HMgMlzU97MsV7D/tY8Va38b83kz8YJX+BefKjspMNAv0Vx6dxMogHOrnRl/sbMIs3BPUKijPqDqJ/+UwJbIow==
throttle-debounce@^5.0.0: throttle-debounce@^5.0.0:
version "5.0.2" version "5.0.2"
resolved "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.2.tgz#ec5549d84e053f043c9fd0f2a6dd892ff84456b1" resolved "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.2.tgz#ec5549d84e053f043c9fd0f2a6dd892ff84456b1"