Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added Images/tofugif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# HW 0: Noisy Planet Part 1 (Intro to Javascript and WebGL)

Live demo: https://jakelem.github.io/hw00-webgl-intro

<p align="center">
<img width="360" height="360" src="https://user-images.githubusercontent.com/1758825/132532354-e3a45402-e484-499e-bfa7-2d73b9f2c946.png">
<img src="Images/tofugif.gif" alt="drawing" width="350"/>
</p>
<p align="center">(source: Ken Perlin)</p>
<p align= "center">


For this project, I made a jiggly tofu. The cube vertices move along a sine wave, whose direction and amplitude are determined by the position of the mouse on the screen. The normals are offset based on a 3D FBM derivative, as described by IQ [in this article](https://www.iquilezles.org/www/articles/morenoise/morenoise.htm). FBM is also used to interpolate colors for the tofu albedo and also as a specular map.


## Objective
- Check that the tools and build configuration we will be using for the class works.
Expand Down
117 changes: 117 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
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;

color: vec4;
colors: Float32Array;
center: vec4;

constructor(center: vec3) {
super(); // Call the constructor of the super class. This is required.
this.center = vec4.fromValues(center[0], center[1], center[2], 1);
}

create() {

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.normals = new Float32Array([0, 0, -1, 0, // FRONT
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0,

0, 0, 1, 0, // BACK
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,

-1, 0, 0, 0, // LEFT
-1, 0, 0, 0,
-1, 0, 0, 0,
-1, 0, 0, 0,

1, 0, 0, 0, // RIGHT
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,

0, -1, 0, 0, // BOTTOM
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0,

0, 1, 0, 0, // TOP
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,

]);

this.positions = new Float32Array([-0.5, -0.5, 0, 1, // FRONT
0.5, -0.5, 0, 1,
0.5, 0.5, 0, 1,
-0.5, 0.5, 0, 1,

-0.5, -0.5, 1, 1, // BACK
0.5, -0.5, 1, 1,
0.5, 0.5, 1, 1,
-0.5, 0.5, 1, 1,

-0.5, -0.5, 0, 1, // LEFT
-0.5, -0.5, 1, 1,
-0.5, 0.5, 1, 1,
-0.5, 0.5, 0, 1,

0.5, -0.5, 0, 1, // RIGHT
0.5, -0.5, 1, 1,
0.5, 0.5, 1, 1,
0.5, 0.5, 0, 1,

-0.5, -0.5, 0, 1, // BOTTOM
-0.5, -0.5, 1, 1,
0.5, -0.5, 1, 1,
0.5, -0.5, 0, 1,

-0.5, 0.5, 0, 1, // TOP
-0.5, 0.5, 1, 1,
0.5, 0.5, 1, 1,
0.5, 0.5, 0, 1,
]);

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;
39 changes: 35 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {vec3} from 'gl-matrix';
import {vec2, vec3, vec4} from 'gl-matrix';
const Stats = require('stats-js');
import * as DAT from 'dat.gui';
import Icosphere from './geometry/Icosphere';
import Square from './geometry/Square';
import Cube from './geometry/Cube';
import OpenGLRenderer from './rendering/gl/OpenGLRenderer';
import Camera from './Camera';
import {setGL} from './globals';
Expand All @@ -13,17 +14,30 @@ import ShaderProgram, {Shader} from './rendering/gl/ShaderProgram';
const controls = {
tesselations: 5,
'Load Scene': loadScene, // A function pointer, essentially
'Color': [255,245,233],
'Secondary Color': [247,240,221],
'Use Numerical Normals' : true
};

let icosphere: Icosphere;
let square: Square;
let cube: Cube;
let time : number = 0;
let prevTesselations: number = 5;
let mouseX = 0;
let mouseY = 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 colArrayToVec4(colArr : number[]) : vec4 {
return vec4.fromValues(colArr[0] / 255.0, colArr[1] / 255.0, colArr[2] / 255.0, 1);
}

function main() {
Expand All @@ -38,6 +52,9 @@ function main() {
// Add controls to the gui
const gui = new DAT.GUI();
gui.add(controls, 'tesselations', 0, 8).step(1);
gui.addColor(controls, 'Color');
gui.addColor(controls, 'Secondary Color');
//gui.add(controls, 'Use Numerical Normals', true);
gui.add(controls, 'Load Scene');

// get canvas and webgl context
Expand All @@ -56,7 +73,7 @@ function main() {
const camera = new Camera(vec3.fromValues(0, 0, 5), vec3.fromValues(0, 0, 0));

const renderer = new OpenGLRenderer(canvas);
renderer.setClearColor(0.2, 0.2, 0.2, 1);
renderer.setClearColor(234 / 255.0,182 / 255.0, 118.0 / 255.0, 1);
gl.enable(gl.DEPTH_TEST);

const lambert = new ShaderProgram([
Expand All @@ -70,18 +87,27 @@ function main() {
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();
}
console.log("what");
lambert.setCamPos(vec4.fromValues(camera.controls.eye[0], camera.controls.eye[1], camera.controls.eye[2], 1));
lambert.setGeometryColor(colArrayToVec4(controls["Color"]));
lambert.setSecondaryColor(colArrayToVec4(controls["Secondary Color"]));
lambert.setNumericalNorm(controls["Use Numerical Normals"]);

lambert.setTime(time);
lambert.setMousePos(vec2.fromValues(mouseX, mouseY));
renderer.render(camera, lambert, [
icosphere,
// square,
cube,
]);
stats.end();

++time;
// Tell the browser to call `tick` again whenever it renders a new frame
requestAnimationFrame(tick);
}
Expand All @@ -100,4 +126,9 @@ function main() {
tick();
}

document.addEventListener( 'mousemove', function( event ) {
mouseX = event.pageX / window.innerWidth;
mouseY = (window.innerHeight - event.pageY) / window.innerHeight;
});

main();
2 changes: 0 additions & 2 deletions src/rendering/gl/OpenGLRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ class OpenGLRenderer {
render(camera: Camera, prog: ShaderProgram, drawables: Array<Drawable>) {
let model = mat4.create();
let viewProj = mat4.create();
let color = vec4.fromValues(1, 0, 0, 1);

mat4.identity(model);
mat4.multiply(viewProj, camera.projectionMatrix, camera.viewMatrix);
prog.setModelMatrix(model);
prog.setViewProjMatrix(viewProj);
prog.setGeometryColor(color);

for (let drawable of drawables) {
prog.draw(drawable);
Expand Down
66 changes: 65 additions & 1 deletion src/rendering/gl/ShaderProgram.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {vec4, mat4} from 'gl-matrix';
import {vec2, vec4, mat4} from 'gl-matrix';
import Drawable from './Drawable';
import {gl} from '../../globals';

Expand Down Expand Up @@ -28,7 +28,16 @@ class ShaderProgram {
unifModel: WebGLUniformLocation;
unifModelInvTr: WebGLUniformLocation;
unifViewProj: WebGLUniformLocation;
unifViewProjInv: WebGLUniformLocation;

unifColor: WebGLUniformLocation;
unifSecondaryColor: WebGLUniformLocation;

unifNumericalNorm: WebGLUniformLocation;

unifTime: WebGLUniformLocation;
unifMousePos: WebGLUniformLocation;
unifCamPos: WebGLUniformLocation;

constructor(shaders: Array<Shader>) {
this.prog = gl.createProgram();
Expand All @@ -47,7 +56,14 @@ class ShaderProgram {
this.unifModel = gl.getUniformLocation(this.prog, "u_Model");
this.unifModelInvTr = gl.getUniformLocation(this.prog, "u_ModelInvTr");
this.unifViewProj = gl.getUniformLocation(this.prog, "u_ViewProj");
this.unifViewProjInv = gl.getUniformLocation(this.prog, "u_ViewProjInv");
this.unifColor = gl.getUniformLocation(this.prog, "u_Color");
this.unifSecondaryColor = gl.getUniformLocation(this.prog, "u_SecondaryColor");
this.unifNumericalNorm = gl.getUniformLocation(this.prog, "u_NumericalNorm");
this.unifTime = gl.getUniformLocation(this.prog, "u_Time");
this.unifMousePos = gl.getUniformLocation(this.prog, "u_MousePos");
this.unifCamPos = gl.getUniformLocation(this.prog, "u_CameraPos");

}

use() {
Expand All @@ -74,7 +90,18 @@ class ShaderProgram {
setViewProjMatrix(vp: mat4) {
this.use();
if (this.unifViewProj !== -1) {
let viewprojinv: mat4 = mat4.create();
mat4.invert(viewprojinv, vp);

gl.uniformMatrix4fv(this.unifViewProj, false, vp);
gl.uniformMatrix4fv(this.unifViewProjInv, false, viewprojinv);
}
}

setInverseViewProjMatrix(vp: mat4) {
this.use();
if (this.unifViewProj !== -1) {
gl.uniformMatrix4fv(this.unifViewProjInv, false, vp);
}
}

Expand All @@ -85,6 +112,43 @@ class ShaderProgram {
}
}

setSecondaryColor(color: vec4) {
this.use();
if (this.unifSecondaryColor !== -1) {
gl.uniform4fv(this.unifSecondaryColor, color);
}
}

setNumericalNorm(n: boolean) {
this.use();
if (this.unifSecondaryColor !== -1) {
gl.uniform1i(this.unifNumericalNorm, Number(n));
}
}



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

setMousePos(pos: vec2) {
this.use();
if (this.unifColor !== -1) {
gl.uniform2fv(this.unifMousePos, pos);
}
}

setCamPos(pos: vec4) {
this.use();
if (this.unifColor !== -1) {
gl.uniform4fv(this.unifCamPos, pos);
}
}

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

Expand Down
Loading