I have asked a lot of people but no one knows this effect


https://www.instagram.com/p/CMxUWEBhmEY/?utm_source=ig_web_copy_link&igsh=MzRlODBiNWFlZA==

Do you know how to make this effect? I have asked a lot of people but no one knows…
So far people said it maybe sin waves, noise… What do you think! Thank you!

1 Like

Welcome to the forum!

I’m unfortunately not able to give you any satisfying and concrete answer.

Judging by the extensive – and really great – typographic experiments on show by that designer, it feels that it’s the result of years-long code snippets used to generate type transformations, all layered together. So I don’t believe you’ll find any single algorithm out there to recreate this.

After seeing the type in motion, I’ll also say that it gives off hefty late-90s Demoscene vibes. I certainly “owned” several games and applications during that time – uhm… found at… sources… – with that type of aesthetic on their splash screen.

As a test, I let ChatGPT analyze the screenshot and recreate the result. With zero surprise, it made nothing close to the original. I nudged it to tweak the code a few times and it eventually come up with this. That’s after a few iterations of lazy prompt tweaking and generating. Zero manual interventions to the code from my side.

(Alas, I won’t post that code here, as I’m not sure on the current forum policy concerning LLM stuff. Though letting GTP generate a base sketch to build off of, could be an approach to take.)

EDIT: Language

OHgpt

2 Likes

Thank u so much for your reply! I think it is getting closer, I spent whole day research , so far I have found sth. So maybe I can also share it here.

1 Like

also Andreion de Castro on Instagram: ""LIGHTS&COLORS" Some recent favourites exploring the theme of lights and colours :) https://www.behance.net/gallery/185734307/LIGHTS-COLOURS"

2 Likes

It looks complicated.

Maybe several effects are at work here

Maybe some kind of lense moving over a changing background from left to right

1 Like

Thanks! Looking for more answers

1 Like

If you follow the link you provided in the original post the creator states

this piece of typographic gymnastics is a snippet of a code + graphic design tutorial page I am developing

why not look at the tutorial? After all she has had 10 months to finish it :grin:

1 Like

Yes i also noticted that, but i didn’t find the tutorial. can you?

No but then I don’t have an Instagram account ! :smile:

I think @eightohnine had it right with this

This is original work based on the skill and imagination of the programmer it is unlikely it can be reproduced without assistance from the creator.

It seems to me that the Processing tutorial you posted is a good starting point to experiment with ‘Kinetic Typography’ although a lot of research and experimentation is required to get anywhere close to the creations of Andreion de Castro

1 Like

Did you ask the author on Instagram?

Maybe this code does help you

You need to install geomerative library and then you have access to the points of each letter.

(Sketch not by me, but from the forum)

So what you have to do:

  • create a background made from rects with a color gradient
  • draw letters on it using their points to create rects with another a color gradient
  • and let a lens / magnifying class pass over this image
  • Google everything here on the forum

Warm regards,

Chrisir



import geomerative.*;
// import processing.sound.*;

// ----------------------------------------------------------------------------------------------------

// SoundFile[] file;

Clock[][] clocks;
String[] words = {
  "fire me", "hire me", "desire me", "disattire me",
  "inspire me", "exquire me", "admire me", "dewire me"
};
String[][] tokens;
RFont text;
RShape[][] shapes;
int splitGlyph = 500;
int inc = 200;

RPoint[][][] points;
float[][][] shiftPntX;
float[][][] shiftPntY;

float timeFactor = 6000;
float morphDuration;
PGraphics pg;

int morph = 0;
boolean run = false;
boolean forward = true;
float diam = 0;
int currentMorph = 0;
long pauseStartTime = 0;
boolean isPaused = false;
long morphStartTime = 0;

// Store positions for the fixed phrases
float[][][] posStaticX;
float[][][] posStaticY;
boolean[] showStatic;
float[] staticAlpha;
boolean fadingOut = false;

void setup() {
  fullScreen();
  smooth(4);

  tokens = new String[words.length][];
  shapes = new RShape[words.length][];
  points = new RPoint[words.length][][];

  for (int i = 0; i < words.length; i++) {
    tokens[i] = splitTokens(words[i]);
    shapes[i] = new RShape[tokens[i].length];
    points[i] = new RPoint[tokens[i].length][splitGlyph];
  }

  clocks = new Clock[tokens[0].length][splitGlyph];
  shiftPntX = new float[tokens[0].length][inc * words.length][splitGlyph];
  shiftPntY = new float[tokens[0].length][inc * words.length][splitGlyph];

  posStaticX = new float[words.length][tokens[0].length][splitGlyph];
  posStaticY = new float[words.length][tokens[0].length][splitGlyph];
  showStatic = new boolean[words.length];
  staticAlpha = new float[words.length];

  RG.init(this);
  text = new RFont("FREESCPT.TTF", 150, RIGHT);

  float frac = 1.0 / splitGlyph;

  for (int w = 0; w < words.length; w++) {
    for (int i = 0; i < tokens[w].length; i++) {
      shapes[w][i] = text.toShape(tokens[w][i]);
      for (int j = 0; j < splitGlyph; j++) {
        points[w][i][j] = shapes[w][i].getPoint(j * frac);
        if (w == 0) {
          float offsetMinutes = 7.5;
          float offsetHours = 24;
          float startHours = offsetHours * j * 1 / 8;
          float startMinutes = j * offsetMinutes;
          clocks[i][j] = new Clock(points[w][i][j].x, points[w][i][j].y, startHours, startMinutes, color(200, 200, 0, 10));
        }
      }
    }
  }

  for (int i = 0; i < tokens[0].length; i++) {
    for (int k = 0; k < inc; k++) {
      for (int j = 0; j < splitGlyph; j++) {
        for (int w = 0; w < words.length - 1; w++) {
          if (points[w][i][j] != null && points[w + 1][i][j] != null) {
            shiftPntX[i][k + w * inc][j] = lerp(points[w][i][j].x, points[w + 1][i][j].x, k * (1.0 / inc));
            shiftPntY[i][k + w * inc][j] = lerp(points[w][i][j].y, points[w + 1][i][j].y, k * (1.0 / inc));
          }
        }
        if (points[words.length - 1][i][j] != null && points[0][i][j] != null) {
          shiftPntX[i][k + (words.length - 1) * inc][j] = lerp(points[words.length - 1][i][j].x, points[0][i][j].x, k * (1.0 / inc));
          shiftPntY[i][k + (words.length - 1) * inc][j] = lerp(points[words.length - 1][i][j].y, points[0][i][j].y, k * (1.0 / inc));
        }
      }
    }
  }

  morph = 0;
  morphStartTime = millis();

  // Calculate morph duration to ensure equal timing
  morphDuration = (float) (12000.0 / words.length);

  for (int w = 0; w < words.length; w++) {
    // ???  showStatic[w]=true;
  }

  // file = new SoundFile[5];
  for (int i = 0; i < 5; i++) {
    // file[i] = new SoundFile(this, "Essais_piano_01.wav");
    //file[i].jump(i * file[i].duration() / 25); /// ????
    //file[i].amp(0.0001);
    //file[i].play();
  }
}

void draw() {
  background(0);
  translate(width / 2, 150);

  float lineHeight = 130; // Height of each line
  float offsetX = 0;
  float firstWordWidth = 0;

  // Calculate morphIndex safely
  int morphIndex = currentMorph * inc + morph;
  morphIndex = min(morphIndex, inc * words.length - 1);

  // Compute the width of the first word for alignment
  for (int j = 0; j < splitGlyph; j++) {
    firstWordWidth = max(firstWordWidth, shiftPntX[0][morphIndex][j]);
  }
  float fixedOffset = firstWordWidth + 220;

  // Morphing and updating clocks
  for (int i = 0; i < tokens[0].length; i++) {
    for (int j = 0; j < splitGlyph; j++) {
      pushStyle();

      if (morphIndex < inc * words.length) {
        float yOffset = currentMorph * lineHeight + (lineHeight * morph / (float) inc);
        clocks[i][j].setPosition(shiftPntX[i][morphIndex][j] + offsetX, shiftPntY[i][morphIndex][j] + yOffset);
        clocks[i][j].update();
        clocks[i][j].display();
      }
      popStyle();
    }

    if (i == 0) {
      offsetX += fixedOffset;
    }
  }

  // Handle pauses and transitions
  if (isPaused) {
    if (!fadingOut && millis() - morphStartTime >= morphDuration) {
      isPaused = false;
      currentMorph = (currentMorph + 1) % words.length;
      morph = 0; // Reset morph to start the next transition
      morphStartTime = millis();

      // Ensure the cycle restarts correctly
      if (currentMorph == 0) {
        fadingOut = true; // Start fading out when transitioning from last to first phrase
      }
    }

    // Update positions for static phrases
    for (int i = 0; i < tokens[0].length; i++) {
      for (int j = 0; j < splitGlyph; j++) {
        if (currentMorph > 0) {
          posStaticX[currentMorph][i][j] = shiftPntX[i][currentMorph * inc + inc - 1][j];
          posStaticY[currentMorph][i][j] = shiftPntY[i][currentMorph * inc + inc - 1][j];
        } else {
          posStaticX[currentMorph][i][j] = shiftPntX[i][(words.length - 1) * inc + inc - 1][j];
          posStaticY[currentMorph][i][j] = shiftPntY[i][(words.length - 1) * inc + inc - 1][j];
        }
      }
    }
  } else {
    morph = (int) ((millis() - morphStartTime) / morphDuration * inc);
    if (morph >= inc) {
      isPaused = true;
      pauseStartTime = millis();

      // Store positions for the current static phrase
      for (int i = 0; i < tokens[0].length; i++) {
        for (int j = 0; j < splitGlyph; j++) {
          posStaticX[currentMorph][i][j] = shiftPntX[i][morphIndex][j];
          posStaticY[currentMorph][i][j] = shiftPntY[i][morphIndex][j];
        }
      }
      showStatic[currentMorph] = true;

      // Check if we are transitioning from "dewire me" to "fire me"
      if (currentMorph == words.length - 1) {
        fadingOut = true;
      }
    }
  }


  // Draw static phrases with fading effects
  for (int w = 0; w < words.length; w++) {
    if (showStatic[w]) {
      for (int i = 0; i < tokens[0].length; i++) {
        for (int j = 0; j < splitGlyph; j++) {
          pushStyle();
          fill(255, staticAlpha[w]);
          clocks[i][j].setPosition(posStaticX[w][i][j] + i * offsetX, posStaticY[w][i][j] + 130 * w + 130);
          clocks[i][j].update();
          clocks[i][j].display();
          popStyle();
        }
      }
    }
  }


  // Global fade-out logic when transitioning from last to first phrase
  if (fadingOut) {
    boolean allFaded = true;
    for (int w = 0; w < words.length; w++) {
      staticAlpha[w] = max(0, staticAlpha[w] - 10);
      showStatic[w] = staticAlpha[w] > 0;
      if (staticAlpha[w] > 0) {
        allFaded = false;
      }
    }

    if (allFaded) {
      // Once all phrases are faded out, reset everything for the next loop
      fadingOut = false;
      for (int w = 0; w < words.length; w++) {
        staticAlpha[w] = 255;
        showStatic[w] = false;
      }
      morph = 0;
      currentMorph = 0;
      morphStartTime = millis();
    }
  }

  /*
  // Ensure sounds play correctly
   for (int i = 0; i < 5; i++) {
   if (!file[i].isPlaying()) {
   file[i].jump(i * file[i].duration() / 25);
   file[i].amp(0.0001);
   file[i].play();
   }
   }
   */
}//draw

// ------------------------------------------------------------------------------------------------------------------------

void mousePressed() {
  run = !run;
}

// ========================================================================================================================

class Clock {
  float cx, cy;
  float radius;
  float clockDiameter;
  float hourRadius;
  float minuteRadius;
  float startHours;
  float startMinutes;
  float h, m;
  color col;
  long startMillis;
  float currentMinutes;

  Clock(float _cx, float _cy, float _startHours, float _startMinutes, color _col) {
    radius = random(10, 25);
    minuteRadius = radius * 0.3;
    hourRadius = radius * 0.15;
    clockDiameter = radius * 1;
    col = _col;
    cx = _cx;
    cy = _cy;
    startHours = _startHours;
    startMinutes = _startMinutes;
    startMillis = millis();
  }

  void setPosition(float _cx, float _cy) {
    cx = _cx;
    cy = _cy;
  }

  void setTime(float _startHours, float _startMinutes) {
    startHours = _startHours;
    startMinutes = _startMinutes;
  }

  void update() {
    long elapsedMillis = millis() - startMillis;
    float elapsedSeconds = (elapsedMillis / 1000.0) * timeFactor;
    float elapsedMinutes = elapsedSeconds / 60.0;
    float elapsedHours = elapsedSeconds / 3600.0;

    float currentHours = startHours + elapsedHours;
    float currentMinutes = startMinutes + elapsedMinutes;

    currentHours = currentHours % 24;
    currentMinutes = currentMinutes % 60;

    h = map(currentHours, 0, 12, 0, TWO_PI) - HALF_PI;
    m = map(currentMinutes, 0, 60, 0, TWO_PI) - HALF_PI;
  }

  void display() {
    col = color(250, 200, 0);
    noStroke();
    fill(col, map(m, 0, TWO_PI, 50, 255));

    arc(cx, cy, minuteRadius * 2, minuteRadius * 2, -HALF_PI, m);

    stroke(255, 150);
    strokeWeight(1.5);

    line(cx, cy, cx + cos(h) * hourRadius, cy + sin(h) * hourRadius);
    strokeWeight(1);
    line(cx, cy, cx + cos(m) * minuteRadius, cy + sin(m) * minuteRadius);
  }
}

1 Like

Original sketch is here:

You may notice a difference in syntax highlighting!
Also some editing was done.

The original sketch used proper syntax highlighting:
https://discourse.processing.org/faq#format-your-code

:)

1 Like

This was an old sketch…Every advice by @Chrisir weights some gold nugget ;-))

Laurent Mareschal

P +33 (0)6.65.62.44.59

2 Likes

Hello @Dalol,

I watched the animation you shared, looked for patterns I could isolate and started coding! I program in achievable steps and add to that. Experience helps.

I am at 48 hrs. of fasting and had some mental clarity and coded this rather quickly!
How Intermittent Fasting Actually Impacts Your Mental Clarity - Health & Wellness Canada

Absolutely no AI was used in generating this!

I did some pixel manipulation here:

Original example < Click here!
// Pixel Manipulation 
// Author: glv
// Date:   2025-10-04

// Shifts the color of pixels with sinusoidal modulation.

PImage img1, img2;

color c;
boolean togOffset = false;
int offset;

PGraphics pg;

void settings()
  {
  String urlString = "http://learningprocessing.com/code/assets/sunflower.jpg";
  img1 = loadImage(urlString);

  println(img1.width, img1.height);
  
  size(img1.width, img1.height, P2D); 
  }

void setup() 
  {
  //frameRate(30);
  
  //img2 = img1.get();
  img2 = get();        // Same size so ok!
  
  // Create a PGraphics with text and replace the sunflower!
  }    

void draw() 
  {
  float ps = frameCount*(TAU/180);  // adds phaseshift (ps)
  
  if (togOffset)  // Hit a key to toggle!
    offset++;

  img2.loadPixels();
  
  color c = color(0);
  for (int y = 0; y < img2.height; y++ )
    {
    for (int x = 0; x < img2.width; x++)
      {
      int loc = x + y*img2.width;
      //if (y<img.height)
        {
        //int shift = 10;
        //shift = (y/10)*10;
        
        float mod = 5+5*sin( y*(TAU/img2.height) + ps); // 0 to 10 sinusoidal
        int shift = (y/10)*(int)mod; // Want this to be an int!
        
        //if (x==0)
        //  println(x, y, shift);
        
        int x2 = (x+shift + offset)%200 ;
        int loc2 = x2 + y*img2.width;
        //println(loc, (x+100)%200, y);
        
        //c = pg.pixels[loc2]; 
        c = img1.pixels[loc2]; 
        }
        
      img2.pixels[loc] = c;
      }
    }
  img2.updatePixels();
  
  image(img2, 0, 0);
  //image(pg, 0, 0);  // PGraphic with text not used!
  
  for (int y=0; y < img1.height; y+=10)
    {
    stroke(255);
    strokeWeight(1);
    line(0, y, width, y);
    }
  }
  
void keyPressed()
  {
  togOffset = !togOffset;
  }

To achieve this:

I then substituted a PGraphics (not shared) with text (black on white) and modified the code to achieve this:

Updated example to illustrate pixel manipulation:

// Pixel Manipulation 
// Author: glv
// Date:   2025-10-05
// Version: 1.1.0

// Shifts the color of pixels with sinusoidal modulation.

PImage img1, img2, img3;

boolean togOffset = false;
boolean togImage = true;
int offset;

PGraphics pg;

void settings()
  {
  String urlString = "http://learningprocessing.com/code/assets/sunflower.jpg";
  img1 = loadImage(urlString);
  img3 = img1.get();

  println(img1.width, img1.height);
  
  size(img1.width, img1.height, P2D); 
  }

void setup() 
  {
  img2 = createImage(img1.width, img1.height, RGB);

  // Create a PGraphics with text and replace the sunflower!
  pg = createGraphics(img1.width, img1.height);
  
  pg.beginDraw();
  pg.background(255); // White
  pg.strokeWeight(50);
  pg.circle(pg.width/2, pg.height/2, 80);
  pg.endDraw();
  }    

final static float PHASE_INCREMENT = TAU/100;

void draw() 
  {
// Demonstrates these events:    
  if (frameCount%120 == 0)
    mousePressed();
    
  if (frameCount == 6*60)
    keyPressed();
    
  float ps = frameCount*PHASE_INCREMENT;  // adds phaseshift (ps)
  
  if (togOffset) offset++; // Hit a key to toggle!
    
  int slices = 20;
  int sliceWidth = img2.height/slices;  
    
  imageMods(sliceWidth, ps);
  
  image(img2, 0, 0);
  
  for (int y=0; y < img1.height; y+=sliceWidth)
    {
    stroke(128);
    strokeWeight(1);
    line(0, y, width, y);
    }
  }
  
void keyPressed()
  {
  togOffset = !togOffset;
  }  
  
void mousePressed()
  {
  togImage = !togImage;
  
  if (togImage)
    img1 = pg.get(); // Extract as PImage 
  else
    img1 = img3.get(); // Extract as PImage   
  }
  
void imageMods(int sliceWidth, float phaseShift)
  {
  img2.loadPixels();
  
  for (int y = 0; y < img2.height; y++ )
    {
    //Static shift
    //int shift = (y/10)*10;  //Try this!
        
    //Dynamic shift    
    int sliceInt = (y/sliceWidth)*sliceWidth;      // This is for quantization
    
    float mod = 20*sin( sliceInt*(TAU/img2.height) + phaseShift); // -20 to 20 sinusoidal
    int shift = (int) mod; // Want this to be an int!  
          
    for (int x = 0; x < img2.width; x++)
      {
      int loc = x + y*img2.width;       // optimize?
        
      int x2 = (x + shift + offset)%img2.width;
      if (x2 < 0) x2 += img2.width;
      
      int loc2 = x2 + y*img2.width;
      
      color c = img1.pixels[loc2];
        
      img2.pixels[loc] = c;
      }
    }
  img2.updatePixels();  
  }

It takes time, effort, research and practice to learn to code such a project, but with that perseverance, you’ll be able to wield those pixels to create anything.

Note:
The original code shared was a first pass and quick effort and has room for improvement!
It is only intended as a very minimal example of what can be done with pixel manipulation.
Also, it is good to walk away from code and come back to it when you are fresh!
The additional code is a revisit the next day with some improvements.
This is not a simple project and work in progress.

Many of the attempts along the way generated some very cool visualizations!

This exploration has inspired me to code and work on some original works.

Reference:

Have fun!

:)

1 Like