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 Demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
</p>
<p align="center">(source: Ken Perlin)</p>

## Result

![Image1](https://github.com/QennyS/hw00-webgl-intro/blob/master/Demo.gif)

I used FBM noise which is adopted from Adam's implementation on Shadertoy and modified it with Iq's warping technique to create such deformed pattern.
As for the vertex shader, I simply make all vertices bounce from it's original position to a new position using sin function.

Live Link: https://qennys.github.io/hw00-webgl-intro/

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

this.positions = new Float32Array([
-2, -2, 0, 1,
2, -2, 0, 1,
2, 2, 0, 1,
-2, 2, 0, 1,
// back
2, -2, -4, 1,
2, 2, -4, 1,
-2, 2, -4, 1,
-2, -2, -4, 1,
// left
-2, -2, 0, 1,
-2, -2, -4, 1,
-2, 2, -4, 1,
-2, 2, 0, 1,
// right
2, -2, 0, 1,
2, -2, -4, 1,
2, 2, -4, 1,
2, 2, 0, 1,
// top
-2, 2, 0, 1,
2, 2, 0, 1,
2, 2, -4, 1,
-2, 2, -4, 1,
//bottom
-2, -2, -4, 1,
2, -2, -4, 1,
2, -2, 0, 1,
-2, -2, 0, 1
]);

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

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('create cube');
}
};

export default Cube;
30 changes: 28 additions & 2 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,29 @@ 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
Color: [255.0, 255.0, 255.0]
};

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

// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
Expand All @@ -64,22 +71,36 @@ function main() {
new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')),
]);

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

noise.setGeometryColor(vec4.fromValues(1.0, 1.0, 1.0, 1.0));

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

noise.setTime(currentTime);
currentTime++;

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, noise, [
icosphere,
// cube
// square,
]);


stats.end();

// Tell the browser to call `tick` again whenever it renders a new frame
Expand All @@ -98,6 +119,11 @@ function main() {

// Start the render loop
tick();

function setColor() {
noise.setGeometryColor(vec4.fromValues(controls.Color[0] / 255.0, controls.Color[1] / 255.0, controls.Color[2] / 255.0, 1.0));
}
}


main();
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(t: number) {
this.use();
if (this.unifTime !== -1) {
gl.uniform1f(this.unifTime, t);
}
}

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

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

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.

uniform float u_Time;

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; // Temporarily store the transformed vertex positions for use below
fs_Pos = modelposition;

vec4 newPos = u_Model * vec4(vs_Pos.xyz * 2.0 , 1);
vec4 interpPos = mix(modelposition, newPos, sin(u_Time * 0.01));

fs_LightVec = lightPos - modelposition; // Compute the direction in which the light source lies

gl_Position = u_ViewProj * interpPos;// gl_Position is a built-in variable of OpenGL which is
// used to render the final positions of the geometry's vertices
}
2 changes: 2 additions & 0 deletions src/shaders/lambert-frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ void main()
// Compute final shaded color
out_Col = vec4(diffuseColor.rgb * lightIntensity, diffuseColor.a);
}


Loading