Added noise to coloration passes, removed film grain pass. Added ImageOverlayPass option; effect can be specified in URL variables.

This commit is contained in:
Rezmason
2018-09-03 20:04:42 -07:00
parent a644133c1e
commit 7bf43539c1
7 changed files with 118 additions and 112 deletions

View File

@@ -5,10 +5,16 @@ Migrate rain logic to shaders that operate on double buffer RTTs
Reach out to Ashley's partner about producing sounds Reach out to Ashley's partner about producing sounds
Much later: Much later:
Optimization: calculate texture derivatives on CPU, pass in as a uniform Optimizations
Optimization: simpler bloom replacement calculate texture derivatives on CPU, pass in as a uniform
simpler bloom replacement
Dissolve threejs project into webgl project Dissolve threejs project into webgl project
Maybe webgl2 project? Maybe webgl2 project?
Deluxe
Flashing row effect? Flashing row effect?
https://youtu.be/z_KmNZNT5xw?t=16
Square event?
https://youtu.be/ngnlBZNuVb8?t=200
https://youtu.be/721sG2D_9-U?t=67
More patterns? More patterns?
Symbol duplication is common Symbol duplication is common

View File

@@ -9,9 +9,9 @@
<script src="./js/ColorMapPass.js"></script> <script src="./js/ColorMapPass.js"></script>
<script src="./js/HorizontalColorationPass.js"></script> <script src="./js/HorizontalColorationPass.js"></script>
<script src="./js/FilmGrainPass.js"></script>
<script src="./js/LuminosityHighPassShader.js"></script> <script src="./js/LuminosityHighPassShader.js"></script>
<script src="./js/UnrealBloomPass.js"></script> <script src="./js/UnrealBloomPass.js"></script>
<script src="./js/ImageOverlayPass.js"></script>
<script src="./js/MatrixMaterial.js"></script> <script src="./js/MatrixMaterial.js"></script>
<script src="./js/MatrixGeometry.js"></script> <script src="./js/MatrixGeometry.js"></script>
@@ -33,6 +33,8 @@
const b = parseFloat(getParam("b", 1.125)); const b = parseFloat(getParam("b", 1.125));
const c = parseFloat(getParam("c", 1.25)); const c = parseFloat(getParam("c", 1.25));
const effect = getParam("effect", "plain");
document.ontouchmove = (e) => e.preventDefault(); document.ontouchmove = (e) => e.preventDefault();
const element = document.createElement("matrixcode"); const element = document.createElement("matrixcode");
document.body.appendChild(element); document.body.appendChild(element);
@@ -56,46 +58,53 @@
glyphSequenceLength, glyphSequenceLength,
}); });
// const stupidMaterial = new THREE.MeshBasicMaterial( { map: texture, flatShading: false, transparent:false } );
const mesh = new THREE.Mesh( geometry, material ); const mesh = new THREE.Mesh( geometry, material );
scene.add(mesh); scene.add(mesh);
composer.addPass( new THREE.RenderPass( scene, camera ) ); composer.addPass( new THREE.RenderPass( scene, camera ) );
const bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.15, 0.3 ); const bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 2, 0.5, 0.3 );
composer.addPass( bloomPass ); composer.addPass( bloomPass );
const colorMap = new THREE.ColorMapPass([ switch (effect) {
case "plain":
composer.addPass(new THREE.ColorMapPass([
{color: new THREE.Vector3(0.00, 0.00, 0.00), at: 0.0}, {color: new THREE.Vector3(0.00, 0.00, 0.00), at: 0.0},
{color: new THREE.Vector3(0.05, 0.52, 0.17), at: 0.4}, {color: new THREE.Vector3(0.05, 0.52, 0.17), at: 0.4},
{color: new THREE.Vector3(0.12, 0.82, 0.37), at: 0.8}, {color: new THREE.Vector3(0.12, 0.82, 0.37), at: 0.8},
{color: new THREE.Vector3(0.29, 1.00, 0.64), at: 1.0}, {color: new THREE.Vector3(0.29, 1.00, 0.64), at: 1.0},
]); ], 0.1));
composer.addPass( colorMap ); break;
case "pride":
const horizontalColoration = new THREE.HorizontalColorationPass([ composer.addPass(new THREE.HorizontalColorationPass([
new THREE.Vector3(1, 0, 0), new THREE.Vector3(1, 0, 0),
new THREE.Vector3(1, 0.5, 0),
new THREE.Vector3(1, 1, 0), new THREE.Vector3(1, 1, 0),
new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 1, 0),
new THREE.Vector3(0, 1, 1),
new THREE.Vector3(0, 0, 1), new THREE.Vector3(0, 0, 1),
new THREE.Vector3(1, 0, 1), new THREE.Vector3(0.8, 0, 1),
], 0.1));
break;
case "customStripes":
const flagColorData = getParam("colors", "0.4,0.15,0.1,0.4,0.15,0.1,0.8,0.8,0.6,0.8,0.8,0.6,1.0,0.7,0.8,1.0,0.7,0.8,").split(",").map(parseFloat);
const numFlagColors = Math.floor(flagColorData.length / 3);
const colors = [];
for (let i = 0; i < numFlagColors; i++) {
colors.push(new THREE.Vector3(flagColorData[i * 3 + 0], flagColorData[i * 3 + 1], flagColorData[i * 3 + 2]));
}
composer.addPass(new THREE.HorizontalColorationPass(colors, 0.1));
break;
case "none":
break;
case "image":
const imageURL = getParam("url", "https://upload.wikimedia.org/wikipedia/commons/0/0a/Flammarion_Colored.jpg");
window.texture2 = new THREE.TextureLoader().load( imageURL );
composer.addPass(new THREE.ImageOverlayPass(texture2));
break;
}
composer.passes.filter(pass => !pass.enabled).renderToScreen = false;
// new THREE.Vector3(1, 0, 0.5), composer.passes.filter(pass => pass.enabled).pop().renderToScreen = true;
// new THREE.Vector3(1, 0, 0.5),
// new THREE.Vector3(0.5, 0, 1),
// new THREE.Vector3(0.5, 0, 1),
// new THREE.Vector3(0.25, 0.25, 1),
// new THREE.Vector3(0.25, 0.25, 1),
]);
// composer.addPass(horizontalColoration);
const blurMag = 0.0001;
const ditherMag = 0.075;
const filmGrainPass = new THREE.FilmGrainPass(blurMag, ditherMag);
composer.addPass(filmGrainPass);
const windowResize = () => { const windowResize = () => {
const [width, height] = [window.innerWidth, window.innerHeight]; const [width, height] = [window.innerWidth, window.innerHeight];
@@ -122,8 +131,7 @@
const render = () => { const render = () => {
requestAnimationFrame(render); requestAnimationFrame(render);
const now = Date.now(); update(Date.now());
update(now);
composer.render(); composer.render();
} }
render(); render();

View File

@@ -11,7 +11,7 @@ const easeInOutQuad = input => {
return 1 - 2 * input * input; return 1 - 2 * input * input;
} }
THREE.ColorMapPass = function (entries) { THREE.ColorMapPass = function (entries, ditherMagnitude = 1) {
const colors = Array(256).fill().map(_ => new THREE.Vector3()); const colors = Array(256).fill().map(_ => new THREE.Vector3());
const sortedEntries = entries.slice().sort((e1, e2) => e1.at - e2.at).map(entry => ({ const sortedEntries = entries.slice().sort((e1, e2) => e1.at - e2.at).map(entry => ({
color: entry.color, color: entry.color,
@@ -44,7 +44,8 @@ THREE.ColorMapPass = function (entries) {
this.shader = { this.shader = {
uniforms: { uniforms: {
tDiffuse: { value: null }, tDiffuse: { value: null },
tColorData: { value: this.dataTexture } tColorData: { value: this.dataTexture },
ditherMagnitude: { value: ditherMagnitude }
}, },
vertexShader: ` vertexShader: `
@@ -56,15 +57,21 @@ THREE.ColorMapPass = function (entries) {
`, `,
fragmentShader: ` fragmentShader: `
#define PI 3.14159265359
uniform sampler2D tDiffuse; uniform sampler2D tDiffuse;
uniform sampler2D tColorData; uniform sampler2D tColorData;
uniform float ditherMagnitude;
varying vec2 vUv; varying vec2 vUv;
highp float rand( const in vec2 uv ) {
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
return fract(sin(sn) * c);
}
void main() { void main() {
gl_FragColor = vec4( gl_FragColor = texture2D( tColorData, vec2( texture2D( tDiffuse, vUv ).r - rand( gl_FragCoord.xy ) * ditherMagnitude, 0.0 ) );
texture2D( tColorData, vec2( texture2D( tDiffuse, vUv ).r, 0.0 ) ).rgb,
1.0
);
} }
` `
}; };

View File

@@ -1,60 +0,0 @@
/**
* @author rezmason
*/
THREE.FilmGrainPass = function (blurMagnitude, ditherMagnitude) {
this.shader = {
uniforms: {
tDiffuse: { value: null },
blurMagnitude: { value: blurMagnitude },
ditherMagnitude: { value: ditherMagnitude }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( position, 1.0 );
}
`,
fragmentShader: `
#define PI 3.14159265359
uniform sampler2D tDiffuse;
uniform float blurMagnitude;
uniform float ditherMagnitude;
varying vec2 vUv;
highp float rand( const in vec2 uv ) {
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
return fract(sin(sn) * c);
}
vec3 dithering( vec3 color1, vec3 color2 ) {
float difference = pow(length(color1 - color2), 0.1);
return color1 + vec3( -1, 0.5, 0.5 ) * ditherMagnitude * difference * mix( -1.0, 1.0, rand( gl_FragCoord.xy ) );
}
void main() {
vec4 sample = texture2D( tDiffuse, vUv );
vec4 blurSum = vec4( 0.0 );
blurSum += texture2D( tDiffuse, vUv + vec2(-blurMagnitude, -blurMagnitude) ) * 0.25;
blurSum += texture2D( tDiffuse, vUv + vec2( blurMagnitude, -blurMagnitude) ) * 0.25;
blurSum += texture2D( tDiffuse, vUv + vec2(-blurMagnitude, blurMagnitude) ) * 0.25;
blurSum += texture2D( tDiffuse, vUv + vec2( blurMagnitude, blurMagnitude) ) * 0.25;
gl_FragColor = vec4(dithering(blurSum.rgb, sample.rgb), 1.0);
}
`
};
THREE.ShaderPass.call(this, this.shader);
};
THREE.FilmGrainPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
constructor: THREE.FilmGrainPass,
render: THREE.ShaderPass.prototype.render
});

View File

@@ -2,7 +2,7 @@
* @author rezmason * @author rezmason
*/ */
THREE.HorizontalColorationPass = function (colors) { THREE.HorizontalColorationPass = function (colors, ditherMagnitude = 1) {
const values = new Uint8Array([].concat(...colors.map(color => color.toArray().map(component => Math.floor(component * 255))))); const values = new Uint8Array([].concat(...colors.map(color => color.toArray().map(component => Math.floor(component * 255)))));
this.dataTexture = new THREE.DataTexture( this.dataTexture = new THREE.DataTexture(
@@ -19,6 +19,7 @@ THREE.HorizontalColorationPass = function (colors) {
uniforms: { uniforms: {
tDiffuse: { value: null }, tDiffuse: { value: null },
tColorData: { value: this.dataTexture }, tColorData: { value: this.dataTexture },
ditherMagnitude: { value: ditherMagnitude },
}, },
vertexShader: ` vertexShader: `
@@ -30,13 +31,22 @@ THREE.HorizontalColorationPass = function (colors) {
`, `,
fragmentShader: ` fragmentShader: `
#define PI 3.14159265359
uniform sampler2D tDiffuse; uniform sampler2D tDiffuse;
uniform sampler2D tColorData; uniform sampler2D tColorData;
uniform float ditherMagnitude;
varying vec2 vUv; varying vec2 vUv;
highp float rand( const in vec2 uv ) {
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
return fract(sin(sn) * c);
}
void main() { void main() {
float value = texture2D(tDiffuse, vUv).r; float value = texture2D(tDiffuse, vUv).r;
vec3 value2 = texture2D(tColorData, vUv).rgb; vec3 value2 = texture2D(tColorData, vUv).rgb - rand( gl_FragCoord.xy ) * ditherMagnitude;
gl_FragColor = vec4(value2 * value, 1.0); gl_FragColor = vec4(value2 * value, 1.0);
} }
` `

41
js/ImageOverlayPass.js Normal file
View File

@@ -0,0 +1,41 @@
/**
* @author rezmason
*/
THREE.ImageOverlayPass = function (texture) {
this.texture = texture;
this.shader = {
uniforms: {
tDiffuse: { value: null },
map: { value: this.texture },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( position, 1.0 );
}
`,
fragmentShader: `
uniform sampler2D tDiffuse;
uniform sampler2D map;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(texture2D(map, vUv).rgb * (pow(texture2D(tDiffuse, vUv).r, 1.5) * 0.995 + 0.005), 1.0);
}
`
};
THREE.ShaderPass.call(this, this.shader);
};
THREE.ImageOverlayPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
constructor: THREE.ImageOverlayPass,
render: function() {
this.uniforms[ "map" ].value = this.texture;
THREE.ShaderPass.prototype.render.call(this, ...arguments);
}
});

View File

@@ -89,12 +89,6 @@ const makeMatrixGeometry = ({
const delta = ((isNaN(last) || now - last > 1000) ? 0 : now - last) / 1000 * animationSpeed; const delta = ((isNaN(last) || now - last > 1000) ? 0 : now - last) / 1000 * animationSpeed;
last = now; last = now;
bloomPass.enabled = delta < minimumPostProcessingFrameTime;
filmGrainPass.enabled = delta < minimumPostProcessingFrameTime;
composer.passes.filter(pass => !pass.enabled).renderToScreen = false;
composer.passes.filter(pass => pass.enabled).pop().renderToScreen = true;
const simTime = now * animationSpeed * fallSpeed * 0.0005; const simTime = now * animationSpeed * fallSpeed * 0.0005;
for (const column of columns) { for (const column of columns) {