You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2021/09/18 03:03:36 UTC
[apisix-website] branch master updated: feat: apisix-website
redesign, add shaders and components used in UI (Sub-PR2) (#495)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
The following commit(s) were added to refs/heads/master by this push:
new 9421df2 feat: apisix-website redesign, add shaders and components used in UI (Sub-PR2) (#495)
9421df2 is described below
commit 9421df28c7aa357f5d490896c192ca748887bb01
Author: Shivam Singh <57...@users.noreply.github.com>
AuthorDate: Sat Sep 18 08:33:33 2021 +0530
feat: apisix-website redesign, add shaders and components used in UI (Sub-PR2) (#495)
---
.../src/pages/sections/components/arrowAnim.jsx | 55 +++++
.../pages/sections/components/eventPosterCard.jsx | 57 ++++++
.../src/pages/sections/components/heroCanvas.jsx | 227 +++++++++++++++++++++
.../src/pages/sections/components/ossCanvas.jsx | 129 ++++++++++++
website/src/shaders/fragment.frag | 20 ++
website/src/shaders/vertex.vert | 157 ++++++++++++++
6 files changed, 645 insertions(+)
diff --git a/website/src/pages/sections/components/arrowAnim.jsx b/website/src/pages/sections/components/arrowAnim.jsx
new file mode 100644
index 0000000..a008e77
--- /dev/null
+++ b/website/src/pages/sections/components/arrowAnim.jsx
@@ -0,0 +1,55 @@
+import React, { useRef } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../../css/customTheme.css";
+
+function ArrowAnim() {
+ const endpathRef1 = useRef(null);
+ const endpathRef2 = useRef(null);
+
+ function mouseOver() {
+ gsap.to([endpathRef2.current],{
+ strokeDashoffset: 970,
+ duration: 0.4
+ });
+ gsap.to([endpathRef1.current],{
+ stroke: "#9b9b9b",
+ duration: 0.4
+ });
+ gsap.to([endpathRef2.current],{
+ stroke: "#9b9b9b",
+ duration: 0.4
+ });
+ }
+
+ function mouseOut() {
+ gsap.to([endpathRef2.current],{
+ strokeDashoffset: 1002,
+ duration: 0.4
+ });
+ gsap.to([endpathRef1.current],{
+ stroke: "black",
+ duration: 0.4
+ });
+ gsap.to([endpathRef2.current],{
+ stroke: "black",
+ duration: 0.4
+ });
+ }
+
+ return (
+ <>
+ <Link
+ to={useBaseUrl("docs")} onMouseOver={mouseOver} onMouseLeave={mouseOut} className="btn-docs">
+ Go to docs...
+ <svg width="15" strokeWidth="3" height="25" viewBox="0 0 43 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path ref={endpathRef1} d="M27.5 1L42.5 16L27.5 31" stroke="black" strokeLinecap="round" strokeLinejoin="round"/>
+ <path ref={endpathRef2} className="arrow-btn" d="M42.5 16H0.5" stroke="black" strokeLinecap="round" strokeLinejoin="round"/>
+ </svg>
+ </Link>
+ </>
+ );
+ }
+
+ export default ArrowAnim;
diff --git a/website/src/pages/sections/components/eventPosterCard.jsx b/website/src/pages/sections/components/eventPosterCard.jsx
new file mode 100644
index 0000000..a34a422
--- /dev/null
+++ b/website/src/pages/sections/components/eventPosterCard.jsx
@@ -0,0 +1,57 @@
+import React, { useState, useRef, useEffect } from "react";
+import gsap from "gsap"
+import "../../../css/customTheme.css";
+
+const EventPosterCard = () => {
+ const [display, setDisplay] = useState(true);
+ const picRef = useRef(null);
+
+ useEffect(() => {
+ gsap.fromTo(picRef.current, {
+ x: 500,
+ opacity: 0
+ }, {
+ x: 0,
+ opacity: 1,
+ delay: 3.0,
+ });
+ }, []);
+
+ useEffect(() => {
+ if (!localStorage.getItem('SHOW_EVENT_ENTRY')) {
+ setDisplay(true);
+ };
+ }, []);
+
+ const onClose = () => {
+ gsap.to(picRef.current, {
+ x: 500,
+ opacity: 0,
+ onComplete: ()=>{
+ setDisplay(false);
+ }
+ });
+ if (typeof window !== 'undefined') {
+ localStorage.setItem('SHOW_EVENT_ENTRY', 'true');
+ }
+ };
+
+ if (!display) {
+ return null;
+ }
+
+ return (
+ <div ref={picRef} className="pic-wrapper">
+ <button className="pic-wrapper-close" onClick={onClose}>
+ <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" className="svg-inline--fa fa-times fa-w-11" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512">
+ <path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path>
+ </svg>
+ </button>
+ <a href="/events/2021/08/21/shanghai-meetup" onClick={onClose}>
+ <img src="/img/meetup-card.jpg" alt="" />
+ </a>
+ </div>
+ )
+ }
+
+ export default EventPosterCard;
diff --git a/website/src/pages/sections/components/heroCanvas.jsx b/website/src/pages/sections/components/heroCanvas.jsx
new file mode 100644
index 0000000..15e1fc6
--- /dev/null
+++ b/website/src/pages/sections/components/heroCanvas.jsx
@@ -0,0 +1,227 @@
+import React, { useRef, useEffect } from "react";
+import * as THREE from "three";
+import gsap from "gsap"
+import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
+import "../../../css/customTheme.css";
+import vertex from '!!raw-loader!../../../shaders/vertex.vert';
+import fragment from '!!raw-loader!../../../shaders/fragment.frag';
+
+function HeroCanvas() {
+ const canvasRef = useRef(0);
+ const overlayRef = useRef(0);
+
+ let canvasHeight, canvasWidth, screenWidth, screenHeight, controls;
+ let isLoaded = false, isRendering = false, animationFrame;
+
+ useEffect(() => {
+
+ screenWidth = window.innerWidth;
+ screenHeight = window.innerHeight;
+
+ let mouse = {x: 0.5, y: 0.5};
+ let fragMouse = {x: 0.5, y: 0.5};
+
+ let camera, mesh, scene, renderer, material, geometry;
+
+ window.addEventListener('resize', onWindowResize, false);
+
+ if (screenWidth > 800) {
+ canvasHeight = screenHeight;
+ canvasWidth = screenWidth / 2;
+ } else {
+ canvasHeight = screenHeight / 2;
+ canvasWidth = screenWidth;
+ }
+
+ canvasRef.current.width = canvasWidth;
+ canvasRef.current.height = canvasHeight;
+
+ canvasRef.current.addEventListener("mousemove", function (event) {
+
+ let ctx = {
+ x: (event.clientX),
+ y: (event.clientY)
+ };
+
+ const canvasOffset = {
+ left: canvasRef.current.getBoundingClientRect().x,
+ top: canvasRef.current.getBoundingClientRect().y
+ };
+
+ ctx.x = ((ctx.x - canvasOffset.left) / canvasWidth);
+ ctx.y = ((ctx.y - canvasOffset.top) / canvasHeight);
+
+ gsap.to(mouse, 2, {
+ x: ctx.x * (canvasWidth / canvasHeight) - (canvasWidth / canvasHeight) / 2,
+ y: (1.0 - ctx.y) - 0.5,
+ onUpdate: ()=>{
+ material.uniforms.u_mouse.value.x = mouse.x;
+ material.uniforms.u_mouse.value.y = mouse.y;
+ }
+ });
+
+ gsap.to(fragMouse, 2, {
+ x: ctx.x,
+ y: (1.0 - ctx.y),
+ onUpdate: ()=>{
+ material.uniforms.u_fragMouse.value.x = fragMouse.x;
+ material.uniforms.u_fragMouse.value.y = fragMouse.y;
+ }
+ });
+ });
+
+ function getRandom(a, b) {
+ return a + (b - a) * Math.random();
+ }
+
+ let canvasObserver = new IntersectionObserver(onCanvasIntersection, {
+ root: null,
+ threshold: 0.01,
+ });
+
+ init(canvasWidth, canvasHeight);
+
+ function onCanvasIntersection(entries, opts){
+ entries.forEach( entry => {
+ if (entry.isIntersecting && isLoaded) {
+ if (isLoaded && !isRendering) {
+ animate();
+ } else {
+ console.log("Loading")
+ }
+ } else {
+ if (animationFrame) {
+ cancelAnimationFrame(animationFrame);
+ isRendering = false;
+ }
+ }
+ }
+ );
+ }
+
+ canvasObserver.observe(canvasRef.current);
+
+ function init(width, height) {
+ const ctx = canvasRef.current;
+
+ renderer = new THREE.WebGLRenderer({canvas: ctx});
+ renderer.autoClearColor = false;
+
+ camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);
+ controls = new OrbitControls( camera, renderer.domElement );
+
+ controls.enableZoom = false;
+ controls.enablePan = false;
+ controls.enabled = false;
+
+ geometry = new THREE.PlaneBufferGeometry(width / height, 1, 200, 200);
+
+ let count = geometry.attributes.position.count;
+ let arrSize = new THREE.BufferAttribute(new Float32Array(count), 1);
+
+ for (let i = 0; i < arrSize.count; i++) {
+ arrSize.array[i] = getRandom(0, 1)
+ }
+ geometry.setAttribute("aSize", arrSize, 1);
+
+ geometry.scale(2.0, 1.0, 1.0);
+
+ scene = new THREE.Scene();
+ renderer.setSize(canvasWidth, canvasHeight);
+
+ let uniforms = {
+ u_time: {
+ type: "f",
+ value: 1.0
+ },
+ u_resolution: {
+ type: "v2",
+ value: new THREE.Vector2()
+ },
+ u_mouse: {
+ type: "v2",
+ value: new THREE.Vector2(0.5, 0.5)
+ },
+ u_fragMouse: {
+ type: "v2",
+ value: new THREE.Vector2(0.5, 0.5)
+ },
+ };
+
+ scene.background = new THREE.Color('red');
+
+ camera.position.z = 5;
+ controls.update();
+
+ material = new THREE.ShaderMaterial({
+ uniforms: uniforms,
+ vertexShader: vertex,
+ fragmentShader: fragment,
+ wireframe: true,
+ side: THREE.DoubleSide
+ });
+
+ mesh = new THREE.Points(geometry, material);
+
+ let backGeometry = new THREE.PlaneBufferGeometry(width / height, 1, 200, 200);
+ let bgMaterial = new THREE.MeshBasicMaterial({color: 0x121212, wireframe: false});
+ let background = new THREE.Mesh(backGeometry, bgMaterial);
+
+ backGeometry.scale(50,50,1);
+ background.position.set(10,10,-10);
+ background.rotation.set(Math.PI/2,0,0);
+
+ scene.add(mesh);
+ scene.add(background);
+
+ camera.position.set( 0.16430412417444037, -1.5202138879420155, 0.20892968987792318); // Tested and checked
+ controls.update();
+
+ renderer.setPixelRatio(window.devicePixelRatio);
+ onWindowResize();
+
+ isLoaded = true;
+ }
+
+ function onWindowResize(event) {
+ screenHeight = window.innerHeight;
+ screenWidth = window.innerWidth;
+
+ renderer.setSize(canvasWidth, canvasHeight);
+ material.uniforms.u_resolution.value.x = renderer.domElement.width;
+ material.uniforms.u_resolution.value.y = renderer.domElement.height;
+ }
+
+ function animate() {
+ animationFrame = requestAnimationFrame(animate);
+ material.uniforms.u_time.value += 0.05;
+ controls.update();
+ renderer.render(scene, camera);
+ isRendering = true;
+ }
+
+ return ()=>{
+ renderer.dispose();
+ canvasObserver.disconnect();
+ }
+ }, []);
+
+
+ useEffect(() => {
+ gsap.to(overlayRef.current,{
+ height: 0,
+ delay: window.innerWidth >= 768 ? 0 : 0.3,
+ duration: 2.1,
+ ease: "Expo.easeInOut"
+ });
+ }, [])
+
+ return (
+ <div style={{position: "relative"}}>
+ <canvas ref={canvasRef} className="homeCanvas"></canvas>
+ <div ref={overlayRef} className="homeCanvas-overlay"></div>
+ </div>
+ );
+}
+
+export default HeroCanvas;
diff --git a/website/src/pages/sections/components/ossCanvas.jsx b/website/src/pages/sections/components/ossCanvas.jsx
new file mode 100644
index 0000000..8d2aca6
--- /dev/null
+++ b/website/src/pages/sections/components/ossCanvas.jsx
@@ -0,0 +1,129 @@
+import React, { useRef, useEffect, useState } from "react";
+import * as THREE from "three";
+import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
+import "../../../css/customTheme.css";
+
+function OssCanvas() {
+ const [screenWidth, setScreenWidth] = useState(typeof window !== 'undefined' && window.innerWidth);
+ const [screenHeight, setScreenHeight] = useState(typeof window !== 'undefined' && window.innerWidth);
+
+ const canvasRef = useRef(null);
+
+ let canvasHeight, canvasWidth;
+
+ useEffect(() => {
+
+ let camera, scene, renderer, material, mesh;
+
+ window.addEventListener('resize', onWindowResize, false);
+
+ let controls;
+ let isLoaded = false, isRendering = false, animationFrame;
+
+ if (screenWidth > 800) {
+ canvasHeight = 500;
+ canvasWidth = screenWidth/2;
+ } else {
+ canvasHeight = 500
+ canvasWidth = screenWidth;
+ }
+
+ function onWindowResize(event) {
+ setScreenHeight(window.innerHeight);
+ setScreenWidth(window.innerWidth);
+ renderer.setSize(canvasWidth, canvasHeight);
+ }
+
+ let ossCanvasObserver = new IntersectionObserver(onOssCanvasIntersection, {
+ root: null,
+ threshold: 0.01,
+ });
+
+ function init(width, height) {
+
+ const ctx = canvasRef.current;
+ renderer = new THREE.WebGLRenderer({canvas: ctx});
+
+ camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 100);
+
+ controls = new OrbitControls( camera, renderer.domElement );
+ controls.enableZoom = false;
+
+ const radius = window.innerWidth > 768 ? 5 : 4.5;
+ const detail = 8;
+
+ const geometry = new THREE.IcosahedronGeometry(radius, detail);
+
+ camera.position.z = 2;
+ camera.position.x = 3;
+
+ controls.update();
+
+ scene = new THREE.Scene();
+ renderer.setSize(canvasWidth, canvasHeight);
+
+ scene.background = new THREE.Color(0x000000);
+
+ material = new THREE.MeshNormalMaterial({wireframe: false, flatShading: true});
+
+ mesh = new THREE.Mesh(geometry, material);
+
+ scene.add(mesh);
+ mesh.position.set(3, 0, -9.5);
+
+ controls.target.copy(mesh.position)
+
+ controls.update();
+ renderer.setPixelRatio(window.devicePixelRatio);
+
+ onWindowResize();
+
+ isLoaded = true;
+ }
+
+ function animate() {
+ animationFrame = requestAnimationFrame(animate);
+
+ mesh.rotation.x += 0.005;
+ mesh.rotation.y += 0.005;
+
+ controls.update();
+
+ renderer.render(scene, camera);
+ isRendering = true;
+ }
+
+ init(canvasWidth, canvasHeight);
+
+ function onOssCanvasIntersection(entries, opts){
+ entries.forEach(entry => {
+ if (entry.isIntersecting && isLoaded) {
+ if (isLoaded && !isRendering) {
+ animate();
+ } else {
+ console.log("Loading")
+ }
+ } else {
+ if (animationFrame) {
+ cancelAnimationFrame(animationFrame);
+ isRendering = false;
+ }
+ }
+ }
+ );
+ }
+
+ ossCanvasObserver.observe(canvasRef.current);
+
+ return () => {
+ renderer.dispose();
+ ossCanvasObserver.disconnect();
+ }
+ }, []);
+
+ return (
+ <canvas ref={canvasRef} width={canvasWidth} height={canvasHeight} className="ossCanvas"></canvas>
+ );
+}
+
+export default OssCanvas;
diff --git a/website/src/shaders/fragment.frag b/website/src/shaders/fragment.frag
new file mode 100644
index 0000000..048443d
--- /dev/null
+++ b/website/src/shaders/fragment.frag
@@ -0,0 +1,20 @@
+precision mediump float;
+
+uniform vec2 u_resolution;
+uniform float u_time;
+uniform vec2 u_mouse;
+uniform vec2 u_fragMouse;
+
+varying vec2 vUv;
+varying float transfer;
+varying float value;
+
+void main() {
+ vec2 st = gl_FragCoord.xy / u_resolution;
+ vec2 mouse = u_fragMouse;
+
+ st.x *= (u_resolution.x / u_resolution.y);
+ mouse.x *= (u_resolution.x / u_resolution.y);
+
+ gl_FragColor = vec4(vec3(1.0, 0.0, transfer), 1.0);
+}
diff --git a/website/src/shaders/vertex.vert b/website/src/shaders/vertex.vert
new file mode 100644
index 0000000..a3b3f31
--- /dev/null
+++ b/website/src/shaders/vertex.vert
@@ -0,0 +1,157 @@
+precision mediump float;
+
+attribute float aSize;
+
+uniform float u_time;
+uniform vec2 u_resolution;
+uniform vec2 u_scale;
+uniform vec2 u_mouse;
+uniform float u_zpos;
+
+varying vec2 vUv;
+varying float transfer;
+varying float value;
+
+mat4 rotationMatrix(vec3 axis, float angle) {
+ axis = normalize(axis);
+ float s = sin(angle);
+ float c = cos(angle);
+ float oc = 1.0 - c;
+
+ return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
+ oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
+ oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+vec3 rotate(vec3 v, vec3 axis, float angle) {
+ mat4 m = rotationMatrix(axis, angle);
+ return (m * vec4(v, 1.0)).xyz;
+}
+
+vec3 mod289(vec3 x) {
+ return x - floor(x * (1.0 / 289.0)) * 289.0;
+}
+
+vec4 mod289(vec4 x) {
+ return x - floor(x * (1.0 / 289.0)) * 289.0;
+}
+
+vec4 permute(vec4 x) {
+ return mod289(((x * 34.0) + 1.0) * x);
+}
+
+vec4 taylorInvSqrt(vec4 r) {
+ return 1.79284291400159 - 0.85373472095314 * r;
+}
+
+float snoise(vec3 v) {
+ const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
+ const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
+
+ vec3 i = floor(v + dot(v, C.yyy));
+ vec3 x0 = v - i + dot(i, C.xxx);
+
+ vec3 g = step(x0.yzx, x0.xyz);
+ vec3 l = 1.0 - g;
+ vec3 i1 = min(g.xyz, l.zxy);
+ vec3 i2 = max(g.xyz, l.zxy);
+
+ vec3 x1 = x0 - i1 + C.xxx;
+ vec3 x2 = x0 - i2 + C.yyy;
+ vec3 x3 = x0 - D.yyy;
+
+ // Permutations
+ i = mod289(i);
+ vec4 p = permute(permute(permute(
+ i.z + vec4(0.0, i1.z, i2.z, 1.0)) +
+ i.y + vec4(0.0, i1.y, i2.y, 1.0)) +
+ i.x + vec4(0.0, i1.x, i2.x, 1.0));
+
+ float n_ = 0.142857142857;
+ vec3 ns = n_ * D.wyz - D.xzx;
+
+ vec4 j = p - 49.0 * floor(p * ns.z * ns.z);
+
+ vec4 x_ = floor(j * ns.z);
+ vec4 y_ = floor(j - 7.0 * x_);
+
+ vec4 x = x_ * ns.x + ns.yyyy;
+ vec4 y = y_ * ns.x + ns.yyyy;
+ vec4 h = 1.0 - abs(x) - abs(y);
+
+ vec4 b0 = vec4(x.xy, y.xy);
+ vec4 b1 = vec4(x.zw, y.zw);
+
+ vec4 s0 = floor(b0) * 2.0 + 1.0;
+ vec4 s1 = floor(b1) * 2.0 + 1.0;
+ vec4 sh = -step(h, vec4(0.0));
+
+ vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
+ vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
+
+ vec3 p0 = vec3(a0.xy, h.x);
+ vec3 p1 = vec3(a0.zw, h.y);
+ vec3 p2 = vec3(a1.xy, h.z);
+ vec3 p3 = vec3(a1.zw, h.w);
+
+ vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
+ p0 *= norm.x;
+ p1 *= norm.y;
+ p2 *= norm.z;
+ p3 *= norm.w;
+
+ vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
+ m = m * m;
+ return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
+}
+
+highp float rand(vec2 co) {
+ highp float a = 12.9898;
+ highp float b = 78.233;
+ highp float c = 43758.5453;
+ highp float dt = dot(co.xy, vec2(a, b));
+ highp float sn = mod(dt, 3.14);
+ return fract(sin(sn) * c);
+}
+
+float noise(float v, vec2 _st) {
+ float f = rand(vec2(fract(v)));
+ return mix(rand(vec2(v) + 0.2), rand(vec2(v)), smoothstep(0.1, 1.0, f));
+}
+
+const float amplitude = 0.125;
+const float frequency = .1;
+const float PI = 3.14159;
+float Gaussian_h = 0.1;
+float Gaussian_sd = 0.09;
+float radius = 1.5;
+
+void main() {
+ vUv = uv;
+ vec3 pos = vec3(position);
+ value = aSize;
+ vec4 ecPosition = modelViewMatrix * vec4( pos, 1.0 );
+ float magnitude = distance(pos, vec3(0.0));
+
+ float noiseFreq = 5.5;
+ float noiseAmp = 1.55;
+ vec3 noisePos = vec3(pos.x * noiseFreq + u_time, pos.y, pos.z);
+
+ if(distance(u_mouse,pos.xy)<=0.9)
+ {
+ float vertexDistance = distance(u_mouse, pos.xy);
+ float height = ((Gaussian_h+0.05)* exp(-(0.5*pow((vertexDistance)/Gaussian_sd, 2.0))));
+ pos.z += sin((height));
+ }
+
+ float vertexDistance = distance(u_mouse, pos.xy);
+
+ pos.z += snoise(noisePos*0.6)*0.1;
+ pos.y += snoise(noisePos*0.3)*0.1;
+ pos.x += snoise(noisePos*0.2)*0.1;
+ transfer = snoise(noisePos*0.4);
+
+ gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(pos.xyz, 1.0);
+ gl_PointSize = aSize*(1.0/-ecPosition.z);
+}