Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a4de72e
Changed code to draw a square
ndevlin Sep 12, 2021
53c92a9
Change to test for update
ndevlin Sep 12, 2021
b476544
Changed bg color to test
ndevlin Sep 12, 2021
8889ebb
Changed clear color to test
ndevlin Sep 13, 2021
1c92ee9
Changed clear color again for testing
ndevlin Sep 13, 2021
14b50f6
Added comment to update for testing
ndevlin Sep 13, 2021
2a6cf1e
Added a Cube class as a square to start with
ndevlin Sep 13, 2021
0366189
Successfully moved center of cube(currently still a square)
ndevlin Sep 13, 2021
39f34a5
Got cube to render. Normals not working properly
ndevlin Sep 13, 2021
89a351a
Added color, turned cube green
ndevlin Sep 13, 2021
b2ba266
Turned Cube blue
ndevlin Sep 13, 2021
6deb4df
Successfully rendering selected color from GUI
ndevlin Sep 13, 2021
6a08112
Renamed some variables
ndevlin Sep 13, 2021
d41a644
Added custom shaders
ndevlin Sep 13, 2021
382cf26
Correctly importing position values
ndevlin Sep 14, 2021
8497bce
Got 2D FBM working
ndevlin Sep 14, 2021
071be14
A form of 3D FBM is working
ndevlin Sep 14, 2021
e947c33
Got trilinear interpolation working
ndevlin Sep 14, 2021
d11d657
Changed 3D noise function
ndevlin Sep 14, 2021
768035a
Added time framework and debugging configuration
ndevlin Sep 14, 2021
2045139
Time successfully coming into shader
ndevlin Sep 14, 2021
6783cc5
Got time-varying trigonometric vertex shader working
ndevlin Sep 14, 2021
f121f15
Have a multi-colored cube
ndevlin Sep 15, 2021
d5a33a7
Have color changing in interesting ways
ndevlin Sep 15, 2021
ccb8743
Corrected issue with normals
ndevlin Sep 15, 2021
5f8307b
Changed frag shader, removed comments
ndevlin Sep 15, 2021
7c558c5
Added comments, cleaned up code
ndevlin Sep 15, 2021
4748aa6
Added ReadMe
ndevlin Sep 15, 2021
f1fe554
Added ScreenShot
ndevlin Sep 15, 2021
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
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:5660/",
"webRoot": "${workspaceFolder}"
}
]
}
Binary file added NoisyPlanetScreenShot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 13 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,18 @@
# HW 0: Noisy Planet Part 1 (Intro to Javascript and WebGL)
# Noisy Planet

<p align="center">
<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>
## Details
- Created by Nathan Devlin, based on code by Adam Mally
- Written in TypeScript
- Renders a cube and an icosphere.
- Allows the user to modify the base color of the objects and the number of subdivisions of the icosphere
- Utilizes a fractal brownian motion fragment shader to give the objects an interesting coloring
- Utilizes a time-based sinusoidal function to undulate the objects in an organic-looking way

## Objective
- Check that the tools and build configuration we will be using for the class works.
- Start learning Typescript and WebGL2
- Practice implementing noise
## Live Demo
View a live WebGL Demo here!:
https://ndevlin.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).

## Running the Code
## ScreenShot:
![](NoisyPlanetScreenShot.png)

1. [Install Node.js](https://nodejs.org/en/download/). Node.js is a JavaScript runtime. It basically allows you to run JavaScript when not in a browser. For our purposes, this is not necessary. The important part is that with it comes `npm`, the Node Package Manager. This allows us to easily declare and install external dependencies such as [dat.GUI](https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage), and [glMatrix](http://glmatrix.net/).

2. Using a command terminal, run `npm install` in the root directory of your project. This will download all of those dependencies.

3. Do either of the following (but we highly recommend the first one for reasons we will explain later).

a. Run `npm start` and then go to `localhost:5660` in your web browser

b. Run `npm run build` and then go open `dist/index.html` in your web browser

## Module Bundling
One of the most important dependencies of our projects is [Webpack](https://webpack.js.org/concepts/). Webpack is a module bundler which allows us to write code in separate files and use `import`s and `export`s to load classes and functions for other files. It also allows us to preprocess code before compiling to a single file. We will be using [Typescript](https://www.typescriptlang.org/docs/home.html) for this course which is Javascript augmented with type annotations. Webpack will convert Typescript files to Javascript files on compilation and in doing so will also check for proper type-safety and usage. Read more about Javascript modules in the resources section below.

## Developing Your Code
All of the JavaScript code is living inside the `src` directory. The main file that gets executed when you load the page as you may have guessed is `main.ts`. Here, you can make any changes you want, import functions from other files, etc. The reason that we highly suggest you build your project with `npm start` is that doing so will start a process that watches for any changes you make to your code. If it detects anything, it'll automagically rebuild your project and then refresh your browser window for you. Wow. That's cool. If you do it the other way, you'll need to run `npm build` and then refresh your page every time you want to test something.

We would suggest editing your project with Visual Studio Code https://code.visualstudio.com/. Microsoft develops it and Microsoft also develops Typescript so all of the features work nicely together. Sublime Text and installing the Typescript plugins should probably work as well.

## Assignment Details
1. Take some time to go through the existing codebase so you can get an understanding of syntax and how the code is architected. Much of the code is designed to mirror the class structures used in CIS 460's OpenGL assignments, so it should hopefully be somewhat familiar.
2. Take a look at the resources linked in the section below. Definitely read about Javascript modules and Typescript. The other links provide documentation for classes used in the code.
3. Add a `Cube` class that inherits from `Drawable` and at the very least implement a constructor and its `create` function. Then, add a `Cube` instance to the scene to be rendered.
4. Read the documentation for dat.GUI below. Update the existing GUI in `main.ts` with a parameter to alter the color passed to `u_Color` in the Lambert shader.
5. Write a custom fragment shader that implements FBM, Worley Noise, or Perlin Noise based on 3D inputs (as opposed to the 2D inputs in the slides). This noise must be used to modify your fragment color. If your custom shader is particularly interesting, you'll earn some bonus points.
6. Write a custom vertex shader that uses a trigonometric function (e.g. `sin`, `tan`) to non-uniformly modify your cube's vertex positions over time. This will necessitate instantiating an incrementing variable in your Typescript code that you pass to your shader every tick. Refer to the base code's methods of passing variables to shaders if you are unsure how to do so.
7. Feel free to update any of the files when writing your code. The implementation of the `OpenGLRenderer` is currently very simple.

## Making a Live Demo
When you push changes to the `master` branch of your repository on Github, a Github workflow will run automatically which builds your code and pushes the build to a new branch `gh-pages`. The configuration file which handles this is located at `.github/workflows/build-and-deploy.yml`. If you want to modify this, you can read more about workflows [here](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions).

Once your built code is pushed to `gh-pages`, Github can automatically publish a live site. Configure that by:

1. Open the Settings tab of your repository in Github.

2. Scroll down to the Pages tab of the Settings (in the table on the left) and choose which branch to make the source for the deployed project. This should be the `gh-pages` branch which is automatically created after the first successful build of the `master` branch.

3. Done! Now, any new commits on the `master` branch will be built and pushed to `gh-pages`. The project should be visible at http://username.github.io/repo-name.


To check if everything is on the right track:

1. Make sure the `gh-pages` branch of your repo has a files called `index.html`, `bundle.js`, and `bundle.js.map`

2. In the settings tab of the repo, under Pages, make sure it says your site is published at some url.

## Submission
1. Create a pull request to this repository with your completed code.
2. Update README.md to contain a solid description of your project with a screenshot of some visuals, and a link to your live demo.
3. Submit the link to your pull request on Canvas, and add a comment to your submission with a hyperlink to your live demo.
4. Include a link to your live site.

## Resources
- Javascript modules https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
- Typescript https://www.typescriptlang.org/docs/home.html
- dat.gui https://workshop.chromeexperiments.com/examples/gui/
- glMatrix http://glmatrix.net/docs/
- WebGL
- Interfaces https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
- Types https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Types
- Constants https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants
142 changes: 142 additions & 0 deletions src/geometry/Cube.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@

// Written by Nathan Devlin, using reference by Adam Mally

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.
// Set the origin of the cube to center
this.center = vec4.fromValues(center[0], center[1], center[2], 1);
}

create()
{
// Positions array
this.positions = new Float32Array([
// First Face
-1 + this.center[0], -1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], -1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], 1 + this.center[1], 1 + this.center[2], 1,
-1 + this.center[0], 1 + this.center[1], 1 + this.center[2], 1,

// Second Face
-1 + this.center[0], -1 + this.center[1], -1 + this.center[2], 1,
1 + this.center[0], -1 + this.center[1], -1 + this.center[2], 1,
1 + this.center[0], 1 + this.center[1], -1 + this.center[2], 1,
-1 + this.center[0], 1 + this.center[1], -1 + this.center[2], 1,

// Third Face
1 + this.center[0], -1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], -1 + this.center[1], -1 + this.center[2], 1,
1 + this.center[0], 1 + this.center[1], -1 + this.center[2], 1,
1 + this.center[0], 1 + this.center[1], 1 + this.center[2], 1,

// Fourth Face
-1 + this.center[0], -1 + this.center[1], 1 + this.center[2], 1,
-1 + this.center[0], -1 + this.center[1], -1 + this.center[2], 1,
-1 + this.center[0], 1 + this.center[1], -1 + this.center[2], 1,
-1 + this.center[0], 1 + this.center[1], 1 + this.center[2], 1,

// Fifth Face
-1 + this.center[0], -1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], -1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], -1 + this.center[1], -1 + this.center[2], 1,
-1 + this.center[0], -1 + this.center[1], -1 + this.center[2], 1,

// Sixth Face
-1 + this.center[0], 1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], 1 + this.center[1], 1 + this.center[2], 1,
1 + this.center[0], 1 + this.center[1], -1 + this.center[2], 1,
-1 + this.center[0], 1 + this.center[1], -1 + this.center[2], 1
]);

// Normals array
this.normals = new Float32Array([
// First Face
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,

// Second Face
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0,
0, 0, -1, 0,

// Third Face
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,

// Fourth Face
-1, 0, 0, 0,
-1, 0, 0, 0,
-1, 0, 0, 0,
-1, 0, 0, 0,

// Fifth Face
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0,
0, -1, 0, 0,

// Sixth Face
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0
]);

// Indices array
this.indices = new Uint32Array([
// First Face
0, 1, 2, 0, 2, 3,

// Second Face
4, 5, 6, 4, 6, 7,

// Third Face
8, 9, 10, 8, 10, 11,

// Fourth Face
12, 13, 14, 12, 14, 15,

// Fifth Face
16, 17, 18, 16, 18, 19,

// Sixth Face
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);

console.log(`Created cube`);
}
};

export default Cube;

70 changes: 64 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import {vec3} from 'gl-matrix';

// Original code by Adam Mally, additions by Nathan Devlin

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,26 +10,47 @@ 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,
tesselations: 4,
'Load Scene': loadScene, // A function pointer, essentially
};

// Controller that allows user color input
const colorObject =
{
actualColor: [ 255, 0, 0 ], // RGB array
};

let icosphere: Icosphere;

let square: Square;

let cube: Cube;

let prevTesselations: number = 5;

// Used as a clock
let currTick: 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 constructor takes in object origin
cube = new Cube(vec3.fromValues(1, 1, 1));
cube.create();
}

function main() {

function main()
{
// Initial display for framerate
const stats = Stats();
stats.setMode(0);
Expand All @@ -40,6 +64,10 @@ function main() {
gui.add(controls, 'tesselations', 0, 8).step(1);
gui.add(controls, 'Load Scene');

// Color control; RGB input
gui.addColor(colorObject, 'actualColor');


// get canvas and webgl context
const canvas = <HTMLCanvasElement> document.getElementById('canvas');
const gl = <WebGL2RenderingContext> canvas.getContext('webgl2');
Expand All @@ -56,16 +84,29 @@ 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);

gl.enable(gl.DEPTH_TEST);

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

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

// This function will be called every frame
function tick() {
function tick()
{
// Increment the clock
currTick += 1.0;

camera.update();
stats.begin();
gl.viewport(0, 0, window.innerWidth, window.innerHeight);
Expand All @@ -76,10 +117,26 @@ function main() {
icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations);
icosphere.create();
}

// Render with lambert shader
/*
renderer.render(camera, lambert, [
icosphere,
// square,
]);
cube,
],
// Divide by 256 to convert from web RGB to shader 0-1 values
vec4.fromValues(colorObject.actualColor[0] / 256.0, colorObject.actualColor[1] / 256.0, colorObject.actualColor[2] / 256.0, 1),
currTick
);
*/

// Render with custom noise-based shader
renderer.render(camera, custom, [icosphere, cube],
// Divide by 256 to convert from web RGB to shader 0-1 values
vec4.fromValues(colorObject.actualColor[0] / 256.0, colorObject.actualColor[1] / 256.0, colorObject.actualColor[2] / 256.0, 1),
currTick
);

stats.end();

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

main();

Loading