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
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>

## Demo
![Demo](result.gif)

For the yellow flower, I used 3D perlin noise to animate the position along the normal in the vertex shader. I also caculated the distance for every animated pos and used the distance to lerp between the given color and white to create the effect that the center part of the flower looks brighter.

For the background, I use worley noise to create the effect.

Link: https://vivienldy.github.io/hw00-intro-base/

## Objective
- Check that the tools and build configuration we will be using for the class works.
- Start learning Typescript and WebGL2
Expand Down
4,086 changes: 4,066 additions & 20 deletions package-lock.json

Large diffs are not rendered by default.

Binary file added result.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
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(36);
let idx = 0;
for(let i = 0; i < 6; i++){
this.indices[idx++] = i*4;
this.indices[idx++] = i*4+1;
this.indices[idx++] = i*4+2;
this.indices[idx++] = i*4;
this.indices[idx++] = i*4+2;
this.indices[idx++] = i*4+3;
}
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,
-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, // top
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
0, -1, 0, 0, // bottom
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0]);
this.positions = new Float32Array([1, 1, 1, 1, // front
1, 0, 1, 1,
0, 0, 1, 1,
0, 1, 1, 1,
1, 1, 0, 1, // right
1, 0, 0, 1,
1, 0, 1, 1,
1, 1, 1, 1,
0, 1, 1, 1, // left
0, 0, 1, 1,
0, 0, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1, // back
0, 0, 0, 1,
1, 0, 0, 1,
1, 1, 0, 1,
1, 1, 0, 1, // top
1, 1, 1, 1,
0, 1, 1, 1,
0, 1, 0, 1,
1, 0, 1, 1, // bottom
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;
8 changes: 4 additions & 4 deletions src/geometry/Square.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class Square extends Drawable {
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0]);
this.positions = new Float32Array([-1, -1, 0, 1,
1, -1, 0, 1,
1, 1, 0, 1,
-1, 1, 0, 1]);
this.positions = new Float32Array([-25, -15, -6, 3,
25, -15, -6, 3,
25, 15, -6, 3,
-25, 15, -6, 3]);

this.generateIdx();
this.generatePos();
Expand Down
46 changes: 44 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {vec3} from 'gl-matrix';
import {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 @@ -17,13 +19,17 @@ const controls = {

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,10 @@ function main() {
const gui = new DAT.GUI();
gui.add(controls, 'tesselations', 0, 8).step(1);
gui.add(controls, 'Load Scene');
var palette = {
color: [ 255, 195, 75, 255 ], // RGB with alpha
};
gui.addColor(palette, 'color');

// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
Expand All @@ -63,9 +73,27 @@ 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(palette.color[0]/255.0, palette.color[1]/255.0,
palette.color[2]/255.0, palette.color[3]));

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

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

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

// This function will be called every frame
function tick() {
time = time + 1;
camera.update();
stats.begin();
gl.viewport(0, 0, window.innerWidth, window.innerHeight);
Expand All @@ -76,9 +104,23 @@ function main() {
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations);
icosphere.create();
}
renderer.render(camera, lambert, [
lambert.setGeometryColor(vec4.fromValues(palette.color[0]/255.0, palette.color[1]/255.0,
palette.color[2]/255.0, palette.color[3]));
customShader.setGeometryColor(vec4.fromValues(palette.color[0]/255.0, palette.color[1]/255.0,
palette.color[2]/255.0, palette.color[3]));
deformShader.setGeometryColor(vec4.fromValues(palette.color[0]/255.0, palette.color[1]/255.0,
palette.color[2]/255.0, palette.color[3]));
deformShader.setTime(time);
worleyShader.setTime(time);
renderer.render(camera, worleyShader, [
// icosphere,
square,
//cube
]);
renderer.render(camera, deformShader, [
icosphere,
// square,
//square
//cube
]);
stats.end();

Expand Down
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 @@ -82,6 +84,14 @@ class ShaderProgram {
this.use();
if (this.unifColor !== -1) {
gl.uniform4fv(this.unifColor, color);
// console.log(color[0]);
}
}

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

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

void main()
{
// Material base color (before shading)
vec4 diffuseColor = u_Color;
//vec4 animatedColor = vec4(u_Color.x * cos(float(u_Time) * 0.05), u_Color.y , u_Color.z , u_Color.a);

vec2 resolution = vec2(1225, 893);
vec2 uv = gl_FragCoord.xy / resolution;
vec2 pos = vec2(0.65,0.5) - uv;
pos.y /= resolution.x / resolution.y;
float dist = 1.0 / length(fs_Pos);
dist *= 0.01;
dist = pow(dist, 0.9) * 90.0;
vec4 col = mix(u_Color, vec4(1,1,1,1), 1.0 - dist);

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

float ambientTerm = 0.2;

float lightIntensity = diffuseTerm + ambientTerm; //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.

// Compute final shaded color
out_Col = vec4(col.rgb * lightIntensity, diffuseColor.a);
}
Loading