Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasDower committed Apr 18, 2023
1 parent cc5d82d commit 3ecf8e1
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 60 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# WebGLTemplateBoilerplate
A simple webpack template for WebGL projects that supports hot-reloading.
# Mandelbrot Set Visualisation

An interactive visualisation of the [Mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set)

* Hold-and-drag to pan the camera.
* Scroll wheel to zoom the camera.

## Getting Started

1. Clone this repo,
2. `npm install`,
3. `npm run dev`,
Expand Down
2 changes: 2 additions & 0 deletions dist/bundle.js

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions dist/bundle.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @license
* Copyright 2010-2022 Three.js Authors
* SPDX-License-Identifier: MIT
*/
2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Three.js TypeScript Tutorials by Sean Bradley : https://sbcode.net/threejs</title>
<title>Mandelbrot Set Visualisation</title>
<style>
body {
overflow: hidden;
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"name": "WebGLTemplate",
"name": "mandelbrot",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack serve --config ./src/webpack.dev.js",
"lint": "eslint --fix ./src/*.ts"
"lint": "eslint --fix ./src/*.ts",
"build": "webpack --config ./src/webpack.prod.js"
},
"keywords": [],
"author": "",
Expand Down
157 changes: 133 additions & 24 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,149 @@
import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 2;
const renderer = new THREE.WebGLRenderer({
antialias: false
});

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
wireframe: true
window.addEventListener('resize', function (e) {
renderer.setSize(window.innerWidth, window.innerHeight);
});

const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
const scene = new THREE.Scene();

window.addEventListener('resize', onWindowResize, false);
function onWindowResize (): void {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);

function animate (): void {
requestAnimationFrame(animate);
const uniforms = {
u_ratio: { value: window.innerWidth / window.innerHeight },
u_width: { value: 3.0 },
u_offset: { value: [0.0, 0.0] }
};

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
const material = new THREE.ShaderMaterial({
uniforms,
vertexShader: `
varying vec2 v_uv;
render();
}
void main() {
v_uv = uv;
gl_Position = vec4( position, 1.0 );
}
`,
fragmentShader: `
#define MAX_ITER 1000.0
uniform float u_ratio;
uniform float u_width;
uniform vec2 u_offset;
varying vec2 v_uv;
vec4 get_color(int i)
{
if (i > int(MAX_ITER))
{
return vec4(0.0, 0.0, 0.0, 1.0);
}
vec4 colors[16] = vec4[](
vec4(0.258, 0.118, 0.059, 1.0), // brown 3
vec4(0.098, 0.027, 0.102, 1.0), // dark violet
vec4(0.035, 0.004, 0.184, 1.0), // darkest blue
vec4(0.016, 0.016, 0.286, 1.0), // blue 5
vec4(0.000, 0.027, 0.392, 1.0), // blue 4
vec4(0.047, 0.173, 0.541, 1.0), // blue 3
vec4(0.094, 0.322, 0.694, 1.0), // blue 2
vec4(0.224, 0.490, 0.820, 1.0), // blue 1
vec4(0.525, 0.710, 0.898, 1.0), // blue 0
vec4(0.827, 0.925, 0.969, 1.0), // lightest blue
vec4(0.945, 0.914, 0.749, 1.0), // lightest yellow
vec4(0.973, 0.788, 0.373, 1.0), // light yellow
vec4(1.000, 0.667, 0.000, 1.0), // dirty yellow
vec4(0.800, 0.502, 0.000, 1.0), // brown 0
vec4(0.600, 0.341, 0.000, 1.0), // brown 1
vec4(0.416, 0.204, 0.012, 1.0) // brown 2
);
int k = int(mod(float(i), 16.0));
return colors[k];
}
vec4 mandelbrot(float x0, float y0)
{
float x = 0.0;
float y = 0.0;
float iteration = 0.0;
while (x*x + y*y <= float(1 << 16) && iteration <= MAX_ITER)
{
float xtemp = x*x - y*y + x0;
y = 2.0*x*y + y0;
x = xtemp;
iteration += 1.0;
}
if (iteration < MAX_ITER)
{
float log_zn = log(x*x + y*y) / 2.0;
float nu = log(log_zn / log(2.0)) / log(2.0);
iteration = iteration + 1.0 - nu;
}
int i0 = int(floor(iteration));
int i1 = int(floor(iteration + 1.0));
vec4 c0 = get_color(i0);
vec4 c1 = get_color(i1);
vec4 color = mix(c0, c1, mod(iteration, 1.0));
return color;
}
void main() {
vec2 scaled_uv = (v_uv - 0.5) * vec2(u_ratio, 1.0);
vec2 c = scaled_uv * u_width;
c += u_offset;
gl_FragColor = mandelbrot(c.x, c.y);
}
`
});

const quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2, 1, 1), material);
scene.add(quad);

const mouse = { x: 0.0, y: 0.0 };
let mouseDown = false;

document.addEventListener('mousemove', (e) => {
if (mouseDown) {
const deltaX = e.clientX - mouse.x;
const deltaY = e.clientY - mouse.y;
const percentageX = deltaX / window.innerWidth;
const percentageY = deltaY / window.innerHeight;
uniforms.u_offset.value[0] -= (window.innerWidth / window.innerHeight) * percentageX * uniforms.u_width.value;
uniforms.u_offset.value[1] += percentageY * uniforms.u_width.value;
}
mouse.y = e.clientY;
mouse.x = e.clientX;
});

document.addEventListener('mousedown', () => {
mouseDown = true;
});

document.addEventListener('mouseup', () => {
mouseDown = false;
});

document.addEventListener('wheel', (e) => {
uniforms.u_width.value *= (e.deltaY > 0 ? 1.1 : 0.9);
});

function animate (): void {
requestAnimationFrame(animate);

function render (): void {
uniforms.u_ratio.value = window.innerWidth / window.innerHeight;
renderer.render(scene, camera);
}

Expand Down
38 changes: 19 additions & 19 deletions src/webpack.common.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
const path = require('path')
const path = require('path');

module.exports = {
entry: './src/client.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../dist'),
},
}
entry: './src/client.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../dist')
}
};
20 changes: 10 additions & 10 deletions src/webpack.dev.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');

module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
static: {
directory: path.join(__dirname, '../dist'),
},
hot: true,
mode: 'development',
devtool: 'eval-source-map',
devServer: {
static: {
directory: path.join(__dirname, '../dist')
},
})
hot: true
}
});
9 changes: 9 additions & 0 deletions src/webpack.prod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
mode: 'production',
performance: {
hints: false
}
});

0 comments on commit 3ecf8e1

Please sign in to comment.