three实现三维天空海面正方体粒子透明反射效果代码
代码语言:html
所属分类:三维
代码描述:three实现三维天空海面正方体粒子透明反射效果代码
代码标签: three 三维 天空 海面 正方体 粒子 透明 反射
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> @import url("https://fonts.googleapis.com/css?family=Homenaje"); .p-canvas-webgl { position: fixed; z-index: 1; top: 0; left: 0; } .p-summary { position: absolute; top: 20px; left: 20px; z-index: 2; color: #fff; font-family: "Homenaje", sans-serif; } .p-summary h1 { margin: 0 0 0.2em; font-size: 42px; font-weight: 400; letter-spacing: 0.05em; } .p-summary p { margin: 0; font-size: 1.1rem; letter-spacing: 0.1em; } .p-summary a { color: #fff; } </style> </head> <body > <div class="p-summary"> <h1>three.js Instancing & SkyBox</h1> </div> <canvas class="p-canvas-webgl" id="canvas-webgl"></canvas> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.84.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gl-matrix-min.js"></script> <script > const debounce = (callback, duration) => { var timer; return function (event) { clearTimeout(timer); timer = setTimeout(function () { callback(event); }, duration); }; }; const MathEx = { degrees: function (radian) { return radian / Math.PI * 180; }, radians: function (degree) { return degree * Math.PI / 180; }, clamp: function (value, min, max) { return Math.min(Math.max(value, min), max); }, mix: function (x1, x2, a) { return x1 * (1 - a) + x2 * a; }, polar: function (radian1, radian2, radius) { return [ Math.cos(radian1) * Math.cos(radian2) * radius, Math.sin(radian1) * radius, Math.cos(radian1) * Math.sin(radian2) * radius]; } }; const force3 = { updateVelocity: (velocity, acceleration, mass) => { vec3.scale(acceleration, acceleration, 1 / mass); vec3.add(velocity, velocity, acceleration); }, applyFriction: (acceleration, mu, n) => { const friction = [0, 0, 0]; vec3.scale(friction, acceleration, -1); const normal = n ? n : 1; vec3.normalize(friction, friction); vec3.scale(friction, friction, mu); vec3.add(acceleration, acceleration, friction); }, applyDrag: (acceleration, value) => { const drag = [0, 0, 0]; vec3.scale(drag, acceleration, -1); vec3.normalize(drag, drag); vec3.scale(drag, drag, vec3.length(acceleration) * value); vec3.add(acceleration, acceleration, drag); }, applyHook: (velocity, acceleration, anchor, rest_length, k) => { const hook = [0, 0, 0]; vec3.sub(hook, velocity, anchor); const distance = vec3.length(hook) - rest_length; vec3.normalize(hook, hook); vec3.scale(hook, hook, -1 * k * distance); vec3.add(acceleration, acceleration, hook); } }; const normalizeVector2 = vector => { vector.x = vector.x / window.innerWidth * 2 - 1; vector.y = -(vector.y / window.innerHeight) * 2 + 1; }; class ForcePerspectiveCamera extends THREE.PerspectiveCamera { constructor(fov, aspect, near, far) { super(fov, aspect, near, far); this.k = 0.02; this.d = 0.2; this.velocity = [0, 0, 0]; this.acceleration = [0, 0, 0]; this.anchor = [0, 0, 0]; this.lookK = 0.02; this.lookD = 0.2; this.lookVelocity = [0, 0, 0]; this.lookAcceleration = [0, 0, 0]; this.lookAnchor = [0, 0, 0]; } updatePosition() { force3.applyHook(this.velocity, this.acceleration, this.anchor, 0, this.k); force3.applyDrag(this.acceleration, this.d); force3.updateVelocity(this.velocity, this.acceleration, 1); } updateLook() { force3.applyHook(this.lookVelocity, this.lookAcceleration, this.lookAnchor, 0, this.lookK); force3.applyDrag(this.lookAcceleration, this.lookD); force3.updateVelocity(this.lookVelocity, this.lookAcceleration, 1); } render() { this.updatePosition(); this.updateLook(); this.position.set( this.velocity[0], this.velocity[1], this.velocity[2]); this.lookAt({ x: this.lookVelocity[0], y: this.lookVelocity[1], z: this.lookVelocity[2] }); }} class CameraController { constructor(camera) { this.camera = camera; this.radian1 = 0; this.radian1Base = 0; this.radian2 = 0; this.radian2Base = 0; this.radius = 2500; this.isZoom = false; } rotate(x, y) { if (this.isZoom === true) this.isZoom = false; this.radian1 = MathEx.clamp(this.radian1Base + y, MathEx.radians(-75), MathEx.radians(75)); this.radian2 = this.radian2Base - x * 2; } zoom(delta) { if (!delta) return; if (this.isZoom === false) this.isZoom = true; const prevRadius = this.radius; this.radius -= delta / Math.abs(delta) * 200; this.radius = MathEx.clamp(this.radius, 700, 8000); const diff = prevRadius - this.radius; } touchEnd() { this.radian1Base = this.radian1; this.radian2Base = this.radian2; } render() { this.camera.anchor = MathEx.polar(this.radian1, this.radian2, this.radius); this.camera.render(); } computeZoomLength() { if (this.isZoom) { return vec3.length(this.camera.acceleration) * 0.05; } else { return 0; } } computeAcceleration() { return vec3.length(this.camera.acceleration) * 0.05; }} ; class Debris { constructor() { this.uniforms = { time: { type: 'f', value: 0 }, cubeTex: { type: 't', value: null } }; this.instances = 1000; this.obj = null; } init(texture) { this.uniforms.cubeTex.value = texture; this.obj = this.createObj(); } createObj() { const geometry = new THREE.InstancedBufferGeometry(); const baseGeometry = new THREE.BoxBufferGeometry(10, 10, 10); geometry.addAttribute('position', baseGeometry.attributes.position); geometry.addAttribute('normal', baseGeometry.attributes.normal); geometry.setIndex(baseGeometry.index); const translate = new THREE.InstancedBufferAttribute(new Float32Array(this.instances * 3), 3, 1); const offsets = new THREE.InstancedBufferAttribute(new Float32Array(this.instances), 1, 1); const rotates = new THREE.InstancedBufferAttribute(new Float32Array(this.instances * 3), 3, 1); for (var i = 0, ul = offsets.count; i < ul; i++) { const polar = MathEx.polar(Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI, Math.random() * 3000 + 100); translate.setXYZ(i, polar[0], polar[1], polar[2]); offsets.setXYZ(i, Math.random() * 100); rotates.setXYZ(i, Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5); } geometry.addAttribute('translate', translate); geometry.addAttribute('offset', offsets); geometry.addAttribute('rotate', rotates); return new THREE.Mesh( geometry, new THREE.RawShaderMaterial({ uniforms: this.uniforms, vertexShader: `attribute vec3 position; attribute vec3 normal; attribute vec3 translate; attribute float offset; attribute vec3 rotate; uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; uniform mat4 modelMatrix; uniform float time; varying vec3 vPosition; varying vec3 vNormal; mat4 computeTranslateMat(vec3 v) { return mat4( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, v.x, v.y, v.z, 1.0 ); } mat4 computeRotateMatX(float radian) { return mat4( 1.0, 0.0, 0.0, 0.0, 0.0, cos(radian), -sin(radian), 0.0, 0.0, sin(radian), cos(radian), 0.0, 0.0, 0.0, 0.0, 1.0 ); } mat4 computeRotateMatY(float radian) { return mat4( cos(radian), 0.0, sin(radian), 0.0, 0.0, 1.0, 0.0, 0.0, -sin(radian), 0.0, cos(radian), 0.0, 0.0, 0.0, 0.0, 1.0 ); } mat4 computeRotateMatZ(float radian) { return mat4( cos(radian), -sin(radian), 0.0, 0.0, sin(radian), cos(radian), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ); } mat4 computeRotateMat(float radX, float radY, float radZ) { return computeRotateMatX(radX) * computeRotateMatY(radY) * computeRotateMatZ(radZ); } void main(void) { float radian = radians(time); mat4 rotateWorld = computeRotateMat(radian * 5.0 + rotate.x, radian * 20.0 + rotate.y, radian + rotate.z); mat4 rotateSelf = computeRotateMat(radian * rotate.x * 100.0, radian * rotate.y * 100.0, radian * rotate.z * 100.0); vec4 updatePosition = rotateWorld * computeTranslateMat(translate) * rotateSelf * vec4(position + normalize(position) * offset, 1.0); vPosition = (modelMatrix * updatePosition).xyz; vNormal = (modelMatrix * rotateWorld * rotateSelf * vec4(normal, 1.0)).xyz; gl_Position = projectionMatrix * modelViewMatrix * updatePosition; }`, fragmentShader: `precision highp float; uniform vec3 cameraPosition; uniform float time; uniform samplerCube cubeTex; varying vec3 vPosition; varying vec3 vNormal; void main() { vec3 ref = reflect(vPosition - cameraPosition, vNormal); vec4 envColor = textureCube(cubeTex, ref); gl_FragColor = envColor * vec4(0.8, 1.0, 0.95, 0.7); }`, transparent: true, side: THREE.DoubleSide })); } render(time) { this.uniforms.time.value += time; }} ; class SkyBox { constructor() { this.uniforms = { time: { type: 'f', value: 0 }, cubeTex: { type: 't', value: null } }; this.obj = null; } init(texture) { this.uniforms.cubeTex.value = texture; this.obj = this.createObj(); } createObj() { return new THREE.Mesh( new THREE.BoxBufferGeometry(30000, 30000, 30000, 1, 1, 1), new THREE.RawShaderMaterial({ uniforms: this.uniforms, vertexShader: `attribute vec3 position; attribute vec3 normal; attribute vec2 uv; uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; uniform float time; varying vec3 vPosition; void main(void) { vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`, fragmentShader: `precision highp float; uniform samplerCube cubeTex; varying vec3 vPosition; void main() { vec3 normal = normalize(vPosition); vec4 color = textureCube(cubeTex, normal); gl_FragColor = color; }`, side: THREE.BackSide })); } render(time) { this.uniforms.time.value += time; }} class PostEffect { constructor(texture) { this.uniforms = { time: { type: 'f', value: 0 }, resolution: { type: 'v2', value: new THREE.Vector2(window.innerWidth, window.innerHeight) }, texture: { type: 't', value: texture }, strengthZoom: { type: 'f', value: 0 }, strengthGlitch: { type: 'f', value: 0 } }; this.obj = this.createObj(); } createObj() { return new THREE.Mesh( new THREE.PlaneBuf.........完整代码请登录后点击上方下载按钮下载查看
网友评论0