diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json
new file mode 100644
index 0000000..f8b4888
--- /dev/null
+++ b/.vs/ProjectSettings.json
@@ -0,0 +1,3 @@
+{
+ "CurrentProjectSetting": null
+}
\ No newline at end of file
diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json
new file mode 100644
index 0000000..aee516a
--- /dev/null
+++ b/.vs/VSWorkspaceState.json
@@ -0,0 +1,12 @@
+{
+ "ExpandedNodes": [
+ "",
+ "\\src",
+ "\\src\\geometry",
+ "\\src\\rendering",
+ "\\src\\rendering\\gl",
+ "\\src\\shaders"
+ ],
+ "SelectedNode": "\\src\\shaders\\lambert-vert.glsl",
+ "PreviewInSolutionExplorer": false
+}
\ No newline at end of file
diff --git a/.vs/hw00-webgl-intro/v16/.suo b/.vs/hw00-webgl-intro/v16/.suo
new file mode 100644
index 0000000..3be2a0b
Binary files /dev/null and b/.vs/hw00-webgl-intro/v16/.suo differ
diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite
new file mode 100644
index 0000000..a486bab
Binary files /dev/null and b/.vs/slnx.sqlite differ
diff --git a/README.md b/README.md
index c636328..f7c879e 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,16 @@
# HW 0: Noisy Planet Part 1 (Intro to Javascript and WebGL)
+Description:
+I implemented the dat.gui.
+I used fractal brownian motion as the noise function to paint some procedural color on all geometries. Also, the fbm moves over time.
+The geometries are changing size as well as changing position over time.
+
+Screenshot:
+
+
+Live Demo Link:
+https://hli605.github.io/hw00-webgl-intro/
+
diff --git a/mySS.png b/mySS.png
new file mode 100644
index 0000000..70e1cf4
Binary files /dev/null and b/mySS.png differ
diff --git a/src/geometry/Cube.ts b/src/geometry/Cube.ts
new file mode 100644
index 0000000..24bf111
--- /dev/null
+++ b/src/geometry/Cube.ts
@@ -0,0 +1,134 @@
+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() {
+ // array of vertex indices
+ 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
+ ]);
+
+ // array of vertex normals
+ this.normals = new Float32Array([
+ 0, 0, 1, 0,
+ 0, 0, 1, 0,
+ 0, 0, 1, 0,
+ 0, 0, 1, 0,
+
+ 0, 0, -1, 0,
+ 0, 0, -1, 0,
+ 0, 0, -1, 0,
+ 0, 0, -1, 0,
+
+ 1, 0, 0, 0,
+ 1, 0, 0, 0,
+ 1, 0, 0, 0,
+ 1, 0, 0, 0,
+
+ -1, 0, 0, 0,
+ -1, 0, 0, 0,
+ -1, 0, 0, 0,
+ -1, 0, 0, 0,
+
+ 0, 1, 0, 0,
+ 0, 1, 0, 0,
+ 0, 1, 0, 0,
+ 0, 1, 0, 0,
+
+ 0, -1, 0, 0,
+ 0, -1, 0, 0,
+ 0, -1, 0, 0,
+ 0, -1, 0, 0
+ ]);
+
+ // array of vertex positions
+ this.positions = new Float32Array([
+ 0.5, 0.5, 0.5, 1.0,
+ 0.5, -0.5, 0.5, 1.0,
+ -0.5, -0.5, 0.5, 1.0,
+ -0.5, 0.5, 0.5, 1.0,
+
+ -0.5, 0.5, -0.5, 1.0,
+ -0.5, -0.5, -0.5, 1.0,
+ 0.5, -0.5, -0.5, 1.0,
+ 0.5, 0.5, -0.5, 1.0,
+
+ 0.5, 0.5, -0.5, 1.0,
+ 0.5, -0.5, -0.5, 1.0,
+ 0.5, -0.5, 0.5, 1.0,
+ 0.5, 0.5, 0.5, 1.0,
+
+ -0.5, 0.5, 0.5, 1.0,
+ -0.5, -0.5, 0.5, 1.0,
+ -0.5, -0.5, -0.5, 1.0,
+ -0.5, 0.5, -0.5, 1.0,
+
+ 0.5, 0.5, -0.5, 1.0,
+ 0.5, 0.5, 0.5, 1.0,
+ -0.5, 0.5, 0.5, 1.0,
+ -0.5, 0.5, -0.5, 1.0,
+
+ 0.5, -0.5, 0.5, 1.0,
+ 0.5, -0.5, -0.5, 1.0,
+ -0.5, -0.5, -0.5, 1.0,
+ -0.5, -0.5, 0.5, 1.0
+ ]);
+
+ for (let i = 0; i < this.positions.length; i++) {
+ if (i % 4 == 0) {
+ this.positions[i] += this.center[0];
+ }
+ else if (i % 4 == 1) {
+ this.positions[i] += this.center[1];
+ }
+ else if (i % 4 == 2) {
+ this.positions[i] += this.center[2];
+ }
+ }
+
+ 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;
\ No newline at end of file
diff --git a/src/main.ts b/src/main.ts
index 65a9461..0f09134 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,103 +1,132 @@
-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';
import Square from './geometry/Square';
+import Cube from './geometry/Cube';
import OpenGLRenderer from './rendering/gl/OpenGLRenderer';
import Camera from './Camera';
-import {setGL} from './globals';
-import ShaderProgram, {Shader} from './rendering/gl/ShaderProgram';
+import { setGL } from './globals';
+import ShaderProgram, { Shader } from './rendering/gl/ShaderProgram';
// 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
+ tesselations: 5,
+ 'Load Scene': loadScene, // A function pointer, essentially
+ Color: [0, 255, 0],
};
let icosphere: Icosphere;
let square: Square;
+let cube: Cube;
let prevTesselations: number = 5;
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();
+ icosphere = new Icosphere(vec3.fromValues(0, 3, 0), 1, controls.tesselations);
+ icosphere.create();
+ square = new Square(vec3.fromValues(0, 0, 0));
+ square.create();
+ cube = new Cube(vec3.fromValues(3, 0, 0));
+ cube.create();
}
function main() {
- // Initial display for framerate
- const stats = Stats();
- stats.setMode(0);
- stats.domElement.style.position = 'absolute';
- stats.domElement.style.left = '0px';
- stats.domElement.style.top = '0px';
- document.body.appendChild(stats.domElement);
-
- // Add controls to the gui
- const gui = new DAT.GUI();
- gui.add(controls, 'tesselations', 0, 8).step(1);
- gui.add(controls, 'Load Scene');
-
- // get canvas and webgl context
- const canvas = document.getElementById('canvas');
- const gl = canvas.getContext('webgl2');
- if (!gl) {
- alert('WebGL 2 not supported!');
- }
- // `setGL` is a function imported above which sets the value of `gl` in the `globals.ts` module.
- // Later, we can import `gl` from `globals.ts` to access it
- setGL(gl);
-
- // Initial call to load scene
- loadScene();
-
- 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);
- gl.enable(gl.DEPTH_TEST);
-
- const lambert = new ShaderProgram([
- new Shader(gl.VERTEX_SHADER, require('./shaders/lambert-vert.glsl')),
- new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')),
- ]);
-
- // This function will be called every frame
- function 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();
+ // Initial display for framerate
+ const stats = Stats();
+ stats.setMode(0);
+ stats.domElement.style.position = 'absolute';
+ stats.domElement.style.left = '0px';
+ stats.domElement.style.top = '0px';
+ document.body.appendChild(stats.domElement);
+
+ // Add controls to the gui
+ const gui = new DAT.GUI();
+ gui.add(controls, 'tesselations', 0, 8).step(1);
+ gui.add(controls, 'Load Scene');
+ gui.addColor(controls, 'Color').onChange(setAllGeometryColor);
+
+ // get canvas and webgl context
+ const canvas = document.getElementById('canvas');
+ const gl = canvas.getContext('webgl2');
+ if (!gl) {
+ alert('WebGL 2 not supported!');
}
- renderer.render(camera, lambert, [
- icosphere,
- // square,
+ // `setGL` is a function imported above which sets the value of `gl` in the `globals.ts` module.
+ // Later, we can import `gl` from `globals.ts` to access it
+ setGL(gl);
+
+ // Initial call to load scene
+ loadScene();
+
+ 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);
+ gl.enable(gl.DEPTH_TEST);
+
+ const lambert = new ShaderProgram([
+ new Shader(gl.VERTEX_SHADER, require('./shaders/lambert-vert.glsl')),
+ new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')),
]);
- stats.end();
+ lambert.setGeometryColor(vec4.fromValues(0, 1, 0, 1));
- // Tell the browser to call `tick` again whenever it renders a new frame
- requestAnimationFrame(tick);
- }
+ const custom = new ShaderProgram([
+ new Shader(gl.VERTEX_SHADER, require('./shaders/custom-vert.glsl')),
+ new Shader(gl.FRAGMENT_SHADER, require('./shaders/custom-frag.glsl')),
+ ]);
+ custom.setGeometryColor(vec4.fromValues(0, 1, 0, 1));
+
+ // This function will be called every frame
+ function 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();
+ }
+
+ // Render with custom shader
+ renderer.render(camera, custom, [
+ icosphere,
+ square,
+ cube,
+ ]);
+
+ // Render with Lambert shader
+ //renderer.render(camera, lambert, [
+ // icosphere,
+ // square,
+ // cube,
+ //]);
+
+ stats.end();
+
+ // Tell the browser to call `tick` again whenever it renders a new frame
+ requestAnimationFrame(tick);
+ }
+
+ window.addEventListener('resize', function () {
+ renderer.setSize(window.innerWidth, window.innerHeight);
+ camera.setAspectRatio(window.innerWidth / window.innerHeight);
+ camera.updateProjectionMatrix();
+ }, false);
- window.addEventListener('resize', function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.setAspectRatio(window.innerWidth / window.innerHeight);
camera.updateProjectionMatrix();
- }, false);
- renderer.setSize(window.innerWidth, window.innerHeight);
- camera.setAspectRatio(window.innerWidth / window.innerHeight);
- camera.updateProjectionMatrix();
+ // Start the render loop
+ tick();
- // Start the render loop
- tick();
+ // Help function
+ function setAllGeometryColor() {
+ lambert.setGeometryColor(vec4.fromValues(controls.Color[0] / 255.0, controls.Color[1] / 255.0, controls.Color[2] / 255.0, 1));
+ custom.setGeometryColor(vec4.fromValues(controls.Color[0] / 255.0, controls.Color[1] / 255.0, controls.Color[2] / 255.0, 1));
+ }
}
main();
diff --git a/src/rendering/gl/OpenGLRenderer.ts b/src/rendering/gl/OpenGLRenderer.ts
index 7e527c2..2e2e45d 100644
--- a/src/rendering/gl/OpenGLRenderer.ts
+++ b/src/rendering/gl/OpenGLRenderer.ts
@@ -1,42 +1,45 @@
-import {mat4, vec4} from 'gl-matrix';
+import { mat4, vec4 } from 'gl-matrix';
import Drawable from './Drawable';
import Camera from '../../Camera';
-import {gl} from '../../globals';
+import { gl } from '../../globals';
import ShaderProgram from './ShaderProgram';
// In this file, `gl` is accessible because it is imported above
class OpenGLRenderer {
- constructor(public canvas: HTMLCanvasElement) {
- }
-
- setClearColor(r: number, g: number, b: number, a: number) {
- gl.clearColor(r, g, b, a);
- }
-
- setSize(width: number, height: number) {
- this.canvas.width = width;
- this.canvas.height = height;
- }
-
- clear() {
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
- }
-
- render(camera: Camera, prog: ShaderProgram, drawables: Array) {
- 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);
+ time: number;
+
+ constructor(public canvas: HTMLCanvasElement) {
+ this.time = 0.0;
+ }
+
+ setClearColor(r: number, g: number, b: number, a: number) {
+ gl.clearColor(r, g, b, a);
+ }
+
+ setSize(width: number, height: number) {
+ this.canvas.width = width;
+ this.canvas.height = height;
+ }
+
+ clear() {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ }
+
+ render(camera: Camera, prog: ShaderProgram, drawables: Array) {
+ let model = mat4.create();
+ let viewProj = mat4.create();
+
+ mat4.identity(model);
+ mat4.multiply(viewProj, camera.projectionMatrix, camera.viewMatrix);
+ prog.setModelMatrix(model);
+ prog.setViewProjMatrix(viewProj);
+ prog.setTime(this.time);
+ this.time += 0.01;
+
+ for (let drawable of drawables) {
+ prog.draw(drawable);
+ }
}
- }
};
export default OpenGLRenderer;
diff --git a/src/rendering/gl/ShaderProgram.ts b/src/rendering/gl/ShaderProgram.ts
index 67fef40..c2f634e 100644
--- a/src/rendering/gl/ShaderProgram.ts
+++ b/src/rendering/gl/ShaderProgram.ts
@@ -1,109 +1,118 @@
-import {vec4, mat4} from 'gl-matrix';
+import { vec4, mat4 } from 'gl-matrix';
import Drawable from './Drawable';
-import {gl} from '../../globals';
+import { gl } from '../../globals';
var activeProgram: WebGLProgram = null;
export class Shader {
- shader: WebGLShader;
+ shader: WebGLShader;
- constructor(type: number, source: string) {
- this.shader = gl.createShader(type);
- gl.shaderSource(this.shader, source);
- gl.compileShader(this.shader);
+ constructor(type: number, source: string) {
+ this.shader = gl.createShader(type);
+ gl.shaderSource(this.shader, source);
+ gl.compileShader(this.shader);
- if (!gl.getShaderParameter(this.shader, gl.COMPILE_STATUS)) {
- throw gl.getShaderInfoLog(this.shader);
+ if (!gl.getShaderParameter(this.shader, gl.COMPILE_STATUS)) {
+ throw gl.getShaderInfoLog(this.shader);
+ }
}
- }
};
class ShaderProgram {
- prog: WebGLProgram;
-
- attrPos: number;
- attrNor: number;
- attrCol: number;
-
- unifModel: WebGLUniformLocation;
- unifModelInvTr: WebGLUniformLocation;
- unifViewProj: WebGLUniformLocation;
- unifColor: WebGLUniformLocation;
-
- constructor(shaders: Array) {
- this.prog = gl.createProgram();
-
- for (let shader of shaders) {
- gl.attachShader(this.prog, shader.shader);
- }
- gl.linkProgram(this.prog);
- if (!gl.getProgramParameter(this.prog, gl.LINK_STATUS)) {
- throw gl.getProgramInfoLog(this.prog);
+ prog: WebGLProgram;
+
+ attrPos: number;
+ attrNor: number;
+ attrCol: number;
+
+ unifModel: WebGLUniformLocation;
+ unifModelInvTr: WebGLUniformLocation;
+ unifViewProj: WebGLUniformLocation;
+ unifColor: WebGLUniformLocation;
+ unifTime: WebGLUniformLocation;
+
+ constructor(shaders: Array) {
+ this.prog = gl.createProgram();
+
+ for (let shader of shaders) {
+ gl.attachShader(this.prog, shader.shader);
+ }
+ gl.linkProgram(this.prog);
+ if (!gl.getProgramParameter(this.prog, gl.LINK_STATUS)) {
+ throw gl.getProgramInfoLog(this.prog);
+ }
+
+ this.attrPos = gl.getAttribLocation(this.prog, "vs_Pos");
+ this.attrNor = gl.getAttribLocation(this.prog, "vs_Nor");
+ this.attrCol = gl.getAttribLocation(this.prog, "vs_Col");
+ 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.unifColor = gl.getUniformLocation(this.prog, "u_Color");
+ this.unifTime = gl.getUniformLocation(this.prog, "u_Time");
}
- this.attrPos = gl.getAttribLocation(this.prog, "vs_Pos");
- this.attrNor = gl.getAttribLocation(this.prog, "vs_Nor");
- this.attrCol = gl.getAttribLocation(this.prog, "vs_Col");
- 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.unifColor = gl.getUniformLocation(this.prog, "u_Color");
- }
-
- use() {
- if (activeProgram !== this.prog) {
- gl.useProgram(this.prog);
- activeProgram = this.prog;
+ use() {
+ if (activeProgram !== this.prog) {
+ gl.useProgram(this.prog);
+ activeProgram = this.prog;
+ }
}
- }
- setModelMatrix(model: mat4) {
- this.use();
- if (this.unifModel !== -1) {
- gl.uniformMatrix4fv(this.unifModel, false, model);
+ setModelMatrix(model: mat4) {
+ this.use();
+ if (this.unifModel !== -1) {
+ gl.uniformMatrix4fv(this.unifModel, false, model);
+ }
+
+ if (this.unifModelInvTr !== -1) {
+ let modelinvtr: mat4 = mat4.create();
+ mat4.transpose(modelinvtr, model);
+ mat4.invert(modelinvtr, modelinvtr);
+ gl.uniformMatrix4fv(this.unifModelInvTr, false, modelinvtr);
+ }
}
- if (this.unifModelInvTr !== -1) {
- let modelinvtr: mat4 = mat4.create();
- mat4.transpose(modelinvtr, model);
- mat4.invert(modelinvtr, modelinvtr);
- gl.uniformMatrix4fv(this.unifModelInvTr, false, modelinvtr);
+ setViewProjMatrix(vp: mat4) {
+ this.use();
+ if (this.unifViewProj !== -1) {
+ gl.uniformMatrix4fv(this.unifViewProj, false, vp);
+ }
}
- }
- setViewProjMatrix(vp: mat4) {
- this.use();
- if (this.unifViewProj !== -1) {
- gl.uniformMatrix4fv(this.unifViewProj, false, vp);
+ setGeometryColor(color: vec4) {
+ this.use();
+ if (this.unifColor !== -1) {
+ gl.uniform4fv(this.unifColor, color);
+ }
}
- }
- setGeometryColor(color: vec4) {
- this.use();
- if (this.unifColor !== -1) {
- gl.uniform4fv(this.unifColor, color);
+ setTime(time: number) {
+ this.use();
+ if (this.unifTime !== -1) {
+ gl.uniform1f(this.unifTime, time);
+ }
}
- }
- draw(d: Drawable) {
- this.use();
+ draw(d: Drawable) {
+ this.use();
- if (this.attrPos != -1 && d.bindPos()) {
- gl.enableVertexAttribArray(this.attrPos);
- gl.vertexAttribPointer(this.attrPos, 4, gl.FLOAT, false, 0, 0);
- }
+ if (this.attrPos != -1 && d.bindPos()) {
+ gl.enableVertexAttribArray(this.attrPos);
+ gl.vertexAttribPointer(this.attrPos, 4, gl.FLOAT, false, 0, 0);
+ }
- if (this.attrNor != -1 && d.bindNor()) {
- gl.enableVertexAttribArray(this.attrNor);
- gl.vertexAttribPointer(this.attrNor, 4, gl.FLOAT, false, 0, 0);
- }
+ if (this.attrNor != -1 && d.bindNor()) {
+ gl.enableVertexAttribArray(this.attrNor);
+ gl.vertexAttribPointer(this.attrNor, 4, gl.FLOAT, false, 0, 0);
+ }
- d.bindIdx();
- gl.drawElements(d.drawMode(), d.elemCount(), gl.UNSIGNED_INT, 0);
+ d.bindIdx();
+ gl.drawElements(d.drawMode(), d.elemCount(), gl.UNSIGNED_INT, 0);
- if (this.attrPos != -1) gl.disableVertexAttribArray(this.attrPos);
- if (this.attrNor != -1) gl.disableVertexAttribArray(this.attrNor);
- }
+ if (this.attrPos != -1) gl.disableVertexAttribArray(this.attrPos);
+ if (this.attrNor != -1) gl.disableVertexAttribArray(this.attrNor);
+ }
};
export default ShaderProgram;
diff --git a/src/shaders/custom-frag.glsl b/src/shaders/custom-frag.glsl
new file mode 100644
index 0000000..bd7d6da
--- /dev/null
+++ b/src/shaders/custom-frag.glsl
@@ -0,0 +1,69 @@
+#version 300 es
+
+// This is a fragment shader. If you've opened this file first, please
+// open and read lambert.vert.glsl before reading on.
+// Unlike the vertex shader, the fragment shader actually does compute
+// the shading of geometry. For every pixel in your program's output
+// screen, the fragment shader is run for every bit of geometry that
+// particular pixel overlaps. By implicitly interpolating the position
+// data passed into the fragment shader by the vertex shader, the fragment shader
+// can compute what color to apply to its pixel based on things like vertex
+// position, light position, and vertex color.
+precision highp float;
+
+uniform vec4 u_Color; // The color with which to render this instance of geometry.
+uniform float u_Time;
+
+// These are the interpolated values out of the rasterizer, so you can't know
+// their specific values without knowing the vertices that contributed to them
+in vec4 fs_Nor;
+in vec4 fs_LightVec;
+in vec4 fs_Col;
+in vec4 fs_Pos;
+
+out vec4 out_Col; // This is the final output color that you will see on your
+ // screen for the pixel that is currently being processed.
+
+vec4 random(vec4 x){
+ return fract(sin((x * 50.0) + 35.0)) * x;
+}
+
+// Refer to a simple noise function online
+float noise(vec3 pos){
+ vec3 i = floor(pos);
+ vec3 f = fract(pos);
+ f = f * f * (3.0 - 2.0 * f);
+
+ vec4 a = i.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
+ vec4 k1 = random(a.xyxy);
+ vec4 k2 = random(k1.xyxy + a.zzww);
+ vec4 b = k2 + i.zzzz;
+ vec4 k3 = random(b);
+ vec4 k4 = random(b + 1.0);
+
+ vec4 o1 = fract(k3 * (1.0 / 41.0));
+ vec4 o2 = fract(k4 * (1.0 / 41.0));
+ vec4 o3 = o2 * f.z + o1 * (1.0 - f.z);
+ vec2 o4 = o3.yw * f.x + o3.xz * (1.0 - f.x);
+
+ return o4.y * f.y + o4.x * (1.0 - f.y);
+}
+
+float fbm(vec3 pos) {
+ float noiseOutput = 0.0;
+ float amplitude = 0.5;
+ for (int i = 0; i < 6; i++) {
+ noiseOutput += amplitude * noise(pos);
+ pos = 2.5 * pos + vec3(10, 20, 30);
+ amplitude *= 0.5;
+ }
+ return noiseOutput;
+}
+
+void main()
+{
+ vec3 color = vec3(1, 0.5, 0.3);
+ color = mix(color, u_Color.rgb, fbm(fs_Pos.xyz + vec3(u_Time)));
+
+ out_Col = vec4(color.rgb, 1);
+}
diff --git a/src/shaders/custom-vert.glsl b/src/shaders/custom-vert.glsl
new file mode 100644
index 0000000..9cf423d
--- /dev/null
+++ b/src/shaders/custom-vert.glsl
@@ -0,0 +1,57 @@
+#version 300 es
+
+//This is a vertex shader. While it is called a "shader" due to outdated conventions, this file
+//is used to apply matrix transformations to the arrays of vertex data passed to it.
+//Since this code is run on your GPU, each vertex is transformed simultaneously.
+//If it were run on your CPU, each vertex would have to be processed in a FOR loop, one at a time.
+//This simultaneous transformation allows your program to run much faster, especially when rendering
+//geometry with millions of vertices.
+
+uniform mat4 u_Model; // The matrix that defines the transformation of the
+ // object we're rendering. In this assignment,
+ // this will be the result of traversing your scene graph.
+
+uniform mat4 u_ModelInvTr; // The inverse transpose of the model matrix.
+ // This allows us to transform the object's normals properly
+ // if the object has been non-uniformly scaled.
+
+uniform mat4 u_ViewProj; // The matrix that defines the camera's transformation.
+ // We've written a static matrix for you to use for HW2,
+ // but in HW3 you'll have to generate one yourself
+
+uniform float u_Time;
+
+in vec4 vs_Pos; // The array of vertex positions passed to the shader
+
+in vec4 vs_Nor; // The array of vertex normals passed to the shader
+
+in vec4 vs_Col; // The array of vertex colors passed to the shader.
+
+out vec4 fs_Nor; // The array of normals that has been transformed by u_ModelInvTr. This is implicitly passed to the fragment shader.
+out vec4 fs_LightVec; // The direction in which our virtual light lies, relative to each vertex. This is implicitly passed to the fragment shader.
+out vec4 fs_Col; // The color of each vertex. This is implicitly passed to the fragment shader.
+out vec4 fs_Pos;
+
+const vec4 lightPos = vec4(5, 5, 3, 1); //The position of our virtual light, which is used to compute the shading of
+ //the geometry in the fragment shader.
+
+void main()
+{
+ fs_Col = vs_Col; // Pass the vertex colors to the fragment shader for interpolation
+
+ mat3 invTranspose = mat3(u_ModelInvTr);
+ fs_Nor = vec4(invTranspose * vec3(vs_Nor), 0); // Pass the vertex normals to the fragment shader for interpolation.
+ // Transform the geometry's normals by the inverse transpose of the
+ // model matrix. This is necessary to ensure the normals remain
+ // perpendicular to the surface after the surface is transformed by
+ // the model matrix.
+ vec4 modelposition = u_Model * vs_Pos;
+ fs_Pos = modelposition;
+
+ modelposition = abs(sin(u_Time)) * modelposition + 0.5 * cos(2.0 * u_Time);
+
+ fs_LightVec = lightPos - modelposition; // Compute the direction in which the light source lies
+
+ gl_Position = u_ViewProj * modelposition;// gl_Position is a built-in variable of OpenGL which is
+ // used to render the final positions of the geometry's vertices
+}