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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
- Start learning Typescript and WebGL2
- Practice implementing noise

## Felicity's Submission
![demoImg](https://user-images.githubusercontent.com/59979404/133345919-207b6eb4-cc4d-41a9-9fd1-9aa101688039.PNG)

The fragment shader uses a colour palette, u_Time, and summed perlin to apply dynamic noise, and the vertex shader alters vertex y and z positions using sin and cos. The colour of the cube can be changed via the gui on the top right.

Link to demo: [https://feliyick.github.io/hw00-webgl-intro/](https://feliyick.github.io/hw00-webgl-intro/)

## Forking the Code
Rather than cloning the homework repository, please __fork__ the code into your own repository using the `Fork` button in the upper-right hand corner of the Github UI. This will enable you to have your own personal repository copy of the code, and let you make a live demo (described later in this document).

Expand Down
3,785 changes: 3,770 additions & 15 deletions package-lock.json

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
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(); // 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,
1, 0, 0, 0, // right
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
0, 1, 0, 0, // up
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
-1, 0, 0, 0, // left
-1, 0, 0, 0,
-1, 0, 0, 0,
-1, 0, 0, 0,
0, 0, -1, 0, // back
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0,
0, -1, 0, 0, // down
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0
]);
this.positions = new Float32Array([
-1, -1, 1, 1, // front face
1, -1, 1, 1,
1, 1, 1, 1,
-1, 1, 1, 1,
1, -1, 1, 1, // right face
1, -1, -1, 1,
1, 1, -1, 1,
1, 1, 1, 1,
-1, 1, 1, 1, // up face
1, 1, 1, 1,
1, 1, -1, 1,
-1, 1, -1, 1,
-1, -1, -1, 1, // left face
-1, -1, 1, 1,
-1, 1, 1, 1,
-1, 1, -1, 1,
-1, -1, -1, 1, // back face
1, -1, -1, 1,
1, 1, -1, 1,
-1, 1, -1, 1,
-1, -1, 1, 1, // down face
1, -1, 1, 1,
1, -1, -1, 1,
-1, -1, -1, 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;
52 changes: 48 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 {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,22 @@ import ShaderProgram, {Shader} from './rendering/gl/ShaderProgram';
const controls = {
tesselations: 5,
'Load Scene': loadScene, // A function pointer, essentially
palette: [242, 146, 146]
};

let icosphere: Icosphere;
let square: Square;
let cube: Cube;
let prevTesselations: number = 5;
let time: number = 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 +45,8 @@ function main() {
const gui = new DAT.GUI();
gui.add(controls, 'tesselations', 0, 8).step(1);
gui.add(controls, 'Load Scene');
let colourController = gui.addColor(controls, 'palette')


// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
Expand All @@ -56,14 +64,23 @@ 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(0.6, 0.78, 0.87, 1.0);
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')),
]);

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

// initial overlay colour
customNoise.setGeometryColor(vec4.fromValues(0.94, 0.57, 0.57, 1.0))


// This function will be called every frame
function tick() {
camera.update();
Expand All @@ -76,10 +93,37 @@ function main() {
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations);
icosphere.create();
}
renderer.render(camera, lambert, [
icosphere,

//lambert render
// colourController.onChange( function( colour ) {
// let col = vec4.fromValues(colour[0] / 255.0,
// colour[1] / 255.0,
// colour[2] / 255.0, 1)
// lambert.setGeometryColor(col)
// })
// lambert.setTime(time);
// time++;
// renderer.render(camera, lambert, [
// // icosphere,
// // square,
// cube
// ]);

//custom noise render
colourController.onChange( function( colour ) {
let col = vec4.fromValues(colour[0] / 255.0,
colour[1] / 255.0,
colour[2] / 255.0, 1)
customNoise.setGeometryColor(col)
})
customNoise.setTime(time);
time++;
renderer.render(camera, customNoise, [
// icosphere,
// square,
cube
]);

stats.end();

// Tell the browser to call `tick` again whenever it renders a new frame
Expand Down
4 changes: 2 additions & 2 deletions src/rendering/gl/OpenGLRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ 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);
// 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);
// prog.setGeometryColor(color);

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

constructor(shaders: Array<Shader>) {
this.prog = gl.createProgram();
Expand All @@ -48,6 +49,7 @@ 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")
}

use() {
Expand Down Expand Up @@ -85,6 +87,13 @@ class ShaderProgram {
}
}

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

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

Expand Down
89 changes: 89 additions & 0 deletions src/shaders/customNoise-frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#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 int 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.

vec3 random3 ( vec3 p ) {
return fract(sin(vec3(dot(p,vec3(127.1, 311.7, 288.99)),
dot(p,vec3(303.1, 183.3, 800.2)),
dot(p, vec3(420.69, 655.0,109.21))))
*43758.5453);
}

float surflet(vec3 p, vec3 gridPoint) {
vec3 t2 = abs(p - gridPoint);
vec3 t;
t.x = 1.f - 6.f * pow(t2.x, 5.f) + 15.f * pow(t2.x, 4.f) - 10.f * pow(t2.x, 3.f);
t.y = 1.f - 6.f * pow(t2.y, 5.f) + 15.f * pow(t2.y, 4.f) - 10.f * pow(t2.y, 3.f);
t.z = 1.f - 6.f * pow(t2.z, 5.f) + 15.f * pow(t2.z, 4.f) - 10.f * pow(t2.z, 3.f);

vec3 gradient = random3(gridPoint) * 2. - vec3(1.);

vec3 diff = p - gridPoint;
float height = dot(diff, gradient);
return height * t.x * t.y * t.z;
}


float summedPerlin(vec4 p)
{
float sum = 0.0;
for(int dx = 0; dx <= 1; ++dx) {
for (int dy = 0; dy <= 1; ++dy) {
for (int dz = 0; dz <= 1; ++dz) {
sum += surflet(vec3(p), floor(vec3(p)) + vec3(dx, dy, dz));
}
}
}

return sum;
}

const vec4 a = vec4(255.0, 136.0, 128.0, 255.0) / 255.0;
const vec4 b = vec4(214, 92, 11, 255.0) / 255.0;
const vec4 c = vec4(232, 168, 65, 255.0) / 255.0;
const vec4 d = vec4(84, 186, 173, 255.0) / 255.0;

vec4 palette(float t) {
return clamp(a + b * cos(2.0 * 3.14159 * (c * t + d)), 0.0, 1.0);
}

void main()
{
// Material base color (before shading)
vec4 diffuseColor = u_Color + palette(summedPerlin(fs_Pos * 3.0));

// Calculate the diffuse term for Lambert shading
float diffuseTerm = dot(normalize(fs_Nor), normalize(fs_LightVec));
// Avoid negative lighting values
// diffuseTerm = clamp(diffuseTerm, 0, 1);

float ambientTerm = 0.2;

float lightIntensity = max(diffuseTerm, 0.0); //Add a small float value to the color multiplier
//to simulate ambient lighting. This ensures that faces that are not
//lit by our point light are not completely black.
lightIntensity += ambientTerm;
// Compute final shaded color
out_Col = vec4(diffuseColor.rgb * lightIntensity, diffuseColor.a);
}
Loading