VFX Presentation By Ayush Tripathi

Fractal Cloud Viewer 2

Fractal Cloud Viewer 2

This lets you view an interesting 3D model made from a few levels of recurring patterns.

Drag mouse or touch up or down to move vertically.

An older version implemented with canvas 2D context is available here.

html, body { padding: 0; margin: 0; overflow: hidden; } canvas { width: 100%; height: 100vh; background-color: #000; /* Prevent swiping and dragging problems. */ -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none; } #dialog-backdrop { position: fixed; left: 0; top: 0; bottom: 0; width: 100%; opacity: 0.5; background-color: #000; } #dialog { position: fixed; top: 50%; left: 50%; margin-top: -175px; margin-left: -125px; padding: 8px; font-family: arial; width: 350px; height: 250px; display: flex; flex-direction: column; color: #fff; background-color: rgba(0, 0, 0, 0.7); border-radius: 5px; border: 1px solid #888; box-shadow: 0 0 25px #000; } #dialog a { color: #fff; } #dialog h1 { font-size: 22px; margin-top: 0; } #dialog div.body { flex-grow: 1; } #dialog footer { flex-grow: 0; text-align: center; } #dialog button { font-weight: bold; cursor: pointer; /* encourage people to click it. */ } var pointsData = []; function getPointCoordinatesData() { var newVal = []; pointsData.forEach(function(point) { for (var i = 0; i < point.coords.length;i++) { newVal.push(point.coords[i]); } }); return newVal; } function getPointColoursData() { var newVal = []; pointsData.forEach(function(point) { newVal.push(point.r); newVal.push(point.g); newVal.push(point.b); }); return newVal; } pointsData = []; function addPointToModel(pointInfo) { var scale = pointInfo.radius/255; pointInfo.r *= scale; pointInfo.g *= scale; pointInfo.b *= scale; pointsData.push(new Point([pointInfo.cx, pointInfo.cy, pointInfo.cz], pointInfo.r, pointInfo.g, pointInfo.b)); } function addExtremelyTiny(cx, cy, cz) { addPointToModel({ 'cx': cx, 'cy': cy, 'cz': cz, 'radius': 0.1, "r": 0xff, "g": 0xff, "b": 0xff }); } function addSuperTiny(cx, cy, cz) { addPointToModel({ 'cx': cx, 'cy': cy, 'cz': cz, 'radius': 0.6, "r": 0, "g": 0, "b": 0x88 }); var tinyRadius = 1.2; for (var i = 0; i < 3; i++) { var angle = i * Math.PI * 2 / 3; var x = cx + tinyRadius * Math.cos(angle); var z = cz + tinyRadius * Math.sin(angle); addExtremelyTiny(x, cy + tinyRadius, z); addExtremelyTiny(x, cy - tinyRadius, z); } } function addTiny(cx, cy, cz) { addPointToModel({ 'cx': cx, 'cy': cy, 'cz': cz, 'radius': 1, 'r': 0x44, 'g': 0xbb, 'b': 0, }); var smallRadius = 3; for (var i = 0; i < 4; i++) { var angle = i * Math.PI / 2; var x = cx + smallRadius * Math.cos(angle); var z = cz + smallRadius * Math.sin(angle); addSuperTiny(x, cy + smallRadius, z); addSuperTiny(x, cy - smallRadius, z); } } function addSmall(cx, cy, cz) { addPointToModel({ 'cx': cx, 'cy': cy, 'cz': cz, 'radius': 3, 'r': 0xff, 'g': 0x55, 'b': 0xff }); var smallRadius = 10; for (var i = 0; i < 8; i++) { var angle = i * Math.PI / 4; var x = cx + smallRadius * Math.cos(angle); var z = cz + smallRadius * Math.sin(angle); addTiny(x, cy + smallRadius, z); addTiny(x, cy - smallRadius, z); } } function addGlowing(cx, cy, cz) { addPointToModel({ 'cx': cx, 'cy': cy, 'cz': cz, 'radius': 6, 'r': 0xff, 'g': 0xdd, 'b': 0xff }); var smallRadius = 30; for (var i = 0; i < 8; i++) { var angle = i * Math.PI / 4; var x = cx + smallRadius * Math.cos(angle); var z = cz + smallRadius * Math.sin(angle); addSmall(x, cy + smallRadius, z); addSmall(x, cy - smallRadius, z); } } function initializeModel() { addPointToModel({ "cx": 0, "cy": 0, "cz": 0, "radius": 20, "r": 0xff, "g": 0xff, "b": 0xee }); var radius = 100; for (var i = 0; i < 8; i++) { var angle = i * Math.PI / 4; var x = radius * Math.cos(angle); var z = radius * Math.sin(angle); addGlowing(x, 100, z); addGlowing(x, -100, z); } } initializeModel(); document.addEventListener('DOMContentLoaded', function() { var body = document.querySelector('body'); var dialog = document.getElementById('dialog'); var ok = document.getElementById('dialog-ok'); var dialogBackdrop = document.getElementById('dialog-backdrop'); function hideDialog() { dialog.remove(); dialogBackdrop.remove(); } ok.addEventListener('click', hideDialog); dialogBackdrop.addEventListener('mousedown', hideDialog); dialogBackdrop.addEventListener('touchstart', hideDialog); }); function loadShader(gl, program, src, type) { let sid = gl.createShader(type); gl.shaderSource(sid, src); gl.compileShader(sid); var compiled = gl.getShaderParameter(sid, gl.COMPILE_STATUS); if (!compiled) { console.log('Shader compiled successfully: ' + compiled); var compilationLog = gl.getShaderInfoLog(sid); console.log('Shader compiler log: ' + compilationLog); } gl.attachShader(program, sid); }class Points { constructor(gl, program) { this.gl = gl; this.program = program; this.coloursData = getPointColoursData(); this.coordinates = getPointCoordinatesData(); this.vertexShaderCode = ` precision mediump float; attribute vec3 position; attribute vec3 colour; uniform vec3 scale; uniform mat3 transform; uniform float distance; uniform float yTranslation; varying vec3 pointColour; void main() { vec3 transformedPosition = position; transformedPosition = transformedPosition * transform; transformedPosition.x = transformedPosition.x * scale.x; transformedPosition.y = (transformedPosition.y + yTranslation) * scale.y; transformedPosition.z += 180.0 + distance; gl_Position = vec4(transformedPosition.xy / transformedPosition.z, 0.0, 1.0); float brightnessScale = max(colour.r, max(colour.g, colour.b)); gl_PointSize = 5000.0 * scale.z * scale.z * brightnessScale / transformedPosition.z; if (gl_PointSize < 1.0) { gl_PointSize = 0.0; } pointColour = colour / brightnessScale; }`; this.fragmentShaderCode = ` precision mediump float; varying vec3 pointColour; void main() { float distance = length(2.0 * gl_PointCoord - 1.0); if (distance > 1.0) { discard; // do not draw this pixel. } else { distance = (1.0 - distance); gl_FragColor = vec4(pointColour * distance * distance, 1); } }`; } _initVec3Attribute(key, attributeName, initData) { this[key] = this.gl.getAttribLocation(this.program, attributeName); let array = new Float32Array(initData); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.gl.createBuffer()); this.gl.bufferData(this.gl.ARRAY_BUFFER, array, this.gl.STATIC_DRAW); this.gl.vertexAttribPointer(this[key], 3 /*components per vertex */, this.gl.FLOAT, false, 0, 0); this.gl.enableVertexAttribArray(this[key]); } initCoords() { this.uniforms = { 'scale': this.gl.getUniformLocation(this.program, 'scale'), 'transform': this.gl.getUniformLocation(this.program, 'transform'), 'distance': this.gl.getUniformLocation(this.program, 'distance'), 'yTranslation': this.gl.getUniformLocation(this.program, 'yTranslation') }; this._initVec3Attribute('coords', 'position', this.coordinates); this._initVec3Attribute('colours', 'colour', this.coloursData); this.setAngle(0); } setScale(newScale, aspectRatio) { newScale = [newScale, newScale * aspectRatio, newScale]; this.gl.uniform3fv(this.uniforms.scale, newScale); } setAngle(newRotation) { var sinTheta = Math.sin(newRotation); var cosTheta = Math.cos(newRotation); var matrix = [ cosTheta, 0, sinTheta, 0, 1, 0, -sinTheta, 0, cosTheta ]; this.gl.uniformMatrix3fv(this.uniforms.transform, false, matrix); } setYTranslation(newYTranslation) { this.gl.uniform1f(this.uniforms.yTranslation, newYTranslation); } setDistance(newDistance) { this.gl.uniform1f(this.uniforms.distance, newDistance); } loadShaders() { loadShader(this.gl, this.program, this.vertexShaderCode, this.gl.VERTEX_SHADER); loadShader(this.gl, this.program, this.fragmentShaderCode, this.gl.FRAGMENT_SHADER); } }document.addEventListener('DOMContentLoaded', function() { var canvas = document.querySelector('canvas'); var gl = canvas.getContext('webgl2', {premultipliedAlpha: false}); gl.getExtension('EXT_frag_depth'); var program = gl.createProgram(); var point = new Points(gl, program); point.loadShaders(); gl.linkProgram(program); gl.useProgram(program); point.initCoords(); gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_COLOR, gl.DST_COLOR); gl.blendFunc (gl.ONE, gl.ONE); function draw() { var w = canvas.getAttribute('width'); var h = canvas.getAttribute('height'); gl.viewport(0, 0, w, h); gl.drawArrays(gl.POINTS, 0, point.coordinates.length / 3); } function resized() { var w = window.innerWidth; var h = window.innerHeight; point.setScale((w + h) * 0.0003, w / h); canvas.setAttribute('width', w); canvas.setAttribute('height', h); requestAnimationFrame(draw); } function updateAnimation() { var t = new Date().getTime(); point.setAngle((t * 0.0001) % (2 * Math.PI)); point.setDistance(80 * Math.sin(t * 0.0005)); draw(); requestAnimationFrame(updateAnimation); } resized(); window.addEventListener('resize', resized); gl.clearDepth(0.5); setUpDragUI(point); updateAnimation(); });function setUpDragUI(points) { var y = 61; var previousMousePosition; function getPositionFromEvent(event) { if (event.touches !== undefined && event.touches[0] !== undefined) { var touch = event.touches[0]; return {'x': touch.pageX, 'y': touch.pageY}; } else { return { 'x': event.clientX, 'y': event.clientY }; } } function mouseDown(event) { previousMousePosition = getPositionFromEvent(event); } function mouseUp() { previousMousePosition = undefined; } function mouseMove(event) { if (previousMousePosition !== undefined) { var newP = getPositionFromEvent(event); y += (newP.y - previousMousePosition.y) * 0.1; previousMousePosition = newP; points.setYTranslation(y); } } window.addEventListener('mousedown', mouseDown); window.addEventListener('touchstart', mouseDown); window.addEventListener('mouseup', mouseUp); window.addEventListener('touchend', mouseUp); window.addEventListener('mousemove', mouseMove); window.addEventListener('touchmove', mouseMove); points.setYTranslation(y); }

Comments

Popular posts from this blog

PM COACHING CLASSES

Class 12th Students Connection Network.