Skip to content

Instantly share code, notes, and snippets.

@wschutzer
Last active November 23, 2024 19:59
Show Gist options
  • Save wschutzer/dd5827e77c771caaf770458348c9e17d to your computer and use it in GitHub Desktop.
Save wschutzer/dd5827e77c771caaf770458348c9e17d to your computer and use it in GitHub Desktop.
Motion Blur Template
/* Motion Blur Template
* ---------------------
* This code uses shaders to aproximate the motion blur effect by averaging the pixels along a sequence
* of frames.
*
* Copyright (C) 2024 Waldeck Schutzer (@infinitymathart)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
final boolean recording = false;
final int duration = 2; // Seconds
final int fps = 60; // Frames Per Second
final float num_frames = fps*duration;
// Motion blur:
final int samples_per_frame = 10; // How many frames to average?
final float shutter_angle = 1.5; // How distant the frames are in time?
final int frameWidth = recording ? 2160 : 800;
final float fac = 1.0*frameWidth/800;
float t = 0; // Normalized animation time in the interval 0 - 1.
PShader motionBlur;
PGraphics gtex0; // Each frame is drawn here
// Vertex shader code
String[] motionBlurVertShader = {
"#version 100",
"#define PROCESSING_TEXTURE_SHADER",
"uniform mat4 transformMatrix;",
"uniform mat4 texMatrix;",
"attribute vec4 position;",
"attribute vec4 color;",
"attribute vec2 texCoord;",
"varying vec4 vertColor;",
"varying vec4 vertTexCoord;",
"void main() {",
"gl_Position = transformMatrix * position;",
"vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);",
"vertColor = color;",
"}"};
String[] motionBlurFragShader = {
"#version 100",
"#ifdef GL_ES",
"precision mediump float;",
"precision mediump int;",
"#endif",
"#define PROCESSING_TEXTURE_SHADER",
"uniform sampler2D texture; // Source and result frame, works as an accumulator",
"uniform sampler2D tex0; // Currently drawn frame to be added",
"uniform float alpha;",
"uniform float beta;",
"varying vec4 vertColor; // Seems to be white",
"varying vec4 vertTexCoord;",
"void main()",
"{",
" vec4 curColor = texture2D(tex0, vertTexCoord.xy); // Color of current pixel ",
" vec4 accColor = texture2D(texture, vertTexCoord.xy); // Color in accumulator",
" gl_FragColor = beta*(alpha*accColor + curColor); // Blending",
"}"};
void settings()
{
size(frameWidth, frameWidth, P2D); // Use P2D renderer for shader support
}
void setup()
{
gtex0 = createGraphics(width, height, P2D);
motionBlur = new PShader(this, motionBlurVertShader, motionBlurFragShader);
}
void draw()
{
background(0);
for(int i=0; i<samples_per_frame; i++)
{
t = map((recording ? 1.0*(frameCount-1): 1.0*mouseX/width*num_frames) + i*shutter_angle/samples_per_frame, 0, num_frames, 0, 1)%1;
draw_(gtex0,t); // Draw on gtex1
motionBlur.set("tex0", gtex0);
motionBlur.set("alpha", (float)(i));
motionBlur.set("beta", (float)(1.0/(i+1)));
filter(motionBlur); // Averages the frames with a moving average
}
if (recording)
{
saveFrame("/tmp/f/frame_####.png");
if (frameCount >= num_frames)
exit();
}
}
void draw_(PGraphics g,float t)
{
g.beginDraw();
g.background(0); // Clear the canvas
g.noStroke();
g.fill(255, 0, 0);
// Draw a moving circle
float x = width / 2 + cos(TAU*t) * 200*fac;
float y = height / 2 + sin(TAU*t) * 200*fac;
g.ellipse(x, y, 50*fac, 50*fac);
g.endDraw();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment