Text motion blur effect

Hello

We are two design students who are currently working extensively with typography in motion. Right now we have developed a font that we will present on a website that we are about to put together. Our vision is to have an interactive headline where our font is slowly moving and where the mouse’s presence affects the speed and the appearance of the text.

The example found in p5 / processing library - Math distance 1D has the same function as we want to achieve. So now we need help to imitate this as much as possible.

Briefly:

  • Is it possible to create the same effect with text?
  • Is it easiest to start from “Match distance 1D” and modulate it or is there a better solution?
  • All types of similar tutorials or guidance are appreciated as we are new to this type of coding.

Attaches pictures describing our question. All help is appreciated. Thanks in advance.

/D&E


http://p5js.org/examples/math-distance-1d.html

1 Like

This is our beginning of the code.
Just makes our text float from left to right. But now we want the speed and movement to be affected by the mouse position. Anyone knows how to do it?

/D&E

PFont font;
float x, y;
float dim = 80.0;

void setup()
{
  size (800, 600);
  font = loadFont("Dynamik60.vlw");
  textFont(font);
  fill (255);
  }
  
  void draw()
{ background (0);
  x = x + 3;
  if (x > width + dim) {
  x = -dim;
} 
  translate (x, height/2-dim/2);
  textSize(60);
  text("DYNAMIK", 0, 0);
}

Please look under P3

http://www.generative-gestaltung.de/1/code

2 Likes

Thanks Chrisir, good link.

But we couldn’t find anything useful there, maybe we don’t know what we looking for…

I think this could be a solution, have taken codes from different places.
Understand like 50%…
Is it possible to make different directions on different texts?

PFont font;
float x;
float y;
float dim = 280.0;

void setup()
{
  size (800, 600);
  font = loadFont("Dynamik60.vlw");
  textFont(font);
  fill (255);
  }
  
  void draw()
{ background (0);
  textAlign(CENTER);
  x = x + 0.4 + mouseX/10;
  
  if (x > width + dim + 300) {
  x = -dim;
} 
  translate (x - 250, height/2-dim/2);
  textSize(120);
  text("DYNAMIK", 0, 0);
  text("                            DYNAMIK", 0, 100);
text("                                                         DYNAMIK", 0, 200);
}

It is possible to edit the examples directly on the p5.js example pages to explore the effects you are interested in.

For example, here is a quick edit of the 1D example to change the rectangles into text. Changed lines are marked with comments.

let xpos1;
let xpos2;
let xpos3;
let xpos4;
let thin = 8;
let thick = 36;
let tsize = 200;  // define text size

function setup() {
  createCanvas(710, 400);
  noStroke();
  xpos1 = width / 2;
  xpos2 = width / 2;
  xpos3 = width / 2;
  xpos4 = width / 2;
  textSize(tsize);  // set text size
}

function draw() {
  background(255);
  background(255);

  let mx = mouseX * 0.4 - width / 5.0;

  fill(102);
  // rect(xpos2, 0, thick, height / 2);
  text("bold", xpos2, tsize);
  fill(204);
  // rect(xpos1, 0, thin, height / 2);
  text("bold", xpos1, tsize);
  fill(102);
  // rect(xpos4, height / 2, thick, height / 2);
  text("bold", xpos4, height/2 + tsize);
  fill(204);
  // rect(xpos3, height / 2, thin, height / 2);
  text("bold", xpos3, height/2 + tsize);

  xpos1 += mx / 16;
  xpos2 += mx / 64;
  xpos3 -= mx / 16;
  xpos4 -= mx / 64;

  if (xpos1 < -thin) {
    xpos1 = width;
  }
  if (xpos1 > width) {
    xpos1 = -thin;
  }
  if (xpos2 < -thick) {
    xpos2 = width;
  }
  if (xpos2 > width) {
    xpos2 = -thick;
  }
  if (xpos3 < -thin) {
    xpos3 = width;
  }
  if (xpos3 > width) {
    xpos3 = -thin;
  }
  if (xpos4 < -thick) {
    xpos4 = width;
  }
  if (xpos4 > width) {
    xpos4 = -thick;
  }
}
1 Like

Thank you Jeremy!

I solved in another way, perhaps you can do it several ways, but if you see something different in my code, please just correct me!

PFont font;
float xpos1;
float xpos2;
float xpos3;
int one = 0;


void setup()
{
  size (800, 600);
  surface.setResizable(true);
  font = loadFont("Dynamik120.vlw");
  textFont(font);
  fill (255);
  smooth();
  xpos1 = width/2;
  xpos2 = width/2;
  xpos3 = width/2;
  }
  
  void draw() {
    background (0);
    
  float mx = mouseX * 0.4 - width/5.0;
  
  text("Text", xpos1, 100);
  text("Text", xpos2, 300);
  text("Text", xpos3, 500);
 
  
  xpos1 += mx/2;
  xpos2 -= mx/1;
  xpos3 += mx/3;
  
  if(xpos1 < -500) { xpos1 = width;}
  if(xpos1 > width) { xpos1= -500;}
  if(xpos2 < -500) { xpos2 = width;}
  if(xpos2 > width) { xpos2= -500;}
  if(xpos3 < -500) { xpos3 = width;}
  if(xpos3 > width) { xpos3= -500;}

  }

Anyone else know how to create the motion blur effect? Tried with no success…

Thanks on behalf!

Now I have the code:

fill(0, 50); rect(0, 0, width, height);

and it created a semi-tran bg. And it leaving trails almost similar to a motion blur effect. Can it somehow become smoother or is it best to give up here…?

11

In case you’re okay with using shaders (PShader), I have a nice solution for you. Let me know.

helvete

2 Likes

I’m up for everything, what’s your solution? :slight_smile:

Okay, here you go. I use a graphics buffer (PGraphics) to draw the text onto. A graphics buffer is exactly like sketch surface you’re drawing on, but it’s “virtual” in a sense that you don’t see it until you display it like an image. If I didn’t use that and drew the text directly in the sketch window, the shader would act funny for some reason. This way the shader doesn’t see my text directly, but rather just as a pre-rendered image and it works great.

Save the following code as blurShader.glsl.
This shader is a modified version of Gene Kogan’s shader that you can find HERE.

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
 
#define PROCESSING_TEXTURE_SHADER
 
uniform sampler2D texture;
 
uniform vec2 texOffset;
uniform vec2 resolution;
 
varying vec4 vertColor;
varying vec4 vertTexCoord;
 
uniform float dx, dy;
uniform int blurSize;       
 
const float pi = 3.14159265;
 
void main() {  
	float xu = gl_FragCoord.x / resolution.x;
	float yu = gl_FragCoord.y / resolution.y;

	float numBlurPixelsPerSide = float(blurSize / 2); 
	float ssigma = blurSize / 4;

	vec2 blurMultiplyVec = vec2(dx, dy);
 
	vec3 incrementalGaussian;
	incrementalGaussian.x = 1.0 / (sqrt(2.0 * pi) * ssigma);
	incrementalGaussian.y = exp(-0.5 / (ssigma * ssigma));
	incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
 
	vec4 avgValue = vec4(0.0, 0.0, 0.0, 1.0);
	float coefficientSum = 0.0;
 
	avgValue += texture2D(texture, vertTexCoord.st) * incrementalGaussian.x;
	coefficientSum += incrementalGaussian.x;
	incrementalGaussian.xy *= incrementalGaussian.yz;
 
	for (float i = 1.0; i <= numBlurPixelsPerSide; i++) { 
		avgValue += texture2D(texture, vertTexCoord.st - i * texOffset * 
								blurMultiplyVec) * incrementalGaussian.x;         
		avgValue += texture2D(texture, vertTexCoord.st + i * texOffset * 
								blurMultiplyVec) * incrementalGaussian.x;         
		coefficientSum += 2.0 * incrementalGaussian.x;
		incrementalGaussian.xy *= incrementalGaussian.yz;
	}

	gl_FragColor = avgValue / coefficientSum;
}

And here’s the Processing code.
To achieve different results, change the blurSize to change the amount of blur and the blurAngle to control the direction of the motion blur (radians, not degrees!)

PFont font;
PShader blurShader;
PGraphics pgText;

void setup(){
	size(600, 400, P2D);

	noLoop();

	pgText = createGraphics(600, 400, P2D);

	font = createFont("Helvetica", 100);

	// define blur shader parameters
	blurShader = loadShader("blurShader.glsl");
	PVector blurVec = new PVector(1, 0); 
	int blurSize = 31;
	float blurAngle = 0;

	blurVec.rotate(blurAngle);
	blurShader.set("blurSize", blurSize);
	blurShader.set("dx", blurVec.x);
	blurShader.set("dy", blurVec.y);

	// Draw the text on the pgText buffer.
	pgText.beginDraw();
	pgText.clear();
	pgText.textAlign(CENTER, CENTER);
	pgText.background(19);
	pgText.textFont(font);
	pgText.textSize(100);
	pgText.noStroke();
	pgText.fill(244);
	pgText.text("HELVETE", 300, 200);
	pgText.endDraw();
}
	
void draw(){
	// use the blur shader
	shader(blurShader);

	// display the pgText surface to see the text
	image(pgText, 0, 0);
}
3 Likes

@patakk
can you please check on the rotation thing, i not understand what happens,
sometimes looks like the upper and lower part of a character rotates separately,
(mouseY)
is that wanted?

// https://discourse.processing.org/t/text-motion-blur-effect/10804/12
// https://github.com/genekogan/Processing-Shader-Examples/blob/master/TextureShaders/data/blur.glsl
// from: @patakk

PFont font;
PShader blurShader;
PGraphics pgText;
PVector blurVec = new PVector(1, 0); 
int blurSize = 31;
float blurAngle = 0;

void make_text(String instring) {
  pgText.beginDraw();                   // Draw the text on the pgText buffer.
  pgText.clear();
  pgText.textAlign(CENTER, CENTER);
  pgText.background(200,200,0);
  pgText.textFont(font);
  pgText.textSize(70);
  pgText.noStroke();
  pgText.fill(200,0,0);
  pgText.text(instring, 300, 200);
  pgText.endDraw();
}

void setup() {
  size(600, 400, P2D);
//  noLoop();
  pgText = createGraphics(800, 400, P2D);
  font = createFont("Helvetica", 70);
  blurShader = loadShader("data/blurShader.glsl");  // define blur shader parameters
  blurVec.rotate(blurAngle);
  blurShader.set("blurSize", blurSize);
  blurShader.set("dx", blurVec.x);
  blurShader.set("dy", blurVec.y);
  make_text("Processing 3.5.3");
  println("use mouse X and mouse Y");
}

void draw() {
  blurAngle = map( mouseY,0,height, 0,TAU);
  blurVec = new PVector(1, 0); 
  blurVec.rotate(blurAngle);
  blurShader.set("dx", blurVec.x);
  blurShader.set("dy", blurVec.y);
  blurSize = (int)map( mouseX,0,width, 0,40);
  blurShader.set("blurSize", blurSize);
  shader(blurShader);                    // use the blur shader
  image(pgText, 0, 0);                   // display the pgText surface to see the text
}

sometimes looks like the upper and lower part of a character rotates separately

I don’t see that, the blurring looks exactly like I’ve shown in the gif above. I’m running this on a Mac.