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
122 changes: 9 additions & 113 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,124 +1,20 @@

# Project 5: Shaders

## Project Instructions
https://nnewberg.github.io/Project5-Shaders/

Implement at least 75 points worth of shaders from the following list. We reserve the right to grant only partial credit for shaders that do not meet our standards, as well as extra credit for shaders that we find to be particularly impressive.
## Project Overview

Some of these shading effects were covered in lecture -- some were not. If you wish to implement the more complex effects, you will have to perform some extra research. Of course, we encourage such academic curiosity which is why we’ve included these advanced shaders in the first place!
I have implemented a lit-sphere, pointilism and gaussian blur shader. <br>
I have also designed a 'Toon Hatch' shader, which was inspired by a shader created by 3 dreams of black:
https://www.chromeexperiments.com/experiment/hatching-glow-shader <br>

Document each shader you implement in your README with at least a sentence or two of explanation. Well-commented code will earn you many brownie (and probably sanity) points.

If you use shadertoy or any materials as reference, please properly credit your sources in the README and on top of the shader file. Failing to do so will result in plagiarism and will significantly reduce your points.
## Pics

Examples: [https://cis700-procedural-graphics.github.io/Project5-Shaders/](https://cis700-procedural-graphics.github.io/Project5-Shaders/)
![img](https://github.com/nnewberg/Project5-Shaders/blob/master/screenshots/red.png?raw=true)

### 15 points each: Instagram-like filters
![img](https://github.com/nnewberg/Project5-Shaders/blob/master/screenshots/toonhatch.png?raw=true)

- Tone mapping:
- Linear (5 points)
- Reinhard (5 points)
- Filmic (5 points)
- Gaussian blur (no double counting with Bloom)
- Iridescence
- Pointilism
- Vignette
- Fish-eye bulge
![img](https://github.com/nnewberg/Project5-Shaders/blob/master/screenshots/blur.png?raw=true)

### 25 points each:
- Bloom
- Noise Warp
- Hatching
- Edge detection with Sobel filtering
- Lit Sphere ([paper](http://www.ppsloan.org/publications/LitSphere.pdf))
- Uncharted 2 customizable filmic curve, following John Hable’s presetantion.
- Without Linear, Reinhard, filmic (10 points)
- With all of linear, Reinhard, filmic (10 points)
- Customizable via GUI: (5 points total)
- Controlling Exposure
- Side by side comparison between linear, Reinhard, filmic, and Uncharted2 .

### 37.5 points each:
- K-means color compression (unless you are extremely clever, the k-means clusterer has to be CPU side)
- Dithering


### 5 points - Interactivity
Implement a dropdown GUI to select different shader effects from your list.

### ??? points
Propose your own shading effects!

### For the overachievers:
Weave all your shading effects into one aesthetically-coherent scene, perhaps by incorporating some of your previous assignments!


## Getting Started

### main.js

`main.js` is responsible for setting up the scene with the Mario mesh, initializing GUI and camera, etc.

### Adding Shaders

To add a shader, you'll want to add a file to the `src/shaders` or `src/post` folder. As examples, we've provided two shaders `lambert.js` and `grayscale.js`. Here, I will give a brief overview of how these work and how everything hooks together.

**shaders/lambert.js**

IMPORTANT: I make my lambert shader available by exporting it in `shaders/index.js`.

```javascript
export {default as Lambert} from './Lambert'
```

Each shader should export a function that takes in the `renderer`, `scene`, and `camera`. That function should return a `Shader` Object.

`Shader.initGUI` is a function that will be called to initialize the GUI for that shader. in `lambert.js`, you can see that it's here that I set up all the parameters that will affect my shader.

`Shader.material` should be a `THREE.ShaderMaterial`. This should be pretty similar to what you've seen in previous projects. `Shader.material.vertexShader` and `Shader.material.fragmentShader` are the vertex and fragment shaders used.

At the bottom, I have the following snippet of code. All it does is bind the Mario texture once it's loaded.

```javascript
textureLoaded.then(function(texture) {
Shader.material.uniforms.texture.value = texture;
});
```

So when you change the Shader parameter in the GUI, `Shader.initGUI(gui)` will be called to initialize the GUI, and then the Mario mesh will have `Shader.material` applied to it.

**post/grayscale.js**

GUI parameters here are initialized the same way they are for the other shaders.

Post process shaders should use the THREE.js `EffectComposer`. To set up the grayscale filter, I first create a new composer: `var composer = new EffectComposer(renderer);`. Then I add a a render pass as the first pass: `composer.addPass(new EffectComposer.RenderPass(scene, camera));`. This will set up the composer to render the scene as normal into a buffer. I add my filter to operate on that buffer: `composer.addPass(GrayscaleShader);`, and mark it as the final pass that will write to the screen `GrayscaleShader.renderToScreen = true;`

GrayscaleShader is a `EffectComposer.ShaderPass` which basically takes the same arguments as `THREE.ShaderMaterial`. Note, that one uniform that will have to include is `tDiffuse`. This is the texture sampler which the EffectComposer will automatically bind the previously rendered pass to. If you look at `glsl/grayscale-frag.glsl`, this is the texture we read from to get the previous pixel color: `vec4 col = texture2D(tDiffuse, f_uv);`.

IMPORTANT: You initially define your shader passes like so:

```javascript
var GrayscaleShader = new EffectComposer.ShaderPass({
uniforms: {
tDiffuse: {
type: 't',
value: null
},
u_amount: {
type: 'f',
value: options.amount
}
},
vertexShader: require('../glsl/pass-vert.glsl'),
fragmentShader: require('../glsl/grayscale-frag.glsl')
});
```

BUT, if you want to modify the uniforms, you need to do so like so: `GrayscaleShader.material.uniforms.u_amount.value = val;`. Note the extra `.material` property.

## Deploy

1. Create a `gh-pages` branch on GitHub
2. Do `npm run build`
3. Commit and add all your changes.
4. Do `npm run deploy`
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"three-effectcomposer": "0.0.1",
"three-obj-loader": "^1.0.2",
"three-orbit-controls": "^82.1.0",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.3.0",
"webpack": "^1.13.1",
"webpack-dev-server": "^1.16.2",
"webpack-glsl-loader": "^1.0.1"
}
}
Binary file added screenshots/blur.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 screenshots/chrome.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 screenshots/red.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 screenshots/toonhatch.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 src/assets/sphere-textures/bluegreen.jpg
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 src/assets/sphere-textures/bronze.jpg
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 src/assets/sphere-textures/chrome.jpg
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 src/assets/sphere-textures/colorwheel.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 src/assets/sphere-textures/red.jpg
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 src/assets/sphere-textures/slime.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/glsl/colorfilter-frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

uniform sampler2D tDiffuse;
uniform float u_amount;
varying vec2 f_uv;

// tDiffuse is a special uniform sampler that THREE.js will bind the previously rendered frame to

void main() {
vec4 col = texture2D(tDiffuse, f_uv);
//float red = dot(col.rgb, vec3(0.500, 0.0, 0.0));

col.rgb = (col.rgb - vec3(1.0, 0.0, 0.0)) * (u_amount) + col.rgb * (1.0 - u_amount);

gl_FragColor = col;
}
152 changes: 152 additions & 0 deletions src/glsl/dot-frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
uniform vec3 uLightDir;
varying vec3 vNormal;
varying vec3 vPos;
#define M_PI 3.1415926535897932384626433832795
#define N_OCTAVES 5


float noise(vec3 seed){
return fract(sin(dot(seed ,vec3(12.9898,78.233, 157.179))) * 43758.5453);
}

float TotalNoise(vec3 seed, float frequency, float amplitude){ //inside frequency outside amplit
float n1 = noise(seed * frequency) * amplitude;
return n1;
}

float lerp(float a, float b, float t){
return (a * (1.0 - t) + b * t);
}

float cosine_interpolate(float a, float b, float t){
float cos_t = (1.0 - cos(t * M_PI)) * 0.5;
return lerp(a, b, cos_t);
}


float trilinearInterpolation(vec3 pos, float frequency, float amplitude){

vec3 pd = pos * frequency;

//8 adjacent vec3 positions on lattice
vec3 v000 = vec3(floor(pd.x),floor(pd.y),floor(pd.z));
vec3 v100 = vec3(ceil(pd.x),floor(pd.y),floor(pd.z));
vec3 v010 = vec3(floor(pd.x), ceil(pd.y), floor(pd.z));
vec3 v001 = vec3(floor(pd.x), floor(pd.y), ceil(pd.z));
vec3 v101 = vec3(ceil(pd.x), floor(pd.y), ceil(pd.z));
vec3 v110 = vec3(ceil(pd.x), ceil(pd.y), floor(pd.z));
vec3 v011 = vec3(floor(pd.x), ceil(pd.y), ceil(pd.z));
vec3 v111 = vec3(ceil(pd.x), ceil(pd.y), ceil(pd.z));

//noise of cooresponding positions on lattice
float n000 = TotalNoise(v000, frequency, amplitude);
float n100 = TotalNoise(v100, frequency, amplitude);
float n010 = TotalNoise(v010, frequency, amplitude);
float n001 = TotalNoise(v001, frequency, amplitude);
float n101 = TotalNoise(v101, frequency, amplitude);
float n110 = TotalNoise(v110, frequency, amplitude);
float n011 = TotalNoise(v011, frequency, amplitude);
float n111 = TotalNoise(v111, frequency, amplitude);

//time val for interpolation
float tX = pd.x - floor(pd.x);
float tY = pd.y - floor(pd.y);
float tZ = pd.z - floor(pd.z);

float n00 = cosine_interpolate(n000, n100, tX);
float n10 = cosine_interpolate(n001, n101, tX);
float n11 = cosine_interpolate(n011, n111, tX);
float n01 = cosine_interpolate(n010, n110, tX);
float n0 = cosine_interpolate(n00, n10, tZ);
float n1 = cosine_interpolate(n01, n11, tZ);
float n = cosine_interpolate(n0, n1, tY);

return n;
}


float PerlinNoise3D(vec3 pos, float freqControl){
float total = 0.0;
float persistance = 1.0 / 2.0;

for (int i = 0 ; i < N_OCTAVES; i++){

float frequency = pow(2.0, float(i)) * freqControl;
float amplitude = pow(persistance, float(i));
total += trilinearInterpolation(pos, frequency, amplitude);

}

return total;

}

vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main()
{
float intensity;
float r; //random number between 0,1;
float partitions = 3.0;

vec4 white = vec4(1.0,1.0,1.0,1.0);
vec4 black = vec4(0.0,0.0,0.0,1.0);
vec4 color = white;


intensity = dot(uLightDir,vNormal);
r = noise(vPos);

// intensity = intensity * partitions;
// intensity = floor(intensity)/partitions;

// float frequency = ((intensity));

//if (intensity > 0.95)
// frequency = 1.0;
// else if (intensity > 0.5)
// frequency = 2.0;
// else if (intensity > 0.25)
// frequency = 3.0;
// else
// frequency = 4.0;

// float amplitude = 1.0/frequency;
// float perlin = PerlinNoise3D(vPos, frequency);
// vec3 noise_col = vec3(perlin,perlin,perlin);

// vec3 hsvColor = rgb2hsv(color.rgb);
// float h = hsvColor.r;

// hsvColor = hsvColor * 5.0;
// hsvColor = floor(hsvColor)/5.0;
// hsvColor.r = h;

// vec3 rgbColor = hsv2rgb(hsvColor);
// color = vec4(rgbColor.x,rgbColor.y,rgbColor.z, 1.0);

if (r > intensity){
color = black;
}

//color = vec4(noise_col.rgb,1.0);

gl_FragColor = color;

}
16 changes: 16 additions & 0 deletions src/glsl/dot-vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
varying vec3 vNormal;
varying vec3 vPos;

void main(){

vec4 vertPos = vec4(position, 1.0);

vec3 eye = normalize(vec3(modelViewMatrix * vertPos));
vec3 n = normalize(normalMatrix * normal);

vNormal = n;
vPos = position;

gl_Position = projectionMatrix * modelViewMatrix * vertPos;

}
32 changes: 32 additions & 0 deletions src/glsl/gaussian-frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

uniform sampler2D tDiffuse;
varying vec2 f_uv;

// tDiffuse is a special uniform sampler that THREE.js will bind the previously rendered frame to

void main() {
vec4 col = texture2D(tDiffuse, f_uv);
float uvIncr = 0.002;

vec2 uv01 = f_uv + vec2(0.0,uvIncr);
vec2 uv0n1 = f_uv + vec2(0.0, -uvIncr);

vec2 uv10 = f_uv + vec2(uvIncr, 0.0);
vec2 uvn10 = f_uv + vec2(-uvIncr, 0.0);

vec4 col1 = texture2D(tDiffuse, uv01);
vec4 col2 = texture2D(tDiffuse, uv0n1);
vec4 col3 = texture2D(tDiffuse, uv10);
vec4 col4 = texture2D(tDiffuse, uvn10);

col = (col1 + col2 + col3 + col4)/4.0;
col[3] = 1.0;

// vec2 uv11 = f_uv + vec2(1.0, 0.0);
// vec2 uvn11 = f_uv + vec2(-1.0, 0.0);
// vec2 uv1n1 = f_uv + vec2(-1.0, 0.0);



gl_FragColor = col;
}
Loading