Skip to content
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@
<img width="360" height="360" src="https://user-images.githubusercontent.com/1758825/132532354-e3a45402-e484-499e-bfa7-2d73b9f2c946.png">
</p>
<p align="center">(source: Ken Perlin)</p>
## Name
David Li 13109274

## Description
Added Color selecter. Color is also modified by a very jank fbm noise in fragment shader. Vertex shader adjusts position of vertices based on trig functions.

Used Fbm noise to generate terrain with detailing done by Perlin. Created a temperature map by using 2d fbm, spreading outward from poles. Created a moisture map using fbm. These maps make use of bias and gain functions to adjust the terrain more favorably. Smoothstep is used to make the noise blend nicely. Fbm and a gain function were used to texture the oceans a bit. Biome/Color depends on whether value sampled at moisture map or temperature map reach a certain threshold, if this is the case, a different cosine color function is used for surpassing the temperature or moisture threshhold. There also exists a default cosine color function if neither threshold is met. The thresholds for temperature and moisture are modifiable attributes which can be adjusted to change the coldness and dryness of the planet. The cosine color functions also make use of stepping functions to generate steps of colors rather than a gradient. I also created clouds by rendering another sphere and using noise to alter the alpha value. The clouds can be toggled in controls. Lastly, a blinn phong is used to make the snowcaps whiter.

## Used Resourcess
https://blog.demofox.org/2012/09/24/bias-and-gain-are-your-friend/

http://dev.thi.ng/gradients/

Link: https://thecollegeboardofc.github.io/hw00-webgl-intro/

![Test Image 1](Ss1.png)
![Test Image 1](Ss2.png)
![Test Image 1](planet.PNG)

## Objective
- Check that the tools and build configuration we will be using for the class works.
Expand Down
Binary file added Ss1.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 Ss2.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 planet.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 93 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {vec3, vec4} from 'gl-matrix';
import Drawable from '../rendering/gl/Drawable';
import {gl} from '../globals';

class Cube extends Drawable {
buffer: ArrayBuffer;
indices: Uint32Array;
positions: Float32Array;
normals: Float32Array;
corner: vec4;

constructor(corner: vec3, public length: number) {
super();
this.corner = vec4.fromValues(corner[0], corner[1], corner[2], 1);
}

create() {
this.positions = new Float32Array (
// front 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,
// right fac
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,
// top face
1, 1, 1, 1,
-1, 1, 1, 1,
-1, 1, -1, 1,
1, 1, -1, 1,
// bottom face
1, -1, 1, 1,
-1, -1, 1, 1,
-1, -1, -1, 1,
1, -1, -1, 1]);

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.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.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);
}
};

export default Cube;
1 change: 1 addition & 0 deletions src/geometry/Square.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Square extends Drawable {
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);
Expand Down
58 changes: 54 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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 @@ -11,19 +12,32 @@ 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,
tesselations: 6,
temperature: .5,
moisture: .5,
clouds: 0,
'Load Scene': loadScene, // A function pointer, essentially
};
var palette = {
color: [ 0, 128, 255 ], // RGB array
};

let icosphere: Icosphere;
let square: Square;
let prevTesselations: number = 5;

let cube: Cube;
let date: Date;
let time = 0.0;
function loadScene() {
date = new Date();
time = date.getTime();
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), 1);
cube.create()

}

function main() {
Expand All @@ -38,7 +52,12 @@ function main() {
// Add controls to the gui
const gui = new DAT.GUI();
gui.add(controls, 'tesselations', 0, 8).step(1);
gui.add(controls, 'temperature', 0., 1.).step(.1);
gui.add(controls, 'moisture', 0., 1.).step(.1);
gui.add(controls, 'clouds', 0, 1).step(1);

gui.add(controls, 'Load Scene');
gui.addColor(palette, 'color');

// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
Expand All @@ -58,12 +77,21 @@ function main() {
const renderer = new OpenGLRenderer(canvas);
renderer.setClearColor(0.2, 0.2, 0.2, 1);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.CULL_FACE);
gl.frontFace(gl.CW);

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 cloud = new ShaderProgram([
new Shader(gl.VERTEX_SHADER, require('./shaders/fbm-vert.glsl')),
new Shader(gl.FRAGMENT_SHADER, require('./shaders/fbm-frag.glsl')),
]);

// This function will be called every frame
function tick() {
camera.update();
Expand All @@ -76,10 +104,32 @@ function main() {
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations);
icosphere.create();
}
let newDate: Date = new Date();
let tickRate = newDate.getTime() - time;
let temp = controls.temperature;
let moist = controls.moisture;

let colorVec = vec3.fromValues(palette.color[0] / 255.0, palette.color[1] / 255.0, palette.color[2] / 255.0);
renderer.render(camera, lambert, [
icosphere,
// square,
]);
],
colorVec,
tickRate / 100.0,
temp,
moist,
);

if (controls.clouds > .5) {
renderer.render(camera, cloud, [
icosphere,
],
colorVec,
tickRate / 100.0,
temp,
moist,
);
}

stats.end();

// Tell the browser to call `tick` again whenever it renders a new frame
Expand Down
13 changes: 8 additions & 5 deletions src/rendering/gl/OpenGLRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {mat4, vec4} from 'gl-matrix';
import {mat4, vec4, vec3} from 'gl-matrix';
import Drawable from './Drawable';
import Camera from '../../Camera';
import {gl} from '../../globals';
Expand All @@ -22,16 +22,19 @@ class OpenGLRenderer {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}

render(camera: Camera, prog: ShaderProgram, drawables: Array<Drawable>) {
render(camera: Camera, prog: ShaderProgram, drawables: Array<Drawable>, color: vec3, tickRate: number, temp: number, moist: number) {
let model = mat4.create();
let viewProj = mat4.create();
let color = vec4.fromValues(1, 0, 0, 1);

//let color = vec4.fromValues(1, 0, 0, 1);
let colour = vec4.fromValues(color[0], color[1], color[2], 1);
mat4.identity(model);
mat4.multiply(viewProj, camera.projectionMatrix, camera.viewMatrix);
prog.setModelMatrix(model);
prog.setViewProjMatrix(viewProj);
prog.setGeometryColor(color);
prog.setGeometryColor(colour);
prog.setTick(tickRate);
prog.setMoisture(moist);
prog.setTempearture(temp);

for (let drawable of drawables) {
prog.draw(drawable);
Expand Down
35 changes: 31 additions & 4 deletions src/rendering/gl/ShaderProgram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class ShaderProgram {
attrNor: number;
attrCol: number;

unifTemperature: WebGLUniformLocation;
unifMoisture: WebGLUniformLocation;
unifTick: WebGLUniformLocation;
unifModel: WebGLUniformLocation;
unifModelInvTr: WebGLUniformLocation;
unifViewProj: WebGLUniformLocation;
Expand All @@ -44,10 +47,13 @@ class ShaderProgram {
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.unifTick = gl.getUniformLocation(this.prog, "u_Tick");
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.unifTemperature = gl.getUniformLocation(this.prog, "u_Temp");
this.unifMoisture = gl.getUniformLocation(this.prog, "u_Moist");
}

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

setTick(tickRate: number) {
this.use();
if (this.unifTick !== -1) {
gl.uniform1f(this.unifTick, tickRate);
}
}

setTempearture(temperature: number) {
this.use();
if (this.unifTemperature !== -1) {
gl.uniform1f(this.unifTemperature, temperature);
}
}

setMoisture(moisture: number) {
this.use();
if (this.unifMoisture !== -1) {
gl.uniform1f(this.unifMoisture, moisture);
}
}

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

Expand Down
Loading