Skip to content

Commit

Permalink
ok
Browse files Browse the repository at this point in the history
  • Loading branch information
jcponce committed Aug 21, 2024
1 parent 6c14164 commit 7083d59
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 0 deletions.
25 changes: 25 additions & 0 deletions threejs/galaxy/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animated galaxy</title>
<link rel="stylesheet" href="./style.css">
</head>

<body>
<canvas class="webgl"></canvas>

<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.min.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
}
}
</script>
<script type="module" src="./script.js"></script>
</body>

</html>
202 changes: 202 additions & 0 deletions threejs/galaxy/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import GUI from 'three/addons/libs/lil-gui.module.min.js'

let galaxyVertexShader, galaxyFragmentShader;

/**
* Load shaders using fetch
*/
async function loadShaders() {
const vertexResponse = await fetch('./shaders/galaxy/vertex.glsl');
galaxyVertexShader = await vertexResponse.text();

const fragmentResponse = await fetch('./shaders/galaxy/fragment.glsl');
galaxyFragmentShader = await fragmentResponse.text();

// Initialize the scene after shaders are loaded
initializeScene();
}

function initializeScene() {
/**
* Base
*/
// Debug
const gui = new GUI()

// Canvas
const canvas = document.querySelector('canvas.webgl')

// Scene
const scene = new THREE.Scene()

/**
* Galaxy
*/
const parameters = {}
parameters.count = 200000
parameters.size = 0.005
parameters.radius = 5
parameters.branches = 3
parameters.spin = 1
parameters.randomness = 0.5
parameters.randomnessPower = 3
parameters.insideColor = '#ff6030'
parameters.outsideColor = '#1b3984'

let geometry = null
let material = null
let points = null

const generateGalaxy = () => {
if (points !== null) {
geometry.dispose()
material.dispose()
scene.remove(points)
}

/**
* Geometry
*/
geometry = new THREE.BufferGeometry()

const positions = new Float32Array(parameters.count * 3)
const colors = new Float32Array(parameters.count * 3)
const scales = new Float32Array(parameters.count * 1)

const insideColor = new THREE.Color(parameters.insideColor)
const outsideColor = new THREE.Color(parameters.outsideColor)

for (let i = 0; i < parameters.count; i++) {
const i3 = i * 3

// Position
const radius = Math.random() * parameters.radius

const branchAngle = (i % parameters.branches) / parameters.branches * Math.PI * 2

const randomX = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : - 1) * parameters.randomness * radius
const randomY = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : - 1) * parameters.randomness * radius
const randomZ = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : - 1) * parameters.randomness * radius

positions[i3] = Math.cos(branchAngle) * radius + randomX
positions[i3 + 1] = randomY
positions[i3 + 2] = Math.sin(branchAngle) * radius + randomZ

// Color
const mixedColor = insideColor.clone()
mixedColor.lerp(outsideColor, radius / parameters.radius)

colors[i3] = mixedColor.r
colors[i3 + 1] = mixedColor.g
colors[i3 + 2] = mixedColor.b

// Scales
scales[i] = Math.random();
}


geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3))
geometry.setAttribute('aScale', new THREE.BufferAttribute(scales, 1))

/**
* Material
*/
material = new THREE.ShaderMaterial({
depthWrite: false,
blending: THREE.AdditiveBlending,
vertexColors: true,
vertexShader: galaxyVertexShader,
fragmentShader: galaxyFragmentShader,
uniforms: {
uSize: { value: 8 * renderer.getPixelRatio() }
}
})

/**
* Points
*/
points = new THREE.Points(geometry, material)
scene.add(points)
}

gui.add(parameters, 'count').min(100).max(1000000).step(100).onFinishChange(generateGalaxy)
gui.add(parameters, 'radius').min(0.01).max(20).step(0.01).onFinishChange(generateGalaxy)
gui.add(parameters, 'branches').min(2).max(20).step(1).onFinishChange(generateGalaxy)
gui.add(parameters, 'randomness').min(0).max(2).step(0.001).onFinishChange(generateGalaxy)
gui.add(parameters, 'randomnessPower').min(1).max(10).step(0.001).onFinishChange(generateGalaxy)
gui.addColor(parameters, 'insideColor').onFinishChange(generateGalaxy)
gui.addColor(parameters, 'outsideColor').onFinishChange(generateGalaxy)

/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}

window.addEventListener('resize', () => {
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight

// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()

// Update renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})

/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.x = 3
camera.position.y = 3
camera.position.z = 3
scene.add(camera)

// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true

/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))

generateGalaxy() // I need to call this right after the Renderer

/**
* Animate
*/
const clock = new THREE.Clock()

const tick = () => {
const elapsedTime = clock.getElapsedTime()

// Update controls
controls.update()

// Render
renderer.render(scene, camera)

// Call tick again on the next frame
window.requestAnimationFrame(tick)
}

tick()
}

// Start loading shaders and then initialize the scene
loadShaders();
13 changes: 13 additions & 0 deletions threejs/galaxy/shaders/galaxy/fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
void main (){

float strength = distance(gl_PointCoord, vec2(0.5, 0.5));
//strength = step(0.5, strength);
strength = 2.0 * strength;
strength = 1.0 - strength;

vec3 color = vec3(strength);

gl_FragColor = vec4(color, 1.0);

//#include <colorspace_fragment>
}
15 changes: 15 additions & 0 deletions threejs/galaxy/shaders/galaxy/vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
uniform float uSize;

attribute float aScale;


void main(){
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
vec4 viewPosition = viewMatrix * modelPosition;
vec4 projectedPosition = projectionMatrix * viewPosition;
gl_Position = projectedPosition;

gl_PointSize = uSize * aScale;
gl_PointSize *= (1.0 / - viewPosition.z);

}
19 changes: 19 additions & 0 deletions threejs/galaxy/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
*
{
margin: 0;
padding: 0;
}

html,
body
{
overflow: hidden;
}

.webgl
{
position: fixed;
top: 0;
left: 0;
outline: none;
}

0 comments on commit 7083d59

Please sign in to comment.