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 .DS_Store
Binary file not shown.
Binary file added 1.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 2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# HW 0: Intro to Javascript and WebGL


## Description
- Implemented the fragment shader that based on Perlin3d
- Implemented the vertex shader uses a trigonometric function to non-uniformly modify cube's vertex positions over time

## LiveDemo
https://yuz796.github.io/hw00-intro-base/
![](1.png)
![](2.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
4,086 changes: 4,066 additions & 20 deletions package-lock.json

Large diffs are not rendered by default.

Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/geometry/.DS_Store
Binary file not shown.
116 changes: 116 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
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,

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, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 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([1, 1, 1, 1,
1, 0, 1, 1,
0, 0, 1, 1,
0, 1, 1, 1,

1, 1, 0, 1,
1, 0, 0, 1,
1, 0, 1, 1,

1, 1, 1, 1,

0, 1, 1, 1,
0, 0, 1, 1,
0, 0, 0, 1,
0, 1, 0, 1,

0, 1, 0, 1,
0, 0, 0, 1,
1, 0, 0, 1,
1, 1, 0, 1,

1, 1, 0, 1,
1, 1, 1, 1,
0, 1, 1, 1,
0, 1, 0, 1,

1, 0, 1, 1,
1, 0, 0, 1,
0, 0, 0, 1,
0, 0 ,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;
56 changes: 50 additions & 6 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,31 @@ 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:[0, 1, 0, 1],
shaders: 0,
'Load Scene': loadScene // A function pointer, essentially
};

let icosphere: Icosphere;
let square: Square;
let cube: Cube;
let prevTesselations: number = 5;
let prevColor: number[] = [1, 0, 0, 1];
let starttime: number = Date.now();

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 @@ -38,7 +46,10 @@ 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.add(controls, 'shaders', {Lambert: 0, Custom: 1});
gui.add(controls, 'Load Scene');


// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
Expand All @@ -52,6 +63,7 @@ function main() {

// Initial call to load scene
loadScene();
prevColor = [0, 1, 0, 0.3];

const camera = new Camera(vec3.fromValues(0, 0, 5), vec3.fromValues(0, 0, 0));

Expand All @@ -63,6 +75,15 @@ function main() {
new Shader(gl.VERTEX_SHADER, require('./shaders/lambert-vert.glsl')),
new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')),
]);
//lambert.setGeometryColor(vec4.fromValues(controls.color[0]/255.0, controls.color[1]/255.0, controls.color[2]/255.0, controls.color[3]));

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(controls.color[0]/255.0, controls.color[1]/255.0, controls.color[2]/255.0, controls.color[3]));



// This function will be called every frame
function tick() {
Expand All @@ -76,10 +97,32 @@ function main() {
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations);
icosphere.create();
}
renderer.render(camera, lambert, [
icosphere,
// square,
]);
//prevColor = controls.color;

if(controls.color != prevColor){
prevColor = controls.color;
lambert.setGeometryColor(vec4.fromValues(controls.color[0]/255.0, controls.color[1]/255.0, controls.color[2]/255.0, controls.color[3]));
custom.setGeometryColor(vec4.fromValues(controls.color[0]/255.0, controls.color[1]/255.0, controls.color[2]/255.0, controls.color[3]));
}

console.log(Date.now() - starttime);
lambert.setTime(Date.now() - starttime);
custom.setTime(Date.now() - starttime);
if(controls.shaders == 0){
renderer.render(camera, lambert, [
//icosphere,
//square,
cube
]);
}else{
renderer.render(camera, custom, [
// icosphere,
// square,
cube,
]);
}


stats.end();

// Tell the browser to call `tick` again whenever it renders a new frame
Expand All @@ -101,3 +144,4 @@ function main() {
}

main();

Binary file added src/rendering/.DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion src/rendering/gl/OpenGLRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class OpenGLRenderer {
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
10 changes: 10 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,14 @@ class ShaderProgram {
}
}

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


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

Expand Down
Binary file added src/shaders/.DS_Store
Binary file not shown.
88 changes: 88 additions & 0 deletions src/shaders/custom-frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#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_Pos;
in vec4 fs_Nor;
in vec4 fs_LightVec;
in vec4 fs_Col;

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 ) {
float x = fract(sin((dot(p, vec3(127.1,311.7,191.999)))) * 43758.5453);
float y = fract(sin((dot(p, vec3(269.5,183.3,154.645)))) * 43758.5453);
float z = fract(sin((dot(p, vec3(420.6,631.2,183.453)))) * 43758.5453);

return vec3(x, y, z);
}


float surflet3D(vec3 p, vec3 gridPoint) {
// Compute the distance between p and the grid point along each axis, and warp it with a
// quintic function so we can smooth our cells
vec3 t2 = abs(p - gridPoint);

vec3 poweroffive = vec3(t2.x * t2.x * t2.x * t2.x * t2.x, t2.y * t2.y * t2.y * t2.y * t2.y, t2.z * t2.z * t2.z * t2.z * t2.z);
vec3 poweroffour = vec3(t2.x * t2.x * t2.x * t2.x, t2.y * t2.y * t2.y * t2.y , t2.z * t2.z * t2.z * t2.z );
vec3 powerofthree = vec3(t2.x * t2.x * t2.x, t2.y * t2.y * t2.y, t2.z * t2.z * t2.z);


vec3 t = vec3(1.f) - 6.f * poweroffive + 15.f * poweroffour - 10.f * powerofthree;
// Get the random vector for the grid point (assume we wrote a function random2
// that returns a vec2 in the range [0, 1])
vec3 gradient = random3(gridPoint) * 2.f - vec3(1.f, 1.f, 1.f);
// Get the vector from the grid point to P
vec3 diff = p - gridPoint;
// Get the value of our height field by dotting grid->P with our gradient
float height = dot(diff, gradient);
// Scale our height field (i.e. reduce it) by our polynomial falloff function
return height * t.x * t.y * t.z;
}
//
float perlin3D(vec3 p) {
float surfletSum = 0.f;
// Iterate over the four integer corners surrounding uv
for(int dx = 0; dx <= 1; ++dx) {
for(int dy = 0; dy <= 1; ++dy) {
for(int dz = 0; dz <= 1; ++dz) {
surfletSum += surflet3D(p, (floor(p) + vec3(dx, dy, dz)));
}
}
}
return surfletSum;
}


void main()
{
vec3 pos = fs_Pos.xyz;
vec3 q = vec3(0.3, 0.4, 0.5);
float rand = perlin3D(pos);

float r = cos(0.0001 * u_Time + rand) / 2.f + 0.3 * sin(fs_Pos.x * fs_Pos.y) + 0.7;
float g = sin(0.0010 * u_Time + rand) / 3.f + 0.3 * cos(fs_Pos.y) + 0.7;
float b = sin(0.0016 * u_Time + rand) / 2.f + 0.4 * sin(fs_Pos.z) + 0.7;

vec4 color_final = vec4(r, g, b, 1.0);
out_Col = color_final;

}

Loading