Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# HW 0: Noisy Planet Part 1 (Intro to Javascript and WebGL)

## Description of project
Six sides of a cube start very far out and come together to interlock in a cube shape, staying there for a few seconds, before clipping past each other and flying back out. This is achieved by using a tangent function to modify the position of the sides by their normal vector, as well as a sine wave that has the same period, to ensure the sides stay together in the middle for a little bit.

As the sides come closer and closer, they start white, but begin to rapidly develop spots of the selected color, as well as black, before transitioning into a psychedelic red-green-blue static. At the same time, fbm noise at a very high octave was used to create this black sort of staticky, oscillating effect when the cube is at a standstill.

https://ruthchu.github.io/hw00-webgl-intro/

![](images/blasting_off.png)
![](images/coming_together.png)
![](images/static_effect.png)

<p align="center">
<img width="360" height="360" src="https://user-images.githubusercontent.com/1758825/132532354-e3a45402-e484-499e-bfa7-2d73b9f2c946.png">
</p>
Expand Down
Binary file added images/blasting_off.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 images/coming_together.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 images/static_effect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import {vec3, vec4} from 'gl-matrix';
import Drawable from '../rendering/gl/Drawable';
import {gl} from '../globals';

class Cube extends Drawable {
indices: Uint32Array;
positions: Float32Array;
normals: Float32Array;
center: vec4;

constructor(center: vec3) {
super();
this.center = vec4.fromValues(center[0], center[1], center[2], 1);
}

create() {
this.positions = new Float32Array([
//faces positive x direction
1, -1, 1, 1,
1, 1, 1, 1,
1, 1, -1, 1,
1, -1, -1, 1,

//faces negative x direction
-1, 1, -1, 1,
-1, -1, -1, 1,
-1, -1, 1, 1,
-1, 1, 1, 1,

//faces positive y direction
-1, 1, -1, 1,
-1, 1, 1, 1,
1, 1, 1, 1,
1, 1, -1, 1,

//faces negative y direction
1, 1, -1, 1,
1, -1, -1, 1,
-1, -1, -1, 1,
-1, 1, -1, 1,

//faces positive z direction
-1, 1, 1, 1,
-1, -1, 1, 1,
1, -1, 1, 1,
1, 1, 1, 1,

//faces negative z direction
-1, -1, 1, 1,
-1, -1, -1, 1,
1, -1, -1, 1,
1, -1, 1, 1
]);

this.normals = new Float32Array([
//faces positive x direction
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,

//faces negative x direction
-1, 0, 0, 0,
-1, 0, 0, 0,
-1, 0, 0, 0,
-1, 0, 0, 0,

//faces positive y direction
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,

//faces negative y direction
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0,

//faces positive z direction
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,

//faces negative z direction
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0
]);

this.indices = new Uint32Array([
0, 1, 2, 0, 2, 3,
4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11,
12, 13, 14, 12, 14, 15,
16, 17, 18, 16, 18, 19,
20, 21, 22, 20, 22, 23
]);

this.generateIdx();
this.generatePos();
this.generateNor();

this.count = this.indices.length;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);

gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor);
gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW);

gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos);
gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW);

console.log(`Created cube`);
}
};

export default Cube;
2 changes: 1 addition & 1 deletion src/geometry/Icosphere.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,4 @@ class Icosphere extends Drawable {
}
};

export default Icosphere;
export default Icosphere;
58 changes: 53 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {vec3} from 'gl-matrix';
import {vec3, vec4} from 'gl-matrix';
const Stats = require('stats-js');
import * as DAT from 'dat.gui';
import Icosphere from './geometry/Icosphere';
Expand All @@ -7,23 +7,34 @@ import OpenGLRenderer from './rendering/gl/OpenGLRenderer';
import Camera from './Camera';
import {setGL} from './globals';
import ShaderProgram, {Shader} from './rendering/gl/ShaderProgram';
import Cube from './geometry/Cube';

// Define an object with application parameters and button callbacks
// This will be referred to by dat.GUI's functions that add GUI elements.
const controls = {
tesselations: 5,
'Load Scene': loadScene, // A function pointer, essentially
terrainFreq: 1,
cloudHeight: .9,
};

const palette = {
color: [ 163, 120, 191 ]
};

let icosphere: Icosphere;
let square: Square;
let prevTesselations: number = 5;
let cube: Cube;
let prevTesselations: number = 6;
let u_tick: number = 0.0;

function loadScene() {
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, controls.tesselations);
icosphere.create();
square = new Square(vec3.fromValues(0, 0, 0));
square.create();
//cube = new Cube(vec3.fromValues(0, 0, 0));
//cube.create();
}

function main() {
Expand All @@ -39,6 +50,9 @@ function main() {
const gui = new DAT.GUI();
gui.add(controls, 'tesselations', 0, 8).step(1);
gui.add(controls, 'Load Scene');
gui.add(controls, 'terrainFreq', 0, 2).step(.1);
gui.add(controls, 'cloudHeight', .6, 1.1).step(.05);
gui.addColor(palette, 'color');

// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
Expand All @@ -58,28 +72,62 @@ function main() {
const renderer = new OpenGLRenderer(canvas);
renderer.setClearColor(0.2, 0.2, 0.2, 1);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CW);

const lambert = new ShaderProgram([
new Shader(gl.VERTEX_SHADER, require('./shaders/lambert-vert.glsl')),
new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')),
]);

const perlin = new ShaderProgram([
new Shader(gl.VERTEX_SHADER, require('./shaders/perlin-vert.glsl')),
new Shader(gl.FRAGMENT_SHADER, require('./shaders/perlin-frag.glsl')),
])

const planet = new ShaderProgram([
new Shader(gl.VERTEX_SHADER, require('./shaders/planet-vert.glsl')),
new Shader(gl.FRAGMENT_SHADER, require('./shaders/planet-frag.glsl')),
])

const raymarch = new ShaderProgram([
new Shader(gl.VERTEX_SHADER, require('./shaders/raymarch-vert.glsl')),
new Shader(gl.FRAGMENT_SHADER, require('./shaders/raymarch-frag.glsl')),
])

// This function will be called every frame
function tick() {
u_tick++;
camera.update();
stats.begin();
gl.viewport(0, 0, window.innerWidth, window.innerHeight);

renderer.clear();
if(controls.tesselations != prevTesselations)
{
prevTesselations = controls.tesselations;
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations);
icosphere.create();
}
renderer.render(camera, lambert, [
renderer.render(camera, planet, [
icosphere,
// square,
]);
//square,
//cube,
], vec4.fromValues(palette.color[0] / 255.,
palette.color[1] / 255.,
palette.color[2] / 255., 1),
u_tick, controls.terrainFreq, controls.cloudHeight);
renderer.render(camera, raymarch, [
icosphere,
//square,
//cube,
], vec4.fromValues(palette.color[0] / 255.,
palette.color[1] / 255.,
palette.color[2] / 255., 1),
u_tick, controls.terrainFreq, controls.cloudHeight);

stats.end();

// Tell the browser to call `tick` again whenever it renders a new frame
Expand Down
11 changes: 9 additions & 2 deletions src/rendering/gl/OpenGLRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,23 @@ class OpenGLRenderer {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}

render(camera: Camera, prog: ShaderProgram, drawables: Array<Drawable>) {
render(camera: Camera, prog: ShaderProgram, drawables: Array<Drawable>,
u_color: vec4, u_time: number, u_terrain: number, u_cloud: number) {
let model = mat4.create();
let viewProj = mat4.create();
let color = vec4.fromValues(1, 0, 0, 1);
let time = u_time;
let color = u_color;
let terrain = u_terrain;
let cloud = u_cloud;

mat4.identity(model);
mat4.multiply(viewProj, camera.projectionMatrix, camera.viewMatrix);
prog.setModelMatrix(model);
prog.setViewProjMatrix(viewProj);
prog.setTime(time);
prog.setGeometryColor(color);
prog.setTerrain(terrain);
prog.setCloud(cloud);

for (let drawable of drawables) {
prog.draw(drawable);
Expand Down
27 changes: 27 additions & 0 deletions src/rendering/gl/ShaderProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class ShaderProgram {
unifModelInvTr: WebGLUniformLocation;
unifViewProj: WebGLUniformLocation;
unifColor: WebGLUniformLocation;
unifTime: WebGLUniformLocation;
unifTerrain: WebGLUniformLocation;
unifCloud: WebGLUniformLocation;

constructor(shaders: Array<Shader>) {
this.prog = gl.createProgram();
Expand All @@ -48,6 +51,9 @@ class ShaderProgram {
this.unifModelInvTr = gl.getUniformLocation(this.prog, "u_ModelInvTr");
this.unifViewProj = gl.getUniformLocation(this.prog, "u_ViewProj");
this.unifColor = gl.getUniformLocation(this.prog, "u_Color");
this.unifTime = gl.getUniformLocation(this.prog, "u_Time");
this.unifTerrain = gl.getUniformLocation(this.prog, "u_Terrain");
this.unifCloud = gl.getUniformLocation(this.prog, "u_Cloud");
}

use() {
Expand Down Expand Up @@ -77,6 +83,13 @@ class ShaderProgram {
gl.uniformMatrix4fv(this.unifViewProj, false, vp);
}
}

setTime(time: number) {
this.use();
if (this.unifTime !== -1) {
gl.uniform1f(this.unifTime, time);
}
}

setGeometryColor(color: vec4) {
this.use();
Expand All @@ -85,6 +98,20 @@ class ShaderProgram {
}
}

setTerrain(terrain: number) {
this.use();
if (this.unifColor !== -1) {
gl.uniform1f(this.unifTerrain, terrain);
}
}

setCloud(cloud: number) {
this.use();
if (this.unifColor !== -1) {
gl.uniform1f(this.unifCloud, cloud);
}
}

draw(d: Drawable) {
this.use();

Expand Down
Loading