diff --git a/video-gen-app/package-lock.json b/video-gen-app/package-lock.json index 00f0f35a..8321576b 100644 --- a/video-gen-app/package-lock.json +++ b/video-gen-app/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@ant-design/icons": "^6.2.5", + "@types/three": "^0.184.1", "antd": "^6.3.7", "dayjs": "^1.11.20", "plyr-react": "^6.0.0", @@ -16,6 +17,7 @@ "react": "^19.2.5", "react-dom": "^19.2.5", "react-router-dom": "^7.15.0", + "three": "^0.184.0", "uuid": "^14.0.0", "zustand": "^5.0.13" }, @@ -392,6 +394,12 @@ "node": ">=6.9.0" } }, + "node_modules/@dimforge/rapier3d-compat": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", + "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", + "license": "Apache-2.0" + }, "node_modules/@emnapi/core": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", @@ -1726,6 +1734,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", @@ -1788,6 +1802,32 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/stats.js": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.184.1", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.184.1.tgz", + "integrity": "sha512-6q4VdiqVsrTRqmk62/BnlcAvIrnDM0zf2ZDVKI5kZiniWrSaOHaQzmbp+BNzoggc/8tgW412pL//wZIxu2PPTA==", + "license": "MIT", + "dependencies": { + "@dimforge/rapier3d-compat": "~0.12.0", + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": ">=0.5.17", + "fflate": "~0.8.2", + "meshoptimizer": "~1.1.1" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.59.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.2.tgz", @@ -2858,6 +2898,12 @@ } } }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -3543,6 +3589,12 @@ "node": ">= 8" } }, + "node_modules/meshoptimizer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz", + "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==", + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -4424,6 +4476,12 @@ "node": ">=0.8" } }, + "node_modules/three": { + "version": "0.184.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.184.0.tgz", + "integrity": "sha512-wtTRjG92pM5eUg/KuUnHsqSAlPM296brTOcLgMRqEeylYTh/CdtvKUvCyyCQTzFuStieWxvZb8mVTMvdPyUpxg==", + "license": "MIT" + }, "node_modules/throttle-debounce": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", diff --git a/video-gen-app/package.json b/video-gen-app/package.json index dfba62c1..6acb5e87 100644 --- a/video-gen-app/package.json +++ b/video-gen-app/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@ant-design/icons": "^6.2.5", + "@types/three": "^0.184.1", "antd": "^6.3.7", "dayjs": "^1.11.20", "plyr-react": "^6.0.0", @@ -18,6 +19,7 @@ "react": "^19.2.5", "react-dom": "^19.2.5", "react-router-dom": "^7.15.0", + "three": "^0.184.0", "uuid": "^14.0.0", "zustand": "^5.0.13" }, diff --git a/write-file.js b/write-file.js new file mode 100644 index 00000000..eb672247 --- /dev/null +++ b/write-file.js @@ -0,0 +1,170 @@ +const fs = require('fs'); +const content = `import { useEffect, useRef } from 'react'; +import * as THREE from 'three'; + +const GalaxyBackground = () => { + const containerRef = useRef(null); + const animationIdRef = useRef(0); + + useEffect(() => { + if (!containerRef.current) return; + + const width = containerRef.current.clientWidth; + const height = containerRef.current.clientHeight; + + const scene = new THREE.Scene(); + + const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000); + camera.position.z = 50; + + const canvas = containerRef.current.querySelector('canvas'); + if (!canvas) return; + + const renderer = new THREE.WebGLRenderer({ + canvas: canvas, + antialias: true, + alpha: true, + }); + renderer.setSize(width, height); + renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); + + const particleCount = 5000; + const positions = new Float32Array(particleCount * 3); + const colors = new Float32Array(particleCount * 3); + const sizes = new Float32Array(particleCount); + const phases = new Float32Array(particleCount); + + const color1 = new THREE.Color(0x6366f1); + const color2 = new THREE.Color(0x8b5cf6); + const color3 = new THREE.Color(0xec4899); + + for (let i = 0; i < particleCount; i++) { + const i3 = i * 3; + + const radius = 2 + Math.random() * 25; + const theta = Math.random() * Math.PI * 2; + const phi = Math.acos(2 * Math.random() - 1); + + positions[i3] = radius * Math.sin(phi) * Math.cos(theta); + positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta); + positions[i3 + 2] = radius * Math.cos(phi); + + const colorMix = Math.random(); + let color; + if (colorMix < 0.33) { + color = color1; + } else if (colorMix < 0.66) { + color = color2; + } else { + color = color3; + } + + colors[i3] = color.r; + colors[i3 + 1] = color.g; + colors[i3 + 2] = color.b; + + sizes[i] = 0.02 + Math.random() * 0.08; + phases[i] = Math.random() * Math.PI * 2; + } + + const geometry = new THREE.BufferGeometry(); + geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); + geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1)); + geometry.setAttribute('phase', new THREE.BufferAttribute(phases, 1)); + + const shaderMaterial = new THREE.ShaderMaterial({ + uniforms: { + uTime: { value: 0 }, + uPixelRatio: { value: renderer.getPixelRatio() }, + uSize: { value: 40 }, + }, + vertexShader: "attribute float size; attribute float phase; varying vec3 vColor; uniform float uTime; uniform float uPixelRatio; uniform float uSize; void main() { vColor = color; float spiralOffset = phase + uTime * 0.1; float spiralRadius = length(position.xy) * 0.02; float x = position.x + cos(spiralOffset) * spiralRadius; float y = position.y + sin(spiralOffset) * spiralRadius; float z = position.z + sin(uTime * 0.05 + phase) * 0.5; vec4 mvPosition = modelViewMatrix * vec4(x, y, z, 1.0); gl_PointSize = size * uSize * (300.0 / -mvPosition.z) * uPixelRatio; gl_Position = projectionMatrix * mvPosition; }", + fragmentShader: "varying vec3 vColor; uniform float uTime; void main() { vec2 center = gl_PointCoord - vec2(0.5); float dist = length(center); if (dist > 0.5) discard; float gradient = 1.0 - smoothstep(0.0, 0.5, dist); float glow = 1.0 - smoothstep(0.15, 0.5, dist); vec3 finalColor = vColor * gradient; float alpha = glow * (0.7 + sin(uTime * 2.0 + gl_FragCoord.x * 0.05) * 0.3); gl_FragColor = vec4(finalColor, alpha); }", + transparent: true, + opacity: 0.9, + depthWrite: false, + blending: THREE.AdditiveBlending, + vertexColors: true, + }); + + const particles = new THREE.Points(geometry, shaderMaterial); + scene.add(particles); + + const centerGlowGeometry = new THREE.SphereGeometry(8, 32, 32); + const centerGlowMaterial = new THREE.MeshBasicMaterial({ + color: 0x6366f1, + transparent: true, + opacity: 0.08, + }); + const centerGlow = new THREE.Mesh(centerGlowGeometry, centerGlowMaterial); + scene.add(centerGlow); + + const animate = () => { + animationIdRef.current = requestAnimationFrame(animate); + + const time = performance.now() * 0.001; + + if (shaderMaterial.uniforms.uTime) { + shaderMaterial.uniforms.uTime.value = time; + } + + particles.rotation.y += 0.0003; + particles.rotation.x += 0.0001; + + centerGlow.rotation.y -= 0.0002; + const pulse = 0.08 + Math.sin(time * 1.5) * 0.03; + centerGlow.scale.setScalar(pulse); + + renderer.render(scene, camera); + }; + + animate(); + + const handleResize = () => { + const newWidth = containerRef.current?.clientWidth || width; + const newHeight = containerRef.current?.clientHeight || height; + + camera.aspect = newWidth / newHeight; + camera.updateProjectionMatrix(); + + renderer.setSize(newWidth, newHeight); + shaderMaterial.uniforms.uPixelRatio.value = renderer.getPixelRatio(); + }; + + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + cancelAnimationFrame(animationIdRef.current); + + geometry.dispose(); + shaderMaterial.dispose(); + renderer.dispose(); + centerGlowGeometry.dispose(); + centerGlowMaterial.dispose(); + }; + }, []); + + return ( +
+ +
+ ); +}; + +export default GalaxyBackground; +`; +fs.writeFileSync('d:/ÃñÖÚÆÕ¿µ/video_item/video-gen-app/src/components/GalaxyBackground.tsx', content); +console.log('File written successfully');