Skip to content

Instantly share code, notes, and snippets.

@JoshOohAhhAi
Created October 12, 2024 07:40
Show Gist options
  • Save JoshOohAhhAi/1eb4eef5e86cd9ff9ea233aece44b913 to your computer and use it in GitHub Desktop.
Save JoshOohAhhAi/1eb4eef5e86cd9ff9ea233aece44b913 to your computer and use it in GitHub Desktop.
Unity 🌈
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/CopyShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/LuminosityHighPassShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/UnrealBloomPass.js"></script>
<script type="x-shader/x-vertex" id="vertex-shader">
uniform float time;
attribute vec3 customColor;
varying vec3 vColor;
// Simplex 4D Noise
// by Ian McEwan, Ashima Arts
//
vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;}
vec4 grad4(float j, vec4 ip){
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
vec4 p,s;
p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
s = vec4(lessThan(p, vec4(0.0)));
p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;
return p;
}
float snoise(vec4 v){
const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4
0.309016994374947451); // (sqrt(5) - 1)/4 F4
// First corner
vec4 i = floor(v + dot(v, C.yyyy) );
vec4 x0 = v - i + dot(i, C.xxxx);
// Other corners
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
vec4 i0;
vec3 isX = step( x0.yzw, x0.xxx );
vec3 isYZ = step( x0.zww, x0.yyz );
// i0.x = dot( isX, vec3( 1.0 ) );
i0.x = isX.x + isX.y + isX.z;
i0.yzw = 1.0 - isX;
// i0.y += dot( isYZ.xy, vec2( 1.0 ) );
i0.y += isYZ.x + isYZ.y;
i0.zw += 1.0 - isYZ.xy;
i0.z += isYZ.z;
i0.w += 1.0 - isYZ.z;
// i0 now contains the unique values 0,1,2,3 in each channel
vec4 i3 = clamp( i0, 0.0, 1.0 );
vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );
// x0 = x0 - 0.0 + 0.0 * C
vec4 x1 = x0 - i1 + 1.0 * C.xxxx;
vec4 x2 = x0 - i2 + 2.0 * C.xxxx;
vec4 x3 = x0 - i3 + 3.0 * C.xxxx;
vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;
// Permutations
i = mod(i, 289.0);
float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);
vec4 j1 = permute( permute( permute( permute (
i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
+ i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
+ i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
+ i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));
// Gradients
// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;
vec4 p0 = grad4(j0, ip);
vec4 p1 = grad4(j1.x, ip);
vec4 p2 = grad4(j1.y, ip);
vec4 p3 = grad4(j1.z, ip);
vec4 p4 = grad4(j1.w, ip);
// Normalise gradients
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;
p4 *= taylorInvSqrt(dot(p4,p4));
// Mix contributions from the five corners
vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);
m0 = m0 * m0;
m1 = m1 * m1;
return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
+ dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;
}
void main() {
vColor = customColor;
vec3 p = position;
float r = snoise(vec4(p*0.015, time*0.0005));
p.y += p.y*r*0.1;
p.x += p.x*r*0.1;
p.z += p.z*r*0.1;
vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
gl_PointSize = 10. * (100.0/-mvPosition.z);
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragment-shader">
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 0.1);
}
</script>
const params = {
exposure: 1,
bloomStrength: 0.87,
bloomThreshold: 0,
bloomRadius: 0.26
};
const { min, PI, sqrt, cos, sin, pow, floor } = Math;
const range = (n) =>
Array(n)
.fill(0)
.map((i, j) => i + j);
const sum = (arr) => arr.reduce((acc, cur) => acc + cur, 0);
const slicedSum = (arr, i) => sum(arr.slice(0, i));
const pointsOnSphere = (n) => {
const pts = [];
const inc = PI * (3 - sqrt(5));
const off = 2 / n;
range(n).forEach((i) => {
const y = i * off - 1 + off / 2;
const r = sqrt(1 - y * y);
const phi = i * inc;
const x = cos(phi) * r;
const z = sin(phi) * r;
pts.push([x, y, z]);
});
return pts;
};
const numMap = (value, sMin, sMax, dMin, dMax) => {
return dMin + ((value - sMin) / (sMax - sMin)) * (dMax - dMin);
};
const colArray = [0xed2225, 0xf99621, 0xf1eb1b, 0x0c9b49, 0x3954a5, 0x93298e];
colArray.reverse();
let camera, controls, scene, renderer, cloud, composer, bloomPass, meshPlanet;
const uniforms = {
time: { type: "f", value: 1.0 }
};
let { innerWidth, innerHeight } = window;
let canvasSize = min(innerWidth, innerHeight);
init();
animate();
function init() {
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(canvasSize, canvasSize);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(128, 90, 474);
controls = new THREE.OrbitControls(camera, renderer.domElement);
const ambientLight = new THREE.AmbientLight(0x666666);
scene.add(ambientLight);
const renderScene = new THREE.RenderPass(scene, camera);
bloomPass = new THREE.UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
1.5,
0.4,
0.85
);
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
composer = new THREE.EffectComposer(renderer);
composer.addPass(renderScene);
composer.addPass(bloomPass);
createObjects();
createGlobe();
window.addEventListener("resize", onWindowResize, false);
}
function onWindowResize() {
camera.aspect = 1;
camera.updateProjectionMatrix();
innerWidth = window.innerWidth;
innerHeight = window.innerHeight;
canvasSize = min(innerWidth, innerHeight);
composer.setSize(canvasSize, canvasSize);
}
function animate(time) {
uniforms.time.value = time;
meshPlanet.rotation.y -= 0.006;
requestAnimationFrame(animate);
render();
}
function render() {
composer.render();
}
function createObjects() {
const layers = range(6).map((i) => canvasSize * pow(2, i + 1));
layers.reverse();
const amount = sum(layers);
const positions = new Float32Array(amount * 3);
const colors = new Float32Array(amount * 3);
const vertex = new THREE.Vector3();
layers.forEach((layer, layerIndex) => {
const points = pointsOnSphere(layer);
points.forEach(([x, y, z], pointIndex) => {
const index = slicedSum(layers, layerIndex) + pointIndex;
const color = new THREE.Color(
colArray[floor(numMap(pointIndex, 0, layer, 0, colArray.length))]
);
const radius = 140 + numMap(layerIndex, 0, layers.length, 0, 120);
vertex.x = radius * x;
vertex.y = radius * y;
vertex.z = radius * z;
vertex.toArray(positions, index * 3);
color.toArray(colors, index * 3);
});
});
const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
geometry.setAttribute("customColor", new THREE.BufferAttribute(colors, 3));
const material = new THREE.ShaderMaterial({
uniforms,
vertexShader: document.querySelector("#vertex-shader").textContent,
fragmentShader: document.querySelector("#fragment-shader").textContent,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
cloud = new THREE.Points(geometry, material);
scene.add(cloud);
}
function createGlobe() {
const textureLoader = new THREE.TextureLoader();
const radius = 100;
const tilt = 0.409105177;
const materialNormalMap = new THREE.MeshPhongMaterial({
specular: 0x333333,
shininess: 1,
map: textureLoader.load("https://assets.codepen.io/3685267/earth.jpg"),
normalScale: new THREE.Vector2(0.85, -0.85)
});
const geometry = new THREE.SphereBufferGeometry(radius, 100, 50);
meshPlanet = new THREE.Mesh(geometry, materialNormalMap);
meshPlanet.rotation.y = 0;
meshPlanet.rotation.z = tilt;
scene.add(meshPlanet);
}
body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
background: #000;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment