three实现一个三维唱片碟片旋转播放曲线乐章效果代码
代码语言:html
所属分类:三维
代码描述:three实现一个三维唱片碟片旋转播放曲线乐章效果代码
代码标签: three 三维 唱片 碟片 旋转 播放 曲线 乐章
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body{ overflow: hidden; margin: 0; } </style> </head> <body > <script async type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/es-module-shims.1.6.2.js"></script> <script type="importmap"> { "imports": { "three": "//repo.bfw.wiki/bfwrepo/js/module/three/build/146/three.module.js", "three/addons/": "//repo.bfw.wiki/bfwrepo/js/module/three/examples/jsm/" } } </script> <script type="module"> import * as THREE from "three"; import {OrbitControls} from "three/addons/controls/OrbitControls.js"; import {mergeBufferGeometries} from "three/addons/utils/BufferGeometryUtils.js"; import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js"; import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; console.clear(); class Postprocessing { constructor(scene, camera, renderer) { const renderScene = new RenderPass(scene, camera); const bloomPass = new UnrealBloomPass( new THREE.Vector2(window.innerWidth, window.innerHeight), 1.25, 0.25, 0 ); let samples = 4; const target1 = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { type: THREE.FloatType, format: THREE.RGBAFormat, encoding: THREE.sRGBEncoding, samples: samples } ); this.bloomComposer = new EffectComposer(renderer, target1); this.bloomComposer.renderToScreen = false; this.bloomComposer.addPass(renderScene); this.bloomComposer.addPass(bloomPass); const finalPass = new ShaderPass( new THREE.ShaderMaterial({ uniforms: { baseTexture: { value: null }, bloomTexture: { value: this.bloomComposer.renderTarget2.texture } }, vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }`, fragmentShader: `uniform sampler2D baseTexture; uniform sampler2D bloomTexture; varying vec2 vUv; void main() { gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) ); }`, defines: {} }), "baseTexture" ); finalPass.needsSwap = true; const target2 = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { type: THREE.FloatType, format: THREE.RGBAFormat, encoding: THREE.sRGBEncoding, samples: samples } ); this.finalComposer = new EffectComposer(renderer, target2); this.finalComposer.addPass(renderScene); this.finalComposer.addPass(finalPass); } } class LightEmitterCurve extends THREE.Curve{ constructor( radius, turns, height ) { super(); this.radius = radius; this.height = height; this.turns = turns; } getPoint( t, optionalTarget = new THREE.Vector3() ) { return optionalTarget.setFromCylindricalCoords( this.radius, -Math.PI * 2 * this.turns * t, this.height * t ); } } class LightEmitters extends THREE.Object3D{ constructor(gu, count, maxR, height, turns, m){ super(); let gsBall = []; let gsEmitter = []; let start = maxR / 4; let totalWidth = maxR * 0.9 - start; let step = totalWidth / (count - 1); let v3 = new THREE.Vector3(); let axis = new THREE.Vector3(0, 1, 0); for( let i = 0; i < count; i++){ let shift = start + step * i; let gBall = new THREE.SphereGeometry(0.05, 64, 32, 0, Math.PI * 2, 0, Math.PI * 0.5); gBall.translate(0, 0, shift); gsBall.push(gBall); /*let gEmitter = new THREE.CylinderGeometry(0.03, 0.03, height, 16, 200); gEmitter.translate(shift, height * 0.5, 0); let pos = gEmitter.attributes.position; for(let i = 0; i < pos.count; i++){ v3.fromBufferAttribute(pos, i); let ratio = v3.y / height; let angle = -ratio * Math.PI * 2 * turns; v3.applyAxisAngle(axis, angle); pos.setXYZ(i, v3.x, v3.y, v3.z); } gEmitter.computeVertexNormals();*/ let lightEmitterCurve = new LightEmitterCurve(shift, turns, height); let gEmitter = new THREE.TubeGeometry(lightEmitterCurve, 200, 0.02, 16); gsEmitter.push(gEmitter); } let gBalls = mergeBufferGeometries(gsBall); let balls = new THREE.Mesh(gBalls, m.clone()); balls.userData.nonGlowing = true; //balls.castShadow = true; this.add(balls); let gEmitters = mergeBufferGeometries(gsEmitter); let mEmitters = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, color: new THREE.Color(1, 0.25, 0), onBeforeCompile: shader => { shader.uniforms.globalBloom = gu.globalBloom; shader.vertexShader = ` varying vec3 vPos; ${shader.vertexShader} `.replace( `#include <begin_vertex>`, `#include <begin_vertex> vPos = position; ` ); //console.log(shader.vertexShader) shader.fragmentShader = ` #define ss(a, b, c) smoothstep(a, b, c) uniform float globalBloom; varying vec3 vPos; ${shader.fragmentShader} `.replace( `#include <dithering_fragment>`, `#include <dithering_fragment> vec3 colNonGlow = vec3(1, 0.75, 0.75); // * pow((sin(vUv.x * 200. * PI2) * 0.5 + 0.5) * 0.6 + 0.4, 3.); vec3 colGlow = gl_FragColor.rgb; gl_FragColor.rgb = mix(colNonGlow, colGlow, globalBloom); ` ); } }); mEmitters.defines = {"USE_UV" : ""}; let emitters = new THREE.Mesh(gEmitters, mEmitters); //emitters.castShadow = true; this.add(emitters); } } class Belt extends THREE.Mesh{ constructor(gu, mainSize, rBig, rSmall, width, m){ let m1 = m.clone(); m1.color.set("gray"); //m1.side = THREE.DoubleSide; let hSize = mainSize; let path = new THREE.Shape() .absarc(0, 0, rBig, Math.PI * 1.5, Math.PI) .absarc(-hSize + rSmall, -hSize + rSmall, rSmall, Math.PI, Math.PI * 1.5) .lineTo(0, -hSize); const segs = 500; const hw = width * 0.5; let pathPts = path.getSpacedPoints(segs).reverse(); /* let pg = new THREE.BufferGeometry().setFromPoints(pathPts); let pm = new THREE.PointsMaterial({color: "yellow", size: 0.05}); let pp = new THREE.Points(pg, pm); */ let g = new THREE.BoxGeometry(segs, 0.01, width, segs, 1, 1).translate(segs * 0.5, 0.005, 0); let vPrev = new THREE.Vector2(), vCurr = new THREE.Vector2(), vNext = new THREE.Vector2(); let vCP = new THREE.Vector2(), vCN = new THREE.Vector2(), v2 = new THREE.Vector2(), cntr = new THREE.Vector2(); let pos = g.attributes.position; for(let i = 0; i < pos.count; i++){ let idxCurr = Math.round(pos.getX(i)); let idxPrev = idxCurr == 0 ? segs - 1 : idxCurr - 1; let idxNext = idxCurr == segs ? 1 : idxCurr + 1; vPrev.copy(pathPts[idxPrev]); vCurr.copy(pathPts[idxCurr]); vNext.copy(pathPts[idxNext]); vCP.subVectors(vPrev, vCurr); vCN.subVectors(vNext, vCurr); let aCP = vCP.angle(); let aCN = vCN.angle(); let hA = Math.PI * 0.5 - (aCP - aCN) * 0.5; let aspect = Math.cos(hA); v2.set(vCurr.x, vCurr.y).multiplyScalar(pos.getY(i) / aspect); v2.rotateAround(cntr, hA).add(vCurr); pos.setXY(i, v2.x, v2.y); } g.rotateX(-Math.PI * 0.5); g.computeVertexNormals(); super(g, m1); this.castShadow = true; this.receiveShadow = true; this.uniforms = { time: {value: 0}, angularSpe.........完整代码请登录后点击上方下载按钮下载查看
网友评论0