#javascript #анимация #canvas #html5_canvas
Есть вот такая абстракция знаю что через canvas такое анимируется, но не силен в данной области, может кто видел или знает как анимировать?
Ответы
Ответ 1
Примерная анимация на Three.js var planeVertShader = ` #define PI 3.1415926 uniform float time; uniform float amplitude; uniform float waveLength; uniform vec3 pos; uniform float timeSpeed; uniform float planeHeight; uniform float initRotation; uniform float speedRotation; varying vec3 varPos; void main() { vec3 p = position + pos + vec3(0., .1, 0.); float wLength = 1. / waveLength; float heightNormal = position.y / planeHeight; float oneRound = heightNormal * PI * 4.; //вращение p.y += sin(p.x * wLength + time) * cos(p.z * wLength + time) * amplitude; p.x = cos(-time * speedRotation + oneRound + initRotation) * position.x; p.z = sin(-time * speedRotation + oneRound + initRotation) * position.x; //скручивание p.x += cos(-time * speedRotation + oneRound) * heightNormal * 5.; p.z += sin(-time * speedRotation + oneRound) * heightNormal * 5.; p += pos + vec3(0., .1, 0.); varPos = position; vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 ); gl_Position = projectionMatrix * mvPosition; } `; var planeFragShader = ` void main() { gl_FragColor = vec4(0.366,0.048,0.515,1.000); } `; var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000); camera.position.set(0, 25, 150); camera.rotation.set(0, 0, 1.57); var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setClearColor(0x000000); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); window.addEventListener('resize', function () { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }, false); // plane var planes = []; var planeHeight = 125; var planeWidth = 15; var planeGeom = new THREE.PlaneBufferGeometry(planeWidth, planeHeight, 15, 100); planeGeom.translate(4, 0, 0); for (let i = 0; i < 2; i++) { let pos = new THREE.Vector3(0, 10, 110); let plane = new THREE.LineSegments(planeGeom, new THREE.ShaderMaterial({ uniforms: { time: { value: 0 }, amplitude: { value: 5 }, waveLength: { value: Math.PI * 5 }, pos: { value: pos }, timeSpeed: { value: THREE.Math.randFloat(Math.PI * .5, Math.PI) }, planeHeight: { value: planeHeight }, initRotation: { value: THREE.Math.randFloat(0, Math.PI) }, speedRotation: { value: THREE.Math.randFloat(Math.PI * 0.5, Math.PI) } }, vertexShader: planeVertShader, fragmentShader: planeFragShader })); scene.add(plane); planes.push(plane) } var clock = new THREE.Clock(); var t = 0; var delta = 0; render(); function render() { requestAnimationFrame(render); delta = clock.getDelta(); t += delta; planes.forEach(sw => { sw.material.uniforms.time.value = t }); renderer.render(scene, camera); } body { overflow: hidden; margin: 0; }Ответ 2
WebGL. Поверхность задана при помощи signed distance, на нее наложен математический шум, который сдвигается со временем. Поверхность находится при помощи raymarch, все это дело вычисляется во фрагментном шейдере. let canvas = document.querySelector('canvas'); let gl = canvas.getContext('webgl'); let pid = gl.createProgram(); shader(` attribute vec2 coords; void main(void) { gl_Position = vec4(coords.xy, 0.0, 1.0); } `, gl.VERTEX_SHADER); shader(` precision highp float; uniform vec4 mr; uniform float time; #define rot(a) mat2(cos(a),-sin(a),sin(a),cos(a)) #define hash31(p) fract(sin(dot(p,vec3(127.1,311.7, 74.7)))*43758.5453123) float noise3(vec3 p) { vec3 i = floor(p); vec3 f = fract(p); f = f*f*(3.-2.*f); return mix( mix( mix(hash31(i+vec3(0,0,0)), hash31(i+vec3(1,0,0)),f.x), mix(hash31(i+vec3(0,1,0)), hash31(i+vec3(1,1,0)),f.x), f.y), mix( mix(hash31(i+vec3(0,0,1)), hash31(i+vec3(1,0,1)),f.x), mix(hash31(i+vec3(0,1,1)), hash31(i+vec3(1,1,1)),f.x), f.y), f.z); } float fbm3(vec3 p) { float v = 0., a = .5; mat2 R = rot(.37); for (int i = 0; i < 2; i++) { p *= 2.; a /= 2.; p.xy *= R; p.yz *= R; v += a * noise3(p); } return v; } float map( in vec3 pos ){ return pos.y + fbm3(vec3(pos.x+time,pos.yz)); } float rayMarch( in vec3 ro, in vec3 rd, float tmax ){ float t = 0.0; float h = (1.0-ro.y)/rd.y; for( int i=0; i<10; i++ ){ vec3 pos = ro + t*rd; float h = map( pos ); if( h<0.001 || t>tmax ) break; t += h; } return t; } vec3 render( in vec3 ro, in vec3 rd ) { vec3 col = vec3(0.); float t = rayMarch( ro, rd, 10. ); vec3 pos = ro + t*rd; vec2 scp = sin(23.*pos.xz); col += 2.0*exp(-5.0*abs(scp.x)); col += 2.0*exp(-5.0*abs(scp.y)); return col*0.5*exp(-0.1*t*t); } mat3 setCamera( in vec3 ro, in vec3 rt, in float cr ) { vec3 cw = normalize(rt-ro); vec3 cp = vec3(sin(cr), cos(cr),0.0); vec3 cu = normalize( cross(cw,cp) ); vec3 cv = normalize( cross(cu,cw) ); return mat3( cu, cv, -cw ); } void main(void) { vec2 uv = gl_FragCoord.xy/mr.zw; vec2 p = uv-0.5; float an = time*0.5 + 6.0*mr.x/mr.z; vec3 ro = vec3( 2.0*cos(an), 1.0, 2.0*sin(an) ); vec3 rt = vec3( 1.0, 0.0, 0.0 ); mat3 cam = setCamera( ro, rt, 0.35 ); vec3 rd = normalize( cam * vec3( p, -1.0) ); vec3 c = render( ro, rd )*vec3( 0.3, 0.4, 0.8 ); gl_FragColor = vec4(c, 1.0 ); } `, gl.FRAGMENT_SHADER); gl.linkProgram(pid); gl.useProgram(pid); let array = new Float32Array([-1, 3, -1, -1, 3, -1]); gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); let coords = gl.getAttribLocation(pid, "coords"); gl.vertexAttribPointer(coords, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(coords); let mr = gl.getUniformLocation(pid, 'mr'); let time = gl.getUniformLocation(pid, 'time'); let x = 0, y = 0; let changeCenter = e => { e = e.touches ? e.touches[0] : e; let z = window.getComputedStyle(canvas).zoom || 1; let d = document.documentElement; x = (e.clientX + d.scrollLeft - canvas.offsetLeft*z) / z; y = (e.clientY + d.scrollTop - canvas.offsetTop*z) / z } window.addEventListener('mousemove', e => changeCenter(e)); window.addEventListener('touchmove', e => changeCenter(e)); window.addEventListener('resize', resize); resize(); function draw(t) { gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.clearColor(0, 0, 0, 0); gl.uniform4f(mr, x, y, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.uniform1f(time, t/1000); gl.drawArrays(gl.TRIANGLES, 0, 3); requestAnimationFrame(draw) } function shader(src, type) { let sid = gl.createShader(type); gl.shaderSource(sid, src); gl.compileShader(sid); var message = gl.getShaderInfoLog(sid); gl.attachShader(pid, sid); if (message.length > 0) { console.log(src.split('\n').map(function (str, i) { return ("" + (1 + i)).padStart(4, "0") + ": " + str }).join('\n')); throw message; } } function resize(){ canvas.width = window.innerWidth; canvas.height = window.innerHeight; draw(); }
Комментариев нет:
Отправить комментарий