Skip to content

Commit

Permalink
ok
Browse files Browse the repository at this point in the history
  • Loading branch information
jcponce committed Aug 14, 2024
1 parent b0a714d commit 1ab3c78
Show file tree
Hide file tree
Showing 11 changed files with 864 additions and 2 deletions.
67 changes: 67 additions & 0 deletions threejs/dodeahedron-fractal/extra.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as THREE from 'three';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';


// Setup Scene, Camera, Renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Postprocessing with Bloom effect
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);

const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
composer.addPass(bloomPass);

// Create Material and Line Geometry
const material = new THREE.LineBasicMaterial({ color: 0xffd700 }); // Golden color

// Set up the Golden Ratio Dragon Curve parameters
const goldenRatio = (1 + Math.sqrt(5)) / 2;
const r1 = Math.pow(1 / goldenRatio, 1 / goldenRatio);
const r2 = Math.pow(r1, 2);
const angle1 = Math.acos((1 + r1**2 - r1**4) / (2 * r1));
const angle2 = Math.acos((1 + r1**4 - r1**2) / (2 * r1**2));

function goldenDragon(x1, y1, x2, y2, turn, n, vertices) {
const dist = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
if (dist < 1 || n <= 0) {
vertices.push(new THREE.Vector3(x2, y2, 0));
return;
}

const angle = Math.atan2(y2 - y1, x2 - x1);
let px, py;
if (turn) {
px = x1 + dist * r1 * Math.cos(angle + angle1);
py = y1 + dist * r1 * Math.sin(angle + angle1);
} else {
px = x1 + dist * r2 * Math.cos(angle - angle2);
py = y1 + dist * r2 * Math.sin(angle - angle2);
}

goldenDragon(x1, y1, px, py, true, n - 1, vertices);
goldenDragon(px, py, x2, y2, false, n - 1, vertices);
}

// Setup the geometry to hold the vertices
const points = [];
goldenDragon(-5, -2, 15, -2, true, 10, points); // Adjust the recursion level as needed
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(geometry, material);
scene.add(line);

// Position the camera and animate
camera.position.z = 10;

function animate() {
requestAnimationFrame(animate);
composer.render();
}
animate();
55 changes: 55 additions & 0 deletions threejs/dodeahedron-fractal/getLayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Based upon Bobby Roe's Simple Particle System
* Watch the tutorial on YouTube: (https://youtu.be/h1UQdbuF204)
*/

import * as THREE from "three";

const loader = new THREE.TextureLoader();

function getSprite({ hasFog, color, opacity, path, pos, size }) {
const spriteMat = new THREE.SpriteMaterial({
color,
fog: hasFog,
map: loader.load(path),
transparent: true,
opacity,
});
spriteMat.color.offsetHSL(0, 0, Math.random() * 0.2 - 0.1);
const sprite = new THREE.Sprite(spriteMat);
sprite.position.set(pos.x, -pos.y, pos.z);
size += Math.random() - 0.5;
sprite.scale.set(size, size, size);
sprite.material.rotation = 0;
return sprite;
}

function getLayer({
hasFog = true,
hue = 0.0,
numSprites = 10,
opacity = 1,
path = "./img/rad-grad.png",
radius = 1,
sat = 0.5,
size = 1,
z = 0,
}) {
const layerGroup = new THREE.Group();
for (let i = 0; i < numSprites; i += 1) {
let angle = (i / numSprites) * Math.PI * 2;
const pos = new THREE.Vector3(
Math.cos(angle) * Math.random() * radius,
Math.sin(angle) * Math.random() * radius,
z + Math.random()
);
const length = new THREE.Vector3(pos.x, pos.y, 0).length();
// const hue = 0.0; // (0.9 - (radius - length) / radius) * 1;

let color = new THREE.Color().setHSL(hue, 1, sat);
const sprite = getSprite({ hasFog, color, opacity, path, pos, size });
layerGroup.add(sprite);
}
return layerGroup;
}
export default getLayer;
236 changes: 236 additions & 0 deletions threejs/dodeahedron-fractal/getParticleSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/**
* Based upon Bobby Roe's Simple Particle System
* Watch the tutorial on YouTube: (https://youtu.be/h1UQdbuF204)
*/

import * as THREE from 'three';

const _VS = `
uniform float pointMultiplier;
attribute float size;
attribute float angle;
attribute vec4 aColor;
varying vec4 vColor;
varying vec2 vAngle;
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
gl_PointSize = size * pointMultiplier / gl_Position.w;
vAngle = vec2(cos(angle), sin(angle));
vColor = aColor;
}`;

const _FS = `
uniform sampler2D diffuseTexture;
varying vec4 vColor;
varying vec2 vAngle;
void main() {
vec2 coords = (gl_PointCoord - 0.5) * mat2(vAngle.x, vAngle.y, -vAngle.y, vAngle.x) + 0.5;
gl_FragColor = texture2D(diffuseTexture, coords) * vColor;
}`;


function getLinearSpline(lerp) {

const points = [];
const _lerp = lerp;

function addPoint(t, d) {
points.push([t, d]);
}

function getValueAt(t) {
let p1 = 0;

for (let i = 0; i < points.length; i++) {
if (points[i][0] >= t) {
break;
}
p1 = i;
}

const p2 = Math.min(points.length - 1, p1 + 1);

if (p1 == p2) {
return points[p1][1];
}

return _lerp(
(t - points[p1][0]) / (
points[p2][0] - points[p1][0]),
points[p1][1], points[p2][1]);
}
return { addPoint, getValueAt };
}

function getParticleSystem(params) {
const { camera, emitter, parent, rate, texture } = params;
const uniforms = {
diffuseTexture: {
value: new THREE.TextureLoader().load(texture)
},
pointMultiplier: {
value: window.innerHeight / (2.0 * Math.tan(30.0 * Math.PI / 180.0))
}
};
const _material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: _VS,
fragmentShader: _FS,
//blending: THREE.AdditiveBlending,
depthTest: true,
depthWrite: false,
transparent: true,
vertexColors: true
});

let _particles = [];

const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
geometry.setAttribute('size', new THREE.Float32BufferAttribute([], 1));
geometry.setAttribute('aColor', new THREE.Float32BufferAttribute([], 4));
geometry.setAttribute('angle', new THREE.Float32BufferAttribute([], 1));

const _points = new THREE.Points(geometry, _material);

parent.add(_points);

const alphaSpline = getLinearSpline((t, a, b) => {
return a + t * (b - a);
});
alphaSpline.addPoint(0.0, 0.0);
alphaSpline.addPoint(0.6, 1.0);
alphaSpline.addPoint(1.0, 0.0);

const colorSpline = getLinearSpline((t, a, b) => {
const c = a.clone();
return c.lerp(b, t);
});
colorSpline.addPoint(0.0, new THREE.Color(0xffff00));
colorSpline.addPoint(0.0, new THREE.Color(0x00ff00));
colorSpline.addPoint(0.0, new THREE.Color(0x00ffff));
colorSpline.addPoint(1.0, new THREE.Color(0xffffff));

const sizeSpline = getLinearSpline((t, a, b) => {
return a + t * (b - a);
});
sizeSpline.addPoint(0.0, 0.0);
sizeSpline.addPoint(1.0, 1.0);
// max point size = 512; => console.log(ctx.getParameter(ctx.ALIASED_POINT_SIZE_RANGE));
const maxVelocity = 1.5;
const radius = 0.5;
const maxLife = 9.5;
const maxSize = 0.15;
let gdfsghk = 0.0;
function _AddParticles(timeElapsed) {
gdfsghk += timeElapsed;
const n = Math.floor(gdfsghk * rate);
gdfsghk -= n / rate;
for (let i = 0; i < n; i += 1) {
const life = (Math.random() * 0.75 + 0.25) * maxLife;
_particles.push({
position: new THREE.Vector3(
(Math.random() * 2 - 1) * radius,
(Math.random() * 2 - 1) * radius,
(Math.random() * 2 - 1) * radius).add(emitter.position),
size: (Math.random() * 0.5 + 0.5) * maxSize,
colour: new THREE.Color(),
alpha: 1.0,
life: life,
maxLife: life,
rotation: Math.random() * 2.0 * Math.PI,
rotationRate: Math.random() * 0.01 - 0.005,
velocity: new THREE.Vector3(
(Math.random() * 2 - 1) * radius * maxVelocity,
(Math.random() * 2 - 1) * radius * maxVelocity,
(Math.random() * 2 - 1) * radius * maxVelocity),
});
}
}

function _UpdateGeometry() {
const positions = [];
const sizes = [];
const colours = [];
const angles = [];

for (let p of _particles) {
positions.push(p.position.x, p.position.y, p.position.z);
colours.push(p.colour.r, p.colour.g, p.colour.b, p.alpha);
sizes.push(p.currentSize);
angles.push(p.rotation);
}

geometry.setAttribute(
'position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute(
'size', new THREE.Float32BufferAttribute(sizes, 1));
geometry.setAttribute(
'aColor', new THREE.Float32BufferAttribute(colours, 4));
geometry.setAttribute(
'angle', new THREE.Float32BufferAttribute(angles, 1));

geometry.attributes.position.needsUpdate = true;
geometry.attributes.size.needsUpdate = true;
geometry.attributes.aColor.needsUpdate = true;
geometry.attributes.angle.needsUpdate = true;
}
_UpdateGeometry();

function _UpdateParticles(timeElapsed) {
for (let p of _particles) {
p.life -= timeElapsed;
}

_particles = _particles.filter(p => {
return p.life > 0.0;
});

for (let p of _particles) {
const t = 1.0 - p.life / p.maxLife;
p.rotation += p.rotationRate;
p.alpha = alphaSpline.getValueAt(t);
p.currentSize = p.size * sizeSpline.getValueAt(t);
p.colour.copy(colorSpline.getValueAt(t));

p.position.add(p.velocity.clone().multiplyScalar(timeElapsed));

const drag = p.velocity.clone();
drag.multiplyScalar(timeElapsed * 0.1);
drag.x = Math.sign(p.velocity.x) * Math.min(Math.abs(drag.x), Math.abs(p.velocity.x));
drag.y = Math.sign(p.velocity.y) * Math.min(Math.abs(drag.y), Math.abs(p.velocity.y));
drag.z = Math.sign(p.velocity.z) * Math.min(Math.abs(drag.z), Math.abs(p.velocity.z));
p.velocity.sub(drag);
}

_particles.sort((a, b) => {
const d1 = camera.position.distanceTo(a.position);
const d2 = camera.position.distanceTo(b.position);

if (d1 > d2) {
return -1;
}
if (d1 < d2) {
return 1;
}
return 0;
});
}

function update(timeElapsed) {
_AddParticles(timeElapsed);
_UpdateParticles(timeElapsed);
_UpdateGeometry();
}
return { update };
}

export { getParticleSystem };
Binary file added threejs/dodeahedron-fractal/img/circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added threejs/dodeahedron-fractal/img/fire.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added threejs/dodeahedron-fractal/img/rad-grad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added threejs/dodeahedron-fractal/img/smoke.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 1ab3c78

Please sign in to comment.