Skip to content

Commit

Permalink
Add shockwave shader
Browse files Browse the repository at this point in the history
  • Loading branch information
joebinns committed Jan 12, 2025
1 parent ee9b758 commit 81bdc8f
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 10 deletions.
13 changes: 13 additions & 0 deletions src/IntensityBasedCircleGridShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const IntensityBasedCircleGridShader = {
uniforms: {
tDiffuse: { value: null },
iResolution: { value: new THREE.Vector3(window.innerWidth, window.innerHeight, 1) },
iMouse: { value: new THREE.Vector2(0.0, 0.0) },
iTime: { value: 0.0 },
GRID_WIDTH: { value: 48.0 },
MIN_RADIUS: { value: 0.0 },
MAX_RADIUS: { value: 1.0 },
Expand All @@ -29,6 +31,8 @@ const IntensityBasedCircleGridShader = {
fragmentShader: [`
uniform sampler2D tDiffuse;
uniform vec3 iResolution;
uniform vec2 iMouse;
uniform float iTime;
uniform float GRID_WIDTH;
uniform float MIN_RADIUS;
Expand All @@ -39,6 +43,8 @@ const IntensityBasedCircleGridShader = {
varying vec2 vUv;
const float PI = 3.14;
float circle(in vec2 st, in float radius)
{
float dist = length(st - 0.5);
Expand All @@ -58,17 +64,24 @@ const IntensityBasedCircleGridShader = {
void main()
{
vec2 mc = iMouse * 0.5 + vec2(0.5);
vec2 gv = (vUv - 0.5) * iResolution.xy / iResolution.x;
vec2 ouv = gv + 0.5;
gv = fract(gv * GRID_WIDTH);
ouv = floor(ouv * GRID_WIDTH) / GRID_WIDTH;
// Mouse
float blur = 50.0 / iResolution.y;
float r = 0.08 + 0.01 * cos(PI * iTime);
float col = smoothstep( r+blur, r-blur, length( mc - ouv ));
float mask = 0.0;
for (float y = -1.0; y <= 1.0; y++) {
for (float x = -1.0; x <= 1.0; x++) {
vec2 offset = vec2(x, y);
vec3 texCol = texture2D(tDiffuse, ouv + offset / GRID_WIDTH).rgb;
float intensity = intensity(texCol);
intensity = ceil(intensity) * max(intensity, col);
float radius = remap(MIN_INTENSITY, MAX_INTENSITY, MIN_RADIUS, MAX_RADIUS, intensity * intensity);
mask = max(mask, circle(gv - offset, radius));
}
Expand Down
51 changes: 41 additions & 10 deletions src/ModelPreviewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { BloomPass } from "bloom-pass";

// Custom shaders
import { OutlinePass } from '../src/OutlinePass.js';
import { ShockwaveShader } from "../src/ShockwaveShader.js";
import { IntensityBasedCircleGridShader } from "../src/IntensityBasedCircleGridShader.js";


let scene, camera, renderer, composer, outline, bloom, intensityBasedCircleGrid, objects, clock, time, mouse, picker, hoverRate, appearRate, hovered, speed, maximumDisplacement, angularSpeed, defaultAngularSpeed, angularDamper, preview;
let scene, camera, renderer, composer, outline, bloom, shockwave, shockwaveTime, intensityBasedCircleGrid, objects, clock, time, mouse, picker, hoverRate, appearRate, hovered, speed, maximumDisplacement, angularSpeed, defaultAngularSpeed, angularDamper, preview;

function SetObjectVisibility(object, visible) {
object.visible = visible;
Expand Down Expand Up @@ -74,28 +74,45 @@ function onWindowResize() {

renderer.setSize(dimensions1.width, dimensions1.height);
composer.setSize(dimensions1.width, dimensions1.height);
shockwave.setSize(dimensions1.width, dimensions1.height);
intensityBasedCircleGrid.setSize(dimensions1.width, dimensions1.height);
outline.setSize(dimensions1.width, dimensions1.height);


shockwave.uniforms.iResolution.value.set(
dimensions1.width,
dimensions1.height
);

intensityBasedCircleGrid.uniforms.iResolution.value.set(
dimensions1.width,
dimensions1.height
);
}

function onDocumentMouseMove(event) {
mouse.x = (event.clientX / dimensions().width) * 2 - 1;
mouse.y = -((event.clientY - 65) / dimensions().height) * 2 + 1;
const dimensions1 = dimensions();
mouse.x = (event.clientX / dimensions1.width) * 2 - 1;
mouse.y = -((event.clientY - 65) / dimensions1.height) * 2 + 1;
}

function onDocumentMouseDown(event) {
let object = picker.picked;
if (object) {
// Click
angularSpeed += (defaultAngularSpeed * 25);
angularSpeed += (defaultAngularSpeed * 20);

shockwave.uniforms.iMouse.value.set(
mouse.x,
mouse.y
);
shockwaveTime = 0;

}
}

function onDocumentMouseUp(event) {
}

export class ModelPreviewer{
constructor(portfolioItems) {
this.portfolioItems = portfolioItems;
Expand All @@ -107,6 +124,7 @@ export class ModelPreviewer{
// Timer
clock = new THREE.Clock();
time = 0;
shockwaveTime = 10;

// Controller
mouse = new THREE.Vector2();
Expand Down Expand Up @@ -148,13 +166,13 @@ export class ModelPreviewer{
dimensions().width,
dimensions().height
);
composer = new EffectComposer(renderer, renderTarget);

composer = new EffectComposer(renderer, renderTarget);

// Render pass
// Skipping the regular render pass as to only render an outline.

// Post processing

// Outline
outline = new OutlinePass(
new THREE.Vector2(dimensions().width, dimensions().height),
Expand All @@ -169,7 +187,11 @@ export class ModelPreviewer{
// Multiple scalar values packed into one uniform: Depth bias, depth multiplier
uniforms.multiplierParameters.value.x = 0.5;
uniforms.multiplierParameters.value.y = 50;


// Shockwave
shockwave = new ShaderPass(ShockwaveShader);
composer.addPass(shockwave);

// Bloom
bloom = new BloomPass(1.5, 25, 4); // Strength, Kernel Size, Sigma
composer.addPass(bloom);
Expand Down Expand Up @@ -199,6 +221,7 @@ export class ModelPreviewer{
// Subscribe to events
document.addEventListener('mousemove', onDocumentMouseMove, false);
document.addEventListener('mousedown', onDocumentMouseDown, false);
document.addEventListener('mouseup', onDocumentMouseUp, false);
window.addEventListener('resize', onWindowResize);
onWindowResize();
}
Expand All @@ -210,6 +233,14 @@ export class ModelPreviewer{
// Update time
let deltaTime = clock.getDelta();
time += deltaTime;
shockwaveTime += deltaTime;

shockwave.uniforms.iTime.value = shockwaveTime;
intensityBasedCircleGrid.uniforms.iTime.value = shockwaveTime;
intensityBasedCircleGrid.uniforms.iMouse.value.set(
mouse.x,
mouse.y
);

// Set appeared per item
let isAnyElementHovered = false;
Expand Down Expand Up @@ -272,7 +303,7 @@ export class ModelPreviewer{
objects.position.y = maximumDisplacement * Math.sin(time * speed);
objects.rotation.y += deltaTime * angularSpeed;


// Render final scene
composer.render();
}
}
86 changes: 86 additions & 0 deletions src/ShockwaveShader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as THREE from "three";

const ShockwaveShader = {

name: 'ShockwaveShader',

uniforms: {
tDiffuse: { value: null },
iResolution: { value: new THREE.Vector3(window.innerWidth, window.innerHeight, 1) },
iMouse: { value: new THREE.Vector2(0.0, 0.0) },
iTime: { value: 10.0 }
},

vertexShader: [`
varying vec2 vUv;
void main()
{
gl_Position = vec4(position.xy, 0.0, 1.0);
vUv = uv;
}
`].join( "\n" ),

fragmentShader: [`
uniform sampler2D tDiffuse;
uniform vec3 iResolution;
uniform vec2 iMouse;
uniform float iTime;
varying vec2 vUv;
void main()
{
float WaveParam1 = 20.0;
float WaveParam2 = 0.8;
float WaveParam3 = 0.12;
vec2 texCoord = vUv;
vec4 Color = texture2D(tDiffuse, texCoord);
//Use this if you want to place the centre with the mouse instead
vec2 WaveCentre = iMouse * 0.5 + vec2(0.5);
float ratio = iResolution.y / iResolution.x;
float Dist = distance(
vec2(texCoord.x, texCoord.y * ratio),
vec2(WaveCentre.x, WaveCentre.y * ratio)
);
//Below is optional and a change from the original but to my eyes it looks better,
// it effectively removes the first few frames of the "animation"
Dist = max(Dist, 0.12);
//Sawtooth function to pulse from centre
float CurrentTime = iTime * 0.8;
//Only distort the pixels within the parameter distance from the centre
if ((Dist <= ((CurrentTime) + (WaveParam3))) &&
(Dist >= ((CurrentTime) - (WaveParam3))))
{
//The pixel offset distance based on the input parameters
float Diff = (Dist - CurrentTime);
float ScaleDiff = (1.0 - pow(abs(Diff * WaveParam1), WaveParam2));
float DiffTime = (Diff * ScaleDiff);
//The direction of the distortion
vec2 DiffTexCoord = normalize(texCoord - WaveCentre);
//Perform the distortion and reduce the effect over time
texCoord += ((DiffTexCoord * DiffTime) / (CurrentTime * Dist * 50.0));
Color = texture2D(tDiffuse, texCoord);
//Blow out the color and reduce the effect over time
Color += (Color * ScaleDiff) / (CurrentTime * Dist * 50.0);
}
//gl_FragColor = Color;
gl_FragColor = texture2D(tDiffuse, texCoord);
}
`
].join( "\n" )
};

export { ShockwaveShader };

0 comments on commit 81bdc8f

Please sign in to comment.
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy