From 7983e76d4cef3d12c67a7266d3248c3f65275211 Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Tue, 21 Feb 2017 14:55:56 -0500 Subject: [PATCH 1/7] vignette --- src/glsl/random-frag.glsl | 20 +++++++++ src/glsl/toon-frag.glsl | 53 ++++++++++++++++++++++++ src/glsl/vignette-frag.glsl | 13 ++++++ src/post/grayscale.js | 1 + src/post/index.js | 4 +- src/post/random.js | 49 ++++++++++++++++++++++ src/post/vignette.js | 53 ++++++++++++++++++++++++ src/shaders/index.js | 4 +- src/shaders/toon.js | 81 +++++++++++++++++++++++++++++++++++++ 9 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 src/glsl/random-frag.glsl create mode 100644 src/glsl/toon-frag.glsl create mode 100644 src/glsl/vignette-frag.glsl create mode 100644 src/post/random.js create mode 100644 src/post/vignette.js create mode 100644 src/shaders/toon.js diff --git a/src/glsl/random-frag.glsl b/src/glsl/random-frag.glsl new file mode 100644 index 0000000..57ff1ef --- /dev/null +++ b/src/glsl/random-frag.glsl @@ -0,0 +1,20 @@ + +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 color = texture2D(tDiffuse, f_uv); + + color.x = 0.393 * (color.x * 255.0) + 0.769*(color.y*255.0) + 0.189*(color.z*255.0); + color.y = 0.349 * (color.x*255.0) + 0.686*(color.y*255.0) + 0.168*(color.z*255.0); + color.z = 0.272 * (color.x*255.0) + 0.534*(color.y*255.0) + 0.131*(color.z*255.0); + + color.x /= 255.0; + color.y /= 255.0; + color.z /= 255.0; + + gl_FragColor = color; +} \ No newline at end of file diff --git a/src/glsl/toon-frag.glsl b/src/glsl/toon-frag.glsl new file mode 100644 index 0000000..c5127fe --- /dev/null +++ b/src/glsl/toon-frag.glsl @@ -0,0 +1,53 @@ + +uniform sampler2D texture; +uniform int u_useTexture; +uniform vec3 u_albedo; +uniform vec3 u_ambient; +uniform vec3 u_lightPos; +uniform vec3 u_lightCol; +uniform float u_lightIntensity; +uniform vec3 u_cameraPos; + +varying vec3 f_position; +varying vec3 f_normal; +varying vec2 f_uv; + +void main() { + vec4 color = vec4(u_albedo, 1.0); + + if (u_useTexture == 1) { + color = texture2D(texture, f_uv); + } + + float d = clamp(dot(f_normal, normalize(u_lightPos - f_position)), 0.0, 1.0); + + vec3 look = normalize(f_position - u_cameraPos); + if (dot(f_normal, look) > -0.2 && dot(f_normal, look) < 0.2) { + gl_FragColor == vec4(0.0,0.0,0.0,1.0); + } else { + if (mod(color.x, 0.3) != 0.0) { + if (mod(color.x, 0.3) >= 0.05) { + color.x = color.x + (0.3 - mod(color.x, 0.3)); + } else if (mod(color.x, 0.3) < 0.05) { + color.x = color.x - (mod(color.x, 0.3)); + } + } + + if (mod(color.y, 0.3) != 0.0) { + if (mod(color.y, 0.3) >= 0.05) { + color.y = color.y + (0.3 - mod(color.y, 0.3)); + } else if (mod(color.y, 0.3) < 0.05) { + color.y = color.y - (mod(color.y, 0.3)); + } + } + + if (mod(color.z, 0.3) != 0.0) { + if (mod(color.z, 0.3) >= 0.05) { + color.z = color.z + (0.3 - mod(color.z, 0.3)); + } else if (mod(color.z, 0.3) < 0.05) { + color.z = color.z - (mod(color.z, 0.3)); + } + } + gl_FragColor = vec4(color.rgb * u_lightCol * u_lightIntensity + u_ambient, 1.0); + } +} \ No newline at end of file diff --git a/src/glsl/vignette-frag.glsl b/src/glsl/vignette-frag.glsl new file mode 100644 index 0000000..a3aa4f7 --- /dev/null +++ b/src/glsl/vignette-frag.glsl @@ -0,0 +1,13 @@ + +uniform sampler2D tDiffuse; +uniform float u_offset; +uniform float u_darkness; +varying vec2 f_uv; + +// tDiffuse is a special uniform sampler that THREE.js will bind the previously rendered frame to + +void main() { + vec4 texel = texture2D( tDiffuse, f_uv ); + vec2 uv = (f_uv - vec2(0.5)) * vec2(u_offset); + gl_FragColor = vec4(mix(texel.rgb, vec3(1.0 - u_darkness), dot(uv, uv)), texel.a); +} \ No newline at end of file diff --git a/src/post/grayscale.js b/src/post/grayscale.js index 728df40..9344ee1 100644 --- a/src/post/grayscale.js +++ b/src/post/grayscale.js @@ -7,6 +7,7 @@ var options = { var GrayscaleShader = new EffectComposer.ShaderPass({ uniforms: { + // the texture the frame is rendered to before passing to the post processing shader tDiffuse: { type: 't', value: null diff --git a/src/post/index.js b/src/post/index.js index 9c0d763..74e9591 100644 --- a/src/post/index.js +++ b/src/post/index.js @@ -15,4 +15,6 @@ export function None(renderer, scene, camera) { } // follow this syntax to make your shaders available to the GUI -export {default as Grayscale} from './grayscale' \ No newline at end of file +export {default as Grayscale} from './grayscale' +export {default as Random} from './random' +export {default as Vignette} from './vignette' \ No newline at end of file diff --git a/src/post/random.js b/src/post/random.js new file mode 100644 index 0000000..d0f433e --- /dev/null +++ b/src/post/random.js @@ -0,0 +1,49 @@ +const THREE = require('three'); +const EffectComposer = require('three-effectcomposer')(THREE) + +var options = { + amount: 1 +} + +var GrayscaleShader = new EffectComposer.ShaderPass({ + uniforms: { + // the texture the frame is rendered to before passing to the post processing shader + tDiffuse: { + type: 't', + value: null + }, + u_amount: { + type: 'f', + value: options.amount + } + }, + vertexShader: require('../glsl/pass-vert.glsl'), + fragmentShader: require('../glsl/random-frag.glsl') +}); + +export default function Grayscale(renderer, scene, camera) { + + // this is the THREE.js object for doing post-process effects + var composer = new EffectComposer(renderer); + + // first render the scene normally and add that as the first pass + composer.addPass(new EffectComposer.RenderPass(scene, camera)); + + // then take the rendered result and apply the GrayscaleShader + composer.addPass(GrayscaleShader); + + // set this to true on the shader for your last pass to write to the screen + GrayscaleShader.renderToScreen = true; + + return { + initGUI: function(gui) { + gui.add(options, 'amount', 0, 1).onChange(function(val) { + GrayscaleShader.material.uniforms.u_amount.value = val; + }); + }, + + render: function() {; + composer.render(); + } + } +} \ No newline at end of file diff --git a/src/post/vignette.js b/src/post/vignette.js new file mode 100644 index 0000000..ed75faf --- /dev/null +++ b/src/post/vignette.js @@ -0,0 +1,53 @@ +const THREE = require('three'); +const EffectComposer = require('three-effectcomposer')(THREE) + +var options = { + offset: 1.0, + darkness: 1.0 +} + +var VignetteShader = new EffectComposer.ShaderPass({ + uniforms: { + // the texture the frame is rendered to before passing to the post processing shader + tDiffuse: { + type: 't', + value: null + }, + u_offset: { + type: 'f', + value: options.offset + }, + u_darkness: { + type: 'f', + value: options.darkness + } + }, + vertexShader: require('../glsl/pass-vert.glsl'), + fragmentShader: require('../glsl/vignette-frag.glsl') +}); + +export default function Vignette(renderer, scene, camera) { + + // this is the THREE.js object for doing post-process effects + var composer = new EffectComposer(renderer); + composer.addPass(new EffectComposer.RenderPass(scene, camera)); + composer.addPass(VignetteShader); + + // set this to true on the shader for your last pass to write to the screen + VignetteShader.renderToScreen = true; + + return { + initGUI: function(gui) { + gui.add(options, 'offset', 0, 1).onChange(function(val) { + VignetteShader.material.uniforms.u_offset.value = val; + }); + gui.add(options, 'darkness', 0, 1).onChange(function(val) { + VignetteShader.material.uniforms.u_darkness.value = val; + }); + }, + + render: function() {; + composer.render(); + } + } +} \ No newline at end of file diff --git a/src/shaders/index.js b/src/shaders/index.js index e5b85c1..b6fa2b0 100644 --- a/src/shaders/index.js +++ b/src/shaders/index.js @@ -1,4 +1,6 @@ // This file exports available shaders to the GUI. // follow this syntax to make your shaders available to the GUI -export {default as Lambert} from './lambert' \ No newline at end of file +export {default as Lambert} from './lambert' + +export {default as Toon} from './toon' \ No newline at end of file diff --git a/src/shaders/toon.js b/src/shaders/toon.js new file mode 100644 index 0000000..13777c6 --- /dev/null +++ b/src/shaders/toon.js @@ -0,0 +1,81 @@ + +const THREE = require('three'); +import {textureLoaded} from '../mario' + +// options for lambert shader +var options = { + lightColor: '#ffffff', + lightIntensity: 2, + albedo: '#dddddd', + ambient: '#111111', + useTexture: true +} + +export default function(renderer, scene, camera) { + + const Shader = { + initGUI: function(gui) { + gui.addColor(options, 'lightColor').onChange(function(val) { + Shader.material.uniforms.u_lightCol.value = new THREE.Color(val); + }); + gui.add(options, 'lightIntensity').onChange(function(val) { + Shader.material.uniforms.u_lightIntensity.value = val; + }); + gui.addColor(options, 'albedo').onChange(function(val) { + Shader.material.uniforms.u_albedo.value = new THREE.Color(val); + }); + gui.addColor(options, 'ambient').onChange(function(val) { + Shader.material.uniforms.u_ambient.value = new THREE.Color(val); + }); + gui.add(options, 'useTexture').onChange(function(val) { + Shader.material.uniforms.u_useTexture.value = val; + }); + }, + + material: new THREE.ShaderMaterial({ + uniforms: { + texture: { + type: "t", + value: null + }, + u_useTexture: { + type: 'i', + value: options.useTexture + }, + u_albedo: { + type: 'v3', + value: new THREE.Color(options.albedo) + }, + u_ambient: { + type: 'v3', + value: new THREE.Color(options.ambient) + }, + u_lightPos: { + type: 'v3', + value: new THREE.Vector3(30, 50, 40) + }, + u_lightCol: { + type: 'v3', + value: new THREE.Color(options.lightColor) + }, + u_lightIntensity: { + type: 'f', + value: options.lightIntensity + }, + u_cameraPos: { + type: 'v3', + value: camera.position + } + }, + vertexShader: require('../glsl/lambert-vert.glsl'), + fragmentShader: require('../glsl/toon-frag.glsl') + }) + } + + // once the Mario texture loads, bind it to the material + textureLoaded.then(function(texture) { + Shader.material.uniforms.texture.value = texture; + }); + + return Shader; +} \ No newline at end of file From 062104b70d01a14de2d5835b874619cae42d4eaa Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Tue, 21 Feb 2017 16:20:38 -0500 Subject: [PATCH 2/7] fisheye, iridescence --- src/glsl/fisheye-frag.glsl | 29 +++++++++++++ src/glsl/iridescent-frag.glsl | 26 +++++++++++ src/glsl/vignette-frag.glsl | 2 +- src/post/fisheye.js | 34 +++++++++++++++ src/post/index.js | 3 +- src/shaders/index.js | 4 +- src/shaders/iridescent.js | 81 +++++++++++++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 src/glsl/fisheye-frag.glsl create mode 100644 src/glsl/iridescent-frag.glsl create mode 100644 src/post/fisheye.js create mode 100644 src/shaders/iridescent.js diff --git a/src/glsl/fisheye-frag.glsl b/src/glsl/fisheye-frag.glsl new file mode 100644 index 0000000..f9226d2 --- /dev/null +++ b/src/glsl/fisheye-frag.glsl @@ -0,0 +1,29 @@ +uniform sampler2D tDiffuse; +varying vec2 f_uv; +const float PI = 3.1415926535; + +// uses the polar method from http://paulbourke.net/dome/fisheye/ +void main() { + float aperture = 200.0; + float apertureHalf = 0.5 * aperture * (PI / 180.0); + float maxFactor = sin(apertureHalf); + + vec2 uv; + vec2 xy = 2.0 * f_uv.xy - 1.0; + float d = length(xy); + + if (d < (2.0 - maxFactor)) { + d = length(xy * maxFactor); + float z = sqrt(1.0 - d * d); + float r = atan(d, z) / PI; + float phi = atan(xy.y, xy.x); + + uv.x = r * cos(phi) + 0.5; + uv.y = r * sin(phi) + 0.5; + } else { + uv = f_uv.xy; + } + + vec4 c = texture2D(tDiffuse, uv); + gl_FragColor = c; +} \ No newline at end of file diff --git a/src/glsl/iridescent-frag.glsl b/src/glsl/iridescent-frag.glsl new file mode 100644 index 0000000..5f2cfb8 --- /dev/null +++ b/src/glsl/iridescent-frag.glsl @@ -0,0 +1,26 @@ + +uniform sampler2D texture; +uniform int u_useTexture; +uniform vec3 u_albedo; +uniform vec3 u_ambient; +uniform vec3 u_lightPos; +uniform vec3 u_lightCol; +uniform float u_lightIntensity; +uniform vec3 u_cameraPos; + +varying vec3 f_position; +varying vec3 f_normal; +varying vec2 f_uv; + +void main() { + vec4 color = vec4(u_albedo, 1.0); + + if (u_useTexture == 1) { + color = texture2D(texture, f_uv); + } + + vec3 look = normalize(u_cameraPos-f_position); + float d = dot(look, f_normal); + + gl_FragColor = vec4(d * color.rgb * u_lightCol * u_lightIntensity + u_ambient, 1.0); +} \ No newline at end of file diff --git a/src/glsl/vignette-frag.glsl b/src/glsl/vignette-frag.glsl index a3aa4f7..7d476c4 100644 --- a/src/glsl/vignette-frag.glsl +++ b/src/glsl/vignette-frag.glsl @@ -7,7 +7,7 @@ varying vec2 f_uv; // tDiffuse is a special uniform sampler that THREE.js will bind the previously rendered frame to void main() { - vec4 texel = texture2D( tDiffuse, f_uv ); + vec4 texel = texture2D(tDiffuse, f_uv); vec2 uv = (f_uv - vec2(0.5)) * vec2(u_offset); gl_FragColor = vec4(mix(texel.rgb, vec3(1.0 - u_darkness), dot(uv, uv)), texel.a); } \ No newline at end of file diff --git a/src/post/fisheye.js b/src/post/fisheye.js new file mode 100644 index 0000000..bf48553 --- /dev/null +++ b/src/post/fisheye.js @@ -0,0 +1,34 @@ +const THREE = require('three'); +const EffectComposer = require('three-effectcomposer')(THREE) + +var FisheyeShader = new EffectComposer.ShaderPass({ + uniforms: { + // the texture the frame is rendered to before passing to the post processing shader + tDiffuse: { + type: 't', + value: null + } + }, + vertexShader: require('../glsl/pass-vert.glsl'), + fragmentShader: require('../glsl/fisheye-frag.glsl') +}); + +export default function Fisheye(renderer, scene, camera) { + + // this is the THREE.js object for doing post-process effects + var composer = new EffectComposer(renderer); + composer.addPass(new EffectComposer.RenderPass(scene, camera)); + composer.addPass(FisheyeShader); + + // set this to true on the shader for your last pass to write to the screen + FisheyeShader.renderToScreen = true; + + return { + initGUI: function(gui) { + }, + + render: function() {; + composer.render(); + } + } +} \ No newline at end of file diff --git a/src/post/index.js b/src/post/index.js index 74e9591..3a65512 100644 --- a/src/post/index.js +++ b/src/post/index.js @@ -17,4 +17,5 @@ export function None(renderer, scene, camera) { // follow this syntax to make your shaders available to the GUI export {default as Grayscale} from './grayscale' export {default as Random} from './random' -export {default as Vignette} from './vignette' \ No newline at end of file +export {default as Vignette} from './vignette' +export {default as Fisheye} from './fisheye' \ No newline at end of file diff --git a/src/shaders/index.js b/src/shaders/index.js index b6fa2b0..0987a37 100644 --- a/src/shaders/index.js +++ b/src/shaders/index.js @@ -2,5 +2,5 @@ // This file exports available shaders to the GUI. // follow this syntax to make your shaders available to the GUI export {default as Lambert} from './lambert' - -export {default as Toon} from './toon' \ No newline at end of file +export {default as Toon} from './toon' +export {default as Iridescent} from './iridescent' \ No newline at end of file diff --git a/src/shaders/iridescent.js b/src/shaders/iridescent.js new file mode 100644 index 0000000..4ebb408 --- /dev/null +++ b/src/shaders/iridescent.js @@ -0,0 +1,81 @@ + +const THREE = require('three'); +import {textureLoaded} from '../mario' + +// options for lambert shader +var options = { + lightColor: '#ffffff', + lightIntensity: 2, + albedo: '#dddddd', + ambient: '#111111', + useTexture: true +} + +export default function(renderer, scene, camera) { + + const Shader = { + initGUI: function(gui) { + gui.addColor(options, 'lightColor').onChange(function(val) { + Shader.material.uniforms.u_lightCol.value = new THREE.Color(val); + }); + gui.add(options, 'lightIntensity').onChange(function(val) { + Shader.material.uniforms.u_lightIntensity.value = val; + }); + gui.addColor(options, 'albedo').onChange(function(val) { + Shader.material.uniforms.u_albedo.value = new THREE.Color(val); + }); + gui.addColor(options, 'ambient').onChange(function(val) { + Shader.material.uniforms.u_ambient.value = new THREE.Color(val); + }); + gui.add(options, 'useTexture').onChange(function(val) { + Shader.material.uniforms.u_useTexture.value = val; + }); + }, + + material: new THREE.ShaderMaterial({ + uniforms: { + texture: { + type: "t", + value: null + }, + u_useTexture: { + type: 'i', + value: options.useTexture + }, + u_albedo: { + type: 'v3', + value: new THREE.Color(options.albedo) + }, + u_ambient: { + type: 'v3', + value: new THREE.Color(options.ambient) + }, + u_lightPos: { + type: 'v3', + value: new THREE.Vector3(30, 50, 40) + }, + u_lightCol: { + type: 'v3', + value: new THREE.Color(options.lightColor) + }, + u_lightIntensity: { + type: 'f', + value: options.lightIntensity + }, + u_cameraPos: { + type: 'v3', + value: camera.position + } + }, + vertexShader: require('../glsl/lambert-vert.glsl'), + fragmentShader: require('../glsl/iridescent-frag.glsl') + }) + } + + // once the Mario texture loads, bind it to the material + textureLoaded.then(function(texture) { + Shader.material.uniforms.texture.value = texture; + }); + + return Shader; +} \ No newline at end of file From 4b4a7672a7690657d57fc317da07e561c8a0a1f4 Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Wed, 22 Feb 2017 02:10:11 -0500 Subject: [PATCH 3/7] pixellate --- src/glsl/fisheye-frag.glsl | 2 +- src/glsl/pixellate-frag.glsl | 13 +++++++++++ src/glsl/vignette-frag.glsl | 3 +-- src/post/fisheye.js | 11 +++++++++ src/post/index.js | 3 ++- src/post/pixellate.js | 45 ++++++++++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 src/glsl/pixellate-frag.glsl create mode 100644 src/post/pixellate.js diff --git a/src/glsl/fisheye-frag.glsl b/src/glsl/fisheye-frag.glsl index f9226d2..92b29e5 100644 --- a/src/glsl/fisheye-frag.glsl +++ b/src/glsl/fisheye-frag.glsl @@ -1,10 +1,10 @@ uniform sampler2D tDiffuse; +uniform float aperture; varying vec2 f_uv; const float PI = 3.1415926535; // uses the polar method from http://paulbourke.net/dome/fisheye/ void main() { - float aperture = 200.0; float apertureHalf = 0.5 * aperture * (PI / 180.0); float maxFactor = sin(apertureHalf); diff --git a/src/glsl/pixellate-frag.glsl b/src/glsl/pixellate-frag.glsl new file mode 100644 index 0000000..8c593c3 --- /dev/null +++ b/src/glsl/pixellate-frag.glsl @@ -0,0 +1,13 @@ +varying vec2 f_uv; +uniform sampler2D tDiffuse; +uniform float pixellateFactor; + +void main() { + vec2 p = f_uv.xy; + + p.x -= mod(p.x, 1.0 / pixellateFactor); + p.y -= mod(p.y, 1.0 / pixellateFactor); + + vec3 col = texture2D(tDiffuse, p).rgb; + gl_FragColor = vec4(col, 1.0); +} \ No newline at end of file diff --git a/src/glsl/vignette-frag.glsl b/src/glsl/vignette-frag.glsl index 7d476c4..2ea42cb 100644 --- a/src/glsl/vignette-frag.glsl +++ b/src/glsl/vignette-frag.glsl @@ -4,8 +4,7 @@ uniform float u_offset; uniform float u_darkness; varying vec2 f_uv; -// tDiffuse is a special uniform sampler that THREE.js will bind the previously rendered frame to - +// uses void main() { vec4 texel = texture2D(tDiffuse, f_uv); vec2 uv = (f_uv - vec2(0.5)) * vec2(u_offset); diff --git a/src/post/fisheye.js b/src/post/fisheye.js index bf48553..7afbd3f 100644 --- a/src/post/fisheye.js +++ b/src/post/fisheye.js @@ -1,12 +1,20 @@ const THREE = require('three'); const EffectComposer = require('three-effectcomposer')(THREE) +var options = { + aperture: 200.0 +} + var FisheyeShader = new EffectComposer.ShaderPass({ uniforms: { // the texture the frame is rendered to before passing to the post processing shader tDiffuse: { type: 't', value: null + }, + aperture: { + type: 'f', + value: options.aperture } }, vertexShader: require('../glsl/pass-vert.glsl'), @@ -25,6 +33,9 @@ export default function Fisheye(renderer, scene, camera) { return { initGUI: function(gui) { + gui.add(options, 'aperture').onChange(function(val) { + FisheyeShader.material.uniforms.aperture.value = val; + }); }, render: function() {; diff --git a/src/post/index.js b/src/post/index.js index 3a65512..a4df485 100644 --- a/src/post/index.js +++ b/src/post/index.js @@ -18,4 +18,5 @@ export function None(renderer, scene, camera) { export {default as Grayscale} from './grayscale' export {default as Random} from './random' export {default as Vignette} from './vignette' -export {default as Fisheye} from './fisheye' \ No newline at end of file +export {default as Fisheye} from './fisheye' +export {default as Pixellate} from './pixellate' \ No newline at end of file diff --git a/src/post/pixellate.js b/src/post/pixellate.js new file mode 100644 index 0000000..106d312 --- /dev/null +++ b/src/post/pixellate.js @@ -0,0 +1,45 @@ +const THREE = require('three'); +const EffectComposer = require('three-effectcomposer')(THREE) + +var options = { + pixellateFactor: 100.0 +} + +var Shader = new EffectComposer.ShaderPass({ + uniforms: { + // the texture the frame is rendered to before passing to the post processing shader + tDiffuse: { + type: 't', + value: null + }, + pixellateFactor: { + type: 'f', + value: options.pixellateFactor + } + }, + vertexShader: require('../glsl/pass-vert.glsl'), + fragmentShader: require('../glsl/pixellate-frag.glsl') +}); + +export default function Fisheye(renderer, scene, camera) { + + // this is the THREE.js object for doing post-process effects + var composer = new EffectComposer(renderer); + composer.addPass(new EffectComposer.RenderPass(scene, camera)); + composer.addPass(Shader); + + // set this to true on the shader for your last pass to write to the screen + Shader.renderToScreen = true; + + return { + initGUI: function(gui) { + gui.add(options, 'pixellateFactor').onChange(function(val) { + Shader.material.uniforms.pixellateFactor.value = val; + }); + }, + + render: function() {; + composer.render(); + } + } +} \ No newline at end of file From a494a795bccb02cb50fbdd7b57ac93fbf0aaca0d Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Wed, 22 Feb 2017 02:21:29 -0500 Subject: [PATCH 4/7] fixed iridescent --- src/glsl/iridescent-frag.glsl | 15 +++++++++------ src/glsl/pixellate-frag.glsl | 1 + src/glsl/vignette-frag.glsl | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/glsl/iridescent-frag.glsl b/src/glsl/iridescent-frag.glsl index 5f2cfb8..94c2761 100644 --- a/src/glsl/iridescent-frag.glsl +++ b/src/glsl/iridescent-frag.glsl @@ -1,6 +1,5 @@ uniform sampler2D texture; -uniform int u_useTexture; uniform vec3 u_albedo; uniform vec3 u_ambient; uniform vec3 u_lightPos; @@ -12,15 +11,19 @@ varying vec3 f_position; varying vec3 f_normal; varying vec2 f_uv; +// cosine based palette, 4 vec3 params from http://www.iquilezles.org/www/articles/palettes/palettes.htm +vec3 palette( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d ) +{ + return a + b*cos( 6.28318*(c*t+d) ); +} + void main() { vec4 color = vec4(u_albedo, 1.0); - - if (u_useTexture == 1) { - color = texture2D(texture, f_uv); - } vec3 look = normalize(u_cameraPos-f_position); float d = dot(look, f_normal); - gl_FragColor = vec4(d * color.rgb * u_lightCol * u_lightIntensity + u_ambient, 1.0); + vec3 paletteColor = palette(d, vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5), vec3(1.0, 1.0, 1.0), vec3(0.00, 0.33, 0.67)); + + gl_FragColor = vec4(paletteColor * color.rgb * u_lightCol * u_lightIntensity + u_ambient, 1.0); } \ No newline at end of file diff --git a/src/glsl/pixellate-frag.glsl b/src/glsl/pixellate-frag.glsl index 8c593c3..2db2ea5 100644 --- a/src/glsl/pixellate-frag.glsl +++ b/src/glsl/pixellate-frag.glsl @@ -2,6 +2,7 @@ varying vec2 f_uv; uniform sampler2D tDiffuse; uniform float pixellateFactor; +// https://www.airtightinteractive.com/2013/02/intro-to-pixel-shaders-in-three-js/ void main() { vec2 p = f_uv.xy; diff --git a/src/glsl/vignette-frag.glsl b/src/glsl/vignette-frag.glsl index 2ea42cb..1e45c6e 100644 --- a/src/glsl/vignette-frag.glsl +++ b/src/glsl/vignette-frag.glsl @@ -4,7 +4,7 @@ uniform float u_offset; uniform float u_darkness; varying vec2 f_uv; -// uses +// https://www.airtightinteractive.com/2013/02/intro-to-pixel-shaders-in-three-js/ void main() { vec4 texel = texture2D(tDiffuse, f_uv); vec2 uv = (f_uv - vec2(0.5)) * vec2(u_offset); From 4172a3b9ec9a0f48145ff0641e503d6559a9040f Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Wed, 22 Feb 2017 03:11:26 -0500 Subject: [PATCH 5/7] pointilisim --- src/glsl/pointilism-frag.glsl | 20 +++++++++++++++++ src/post/index.js | 3 ++- src/post/pointilism.js | 41 +++++++++++++++++++++++++++++++++++ src/shaders/iridescent.js | 16 +------------- 4 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 src/glsl/pointilism-frag.glsl create mode 100644 src/post/pointilism.js diff --git a/src/glsl/pointilism-frag.glsl b/src/glsl/pointilism-frag.glsl new file mode 100644 index 0000000..a323a18 --- /dev/null +++ b/src/glsl/pointilism-frag.glsl @@ -0,0 +1,20 @@ +varying vec2 f_uv; +uniform sampler2D tDiffuse; + +float generateNoise(float x, float y) { + return fract(sin(dot(vec2(x,y), vec2(12.9898, 78.23))) * 43758.5453); +} + +void main() { + vec4 texel = texture2D(tDiffuse, f_uv); + vec3 col = texel.rgb; + + float darkness = (0.2126*col.r + 0.7152*col.g + 0.0722*col.b); + float noiseValue = generateNoise(texel.x, texel.y); + + if (noiseValue > darkness) { + gl_FragColor = vec4(darkness); + } else { + gl_FragColor = vec4(1.0); + } +} \ No newline at end of file diff --git a/src/post/index.js b/src/post/index.js index a4df485..872f0ca 100644 --- a/src/post/index.js +++ b/src/post/index.js @@ -19,4 +19,5 @@ export {default as Grayscale} from './grayscale' export {default as Random} from './random' export {default as Vignette} from './vignette' export {default as Fisheye} from './fisheye' -export {default as Pixellate} from './pixellate' \ No newline at end of file +export {default as Pixellate} from './pixellate' +export {default as Pointilism} from './pointilism' \ No newline at end of file diff --git a/src/post/pointilism.js b/src/post/pointilism.js new file mode 100644 index 0000000..1164e4b --- /dev/null +++ b/src/post/pointilism.js @@ -0,0 +1,41 @@ +const THREE = require('three'); +const EffectComposer = require('three-effectcomposer')(THREE) + +var options = { + pixellateFactor: 100.0 +} + +var Shader = new EffectComposer.ShaderPass({ + uniforms: { + // the texture the frame is rendered to before passing to the post processing shader + tDiffuse: { + type: 't', + value: null + } + }, + vertexShader: require('../glsl/pass-vert.glsl'), + fragmentShader: require('../glsl/pointilism-frag.glsl') +}); + +export default function Fisheye(renderer, scene, camera) { + + // this is the THREE.js object for doing post-process effects + var composer = new EffectComposer(renderer); + composer.addPass(new EffectComposer.RenderPass(scene, camera)); + composer.addPass(Shader); + + // set this to true on the shader for your last pass to write to the screen + Shader.renderToScreen = true; + + return { + initGUI: function(gui) { + gui.add(options, 'pixellateFactor').onChange(function(val) { + Shader.material.uniforms.pixellateFactor.value = val; + }); + }, + + render: function() {; + composer.render(); + } + } +} \ No newline at end of file diff --git a/src/shaders/iridescent.js b/src/shaders/iridescent.js index 4ebb408..2f325c4 100644 --- a/src/shaders/iridescent.js +++ b/src/shaders/iridescent.js @@ -7,8 +7,7 @@ var options = { lightColor: '#ffffff', lightIntensity: 2, albedo: '#dddddd', - ambient: '#111111', - useTexture: true + ambient: '#111111' } export default function(renderer, scene, camera) { @@ -27,9 +26,6 @@ export default function(renderer, scene, camera) { gui.addColor(options, 'ambient').onChange(function(val) { Shader.material.uniforms.u_ambient.value = new THREE.Color(val); }); - gui.add(options, 'useTexture').onChange(function(val) { - Shader.material.uniforms.u_useTexture.value = val; - }); }, material: new THREE.ShaderMaterial({ @@ -38,10 +34,6 @@ export default function(renderer, scene, camera) { type: "t", value: null }, - u_useTexture: { - type: 'i', - value: options.useTexture - }, u_albedo: { type: 'v3', value: new THREE.Color(options.albedo) @@ -71,11 +63,5 @@ export default function(renderer, scene, camera) { fragmentShader: require('../glsl/iridescent-frag.glsl') }) } - - // once the Mario texture loads, bind it to the material - textureLoaded.then(function(texture) { - Shader.material.uniforms.texture.value = texture; - }); - return Shader; } \ No newline at end of file From 0d3f17ec22271d4a0b66ed76bf55cff8a04ce06a Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Wed, 22 Feb 2017 03:32:38 -0500 Subject: [PATCH 6/7] tried hatching --- src/glsl/hatching-frag.glsl | 15 +++++++++++++++ src/post/hatching.js | 34 ++++++++++++++++++++++++++++++++++ src/post/index.js | 3 ++- src/post/pointilism.js | 7 ------- 4 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 src/glsl/hatching-frag.glsl create mode 100644 src/post/hatching.js diff --git a/src/glsl/hatching-frag.glsl b/src/glsl/hatching-frag.glsl new file mode 100644 index 0000000..16a6415 --- /dev/null +++ b/src/glsl/hatching-frag.glsl @@ -0,0 +1,15 @@ +varying vec2 f_uv; +uniform sampler2D tDiffuse; + +void main() { + vec4 texel = texture2D(tDiffuse, f_uv); + vec3 col = texel.rgb; + + float darkness = (0.2126*col.r + 0.7152*col.g + 0.0722*col.b); + float sinValX = sin(f_uv.x * 1000.0); + float sinValY = sin(f_uv.y * 1000.0); + + float hatching = darkness * sinValX * sinValY; + + gl_FragColor = vec4(hatching); +} \ No newline at end of file diff --git a/src/post/hatching.js b/src/post/hatching.js new file mode 100644 index 0000000..929f036 --- /dev/null +++ b/src/post/hatching.js @@ -0,0 +1,34 @@ +const THREE = require('three'); +const EffectComposer = require('three-effectcomposer')(THREE) + +var Shader = new EffectComposer.ShaderPass({ + uniforms: { + // the texture the frame is rendered to before passing to the post processing shader + tDiffuse: { + type: 't', + value: null + } + }, + vertexShader: require('../glsl/pass-vert.glsl'), + fragmentShader: require('../glsl/hatching-frag.glsl') +}); + +export default function Fisheye(renderer, scene, camera) { + + // this is the THREE.js object for doing post-process effects + var composer = new EffectComposer(renderer); + composer.addPass(new EffectComposer.RenderPass(scene, camera)); + composer.addPass(Shader); + + // set this to true on the shader for your last pass to write to the screen + Shader.renderToScreen = true; + + return { + initGUI: function(gui) { + }, + + render: function() {; + composer.render(); + } + } +} \ No newline at end of file diff --git a/src/post/index.js b/src/post/index.js index 872f0ca..8f388b7 100644 --- a/src/post/index.js +++ b/src/post/index.js @@ -20,4 +20,5 @@ export {default as Random} from './random' export {default as Vignette} from './vignette' export {default as Fisheye} from './fisheye' export {default as Pixellate} from './pixellate' -export {default as Pointilism} from './pointilism' \ No newline at end of file +export {default as Pointilism} from './pointilism' +export {default as Hatching} from './hatching' \ No newline at end of file diff --git a/src/post/pointilism.js b/src/post/pointilism.js index 1164e4b..023b83c 100644 --- a/src/post/pointilism.js +++ b/src/post/pointilism.js @@ -1,10 +1,6 @@ const THREE = require('three'); const EffectComposer = require('three-effectcomposer')(THREE) -var options = { - pixellateFactor: 100.0 -} - var Shader = new EffectComposer.ShaderPass({ uniforms: { // the texture the frame is rendered to before passing to the post processing shader @@ -29,9 +25,6 @@ export default function Fisheye(renderer, scene, camera) { return { initGUI: function(gui) { - gui.add(options, 'pixellateFactor').onChange(function(val) { - Shader.material.uniforms.pixellateFactor.value = val; - }); }, render: function() {; From d33c8548300002201652e69e25d23876916061fc Mon Sep 17 00:00:00 2001 From: gracexu94 Date: Wed, 22 Feb 2017 03:37:29 -0500 Subject: [PATCH 7/7] readme --- README.md | 130 +++--------------------------------------------------- 1 file changed, 7 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index 08c69b7..344f3f1 100644 --- a/README.md +++ b/README.md @@ -1,123 +1,7 @@ - -# Project 5: Shaders - -## Project Instructions - -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. - -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! - -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. - -Examples: [https://cis700-procedural-graphics.github.io/Project5-Shaders/](https://cis700-procedural-graphics.github.io/Project5-Shaders/) - -### 15 points each: Instagram-like filters - -- Tone mapping: - - Linear (+5 points) - - Reinhard (+5 points) - - Filmic (+5 points) -- Gaussian blur (no double counting with Bloom) -- Iridescence -- Pointilism -- Vignette -- Fish-eye bulge - -### 25 points each: -- Bloom -- Noise Warp -- Hatching -- Lit Sphere ([paper](http://www.ppsloan.org/publications/LitSphere.pdf)) - -### 37.5 points each: -- K-means color compression (unless you are extremely clever, the k-means clusterer has to be CPU side) -- Dithering -- Edge detection with Sobel filtering -- 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 (+17.5 points) - - Controlling Exposure (4 points) - - Side by side comparison between linear, Reinhard, filmic, and Uncharted2 (13.5 points). - -### 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` \ No newline at end of file +Implemented: +- Iridescence shader using IQ's color palette and formula from slides (15) +- Pointilism filter using old noise functions from Project 1 and slides(15) +- Vignette filter (15) +- Fish-eye filter (15) +- Pixellate filter (proposing 15??) +- attempted hatching filter (???) \ No newline at end of file