Warping texture with an other texture

edited September 2017 in GLSL / Shaders

I try to warp an image with an other image but I don't find the way to do it. The idea at the end it's use the a stable fluid to warp the image. Here a little example to show the problem : link sketch problem

link project in problem version

So any idea are very very welcome !

shader frag

/**
ROPE - Romanesco processing environment – 
* Copyleft (c) 2014-2017 
* Stan le Punk > http://stanlepunk.xyz/

Shader to warp texture

Render fluid
v 0.0.2
*/
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

#define PROCESSING_TEXTURE_SHADER

#define PI 3.1415926535897932384626433832795

varying vec4 vertTexCoord;
uniform sampler2D texture;

uniform int mode;
uniform float roof_component_colour;

uniform sampler2D vel_texture;
uniform sampler2D dir_texture;
uniform vec2 grid_wh;

float map(float value, float start1, float stop1, float start2, float stop2) {
  float result = start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
  return result;
}  
vec2 cartesian_coord(float angle) {
  float x = cos(angle);
  float y = sin(angle);
  return vec2(x,y);
}

void main() {

  vec2 ratio = gl_FragCoord.xy / grid_wh;
  // vec2 ratio = vertTexCoord.st / grid_wh;

  vec4 vel = texture2D(vel_texture, ratio);
  vec4 dir = texture2D(dir_texture, ratio);


  // rendering picture ;
  if(mode == 0 ) {

    float angle_rad = map(dir.x, 0, roof_component_colour, -PI, PI);
    vec2 dir_cart = cartesian_coord(angle_rad) ;

    // float gap = max(grid_wh.x, grid_wh.y);
    // vec2 translate_pix = dir_cart.xy *vel.x / gap;
    vec2 translate_pix = dir_cart.xy *vel.x ;

    vec2 coord_dest = vertTexCoord.st +translate_pix ;
    vec4 tex_colour = texture2D(texture, coord_dest);

    gl_FragColor = tex_colour;
  }
  // velocity
  if(mode == 1 ) {
    gl_FragColor = texture2D(vel_texture, vertTexCoord.st);;
  }
  // direction force field
  if(mode == 2) {
    gl_FragColor = texture2D(dir_texture, vertTexCoord.st);;
  }

}

Processing

PImage tex_velocity, tex_direction ;
PShader warping;
PImage img ;
int grid_w, grid_h ;
void setup() {
  size(600,375,P2D);
  img = loadImage("pirate_small.jpg");
  grid_w = 60 ;
  grid_h = 37 ;
  tex_velocity = createImage(grid_w,grid_h,RGB);
  tex_direction = createImage(grid_w,grid_h,RGB);  
  warping = loadShader("shader/warp/rope_warp_fluid.glsl");
  noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
    noise_img(tex_direction, 360, .1, .1); // degree direction
}

void draw() {
    if(frameCount%60 == 0) {
        noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
        noise_img(tex_direction, 360, .1, .1); // degree direction
    }

    warping.set("mode", 0) ;
    warping.set("texture",img);
    warping.set("roof_component_colour",g.colorModeX);
    warping.set("grid_wh",grid_w,grid_h);

  warping.set("vel_texture",tex_velocity);
  warping.set("dir_texture",tex_direction);
  shader(warping);

  image(img,0,0);
  resetShader();
  image(tex_velocity,5,5);
  image(tex_direction,grid_w +15 ,5 );
}


float x_offset, y_offset ;
void noise_img(PImage dst, int max, float ratio_x, float ratio_y) {
    noiseSeed((int)random(10000));
    for(int x = 0 ; x < dst.width ; x++) {
        x_offset += ratio_x ;
        for(int y = 0 ; y < dst.height ; y++) {
            y_offset += ratio_y ;
            float v = map(noise(x_offset,y_offset),0,1,0,max);
            v = (int)map(v,0,max,0,g.colorModeX);
            int c = color(v,v,v,g.colorModeA) ;
            dst.set(x,y,c);
        }
    }
}

Answers

  • edited September 2017

    @Stanlepunk

    I think you looking for a photoshop like solution:
    you can enable it in OpenGL (easy) eg. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    https://www.khronos.org/opengl/wiki/Blending
    https://learnopengl.com/#!Advanced-OpenGL/Blending

    or experiment with direct in the Fragment shader
    according to to wiki: GL_FUNC_ADD: O = sS + dD
    texture(tex1,uv)+texture(tex2,uv);
    (it want work so easy as that ... depends if you have a png with alpha etc. )

    I also mess up a bit with you code for my own education, this is my coding style maybe you find something usefull.

    shader vert
    note: The default Processing vert TexCoord is premultiplied something. I don't even know what happens in the background. I found it easy to write your own shader vertex and work your way from their. What i do, becourse i don't always want to look up how that stuff is implemented.

    //who read this in 2017
    #version 150
    in vec2 position;
    out vec2 vTexCoord;
    void main() {
    gl_Position = vec4(position.xy,0.,1.);
    //scale and flip
    vTexCoord=-position*.5+.5;
    }
    

    shader frag

    #version 150
    //let my hardware decide - default highp 
    //verson >4  double-precision types just saying
    #define PI acos(-1.)
    
    in vec4 vTexCoord;
    uniform sampler2D tex, vel_texture, dir_texture;
    uniform float roof_component_colour;
    uniform int mode;
    uniform vec2 grid_wh;
    out vec4 fragColor;
    
    float map(float value, float start1, float stop1, float start2, float stop2) {
    return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
    }   
    
    void main() {
        vec2 ratio = gl_FragCoord.xy / grid_wh;
      // vec2 ratio = vTexCoord.st / grid_wh;
    
      vec4 vel = texture(vel_texture, ratio), dir = texture(dir_texture, ratio);
    
      //linux firefox (older smartphones) needed to be initialized otherwise artifacts
      fragColor=vec4(0.);
    
      // rendering picture ;
      switch(mode) {
            // velocity
            case 1: fragColor = texture(vel_texture, vTexCoord.st);
            break;
            // direction force field
            case 2: fragColor = texture(dir_texture, vTexCoord.st);
            break;
        default :
            float angle_rad = map(dir.x, 0, roof_component_colour, -PI, PI);
            //cartesian_coord
            vec2 dir_cart = vec2(cos(angle_rad),sin(angle_rad)) ;
    
            // float gap = max(grid_wh.x, grid_wh.y);
            // vec2 translate_pix = dir_cart.xy *vel.x / gap;
            vec2 translate_pix = dir_cart.xy *vel.x ;
    
            vec2 coord_dest = vTexCoord.st +translate_pix ;
            vec4 tex_colour = texture(tex, coord_dest);
    
            fragColor = texture(tex, coord_dest) ;
            break;
      }
    }
    

    processing

    PImage tex_velocity, tex_direction,img;
    PShader warping;
    int grid_w= 60, grid_h= 37 ;
    void setup() {
      size(600,375,P2D);
      noStroke();
      //orthoCam in P2D (see openGL how to viewPort)
      rectMode(RADIUS);
    
      img = loadImage("pirate_small.jpg");
    
      tex_velocity = createImage(grid_w,grid_h,RGB);
      tex_direction = createImage(grid_w,grid_h,RGB);  
    
      warping =loadShader("shader/warp/rope_warp_fluid.frag","shader/warp/rope_warp_fluid.vert");
    
      noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
      noise_img(tex_direction, 360, .1, .1); // degree direction
    
        // needs to be updated (in draw func) ? 
        warping.set("tex",img);
        warping.set("roof_component_colour",g.colorModeX);
        warping.set("grid_wh",grid_w,grid_h);
        //everything is set ? Compile!
        shader(warping);
        frameRate(1);
    }
    int t =0; 
    void draw() {
    
      background(0);
    
        if(frameCount%60 == 0) {
            noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
            noise_img(tex_direction, 360, .1, .1); // degree direction
        }
    
        warping.set("mode",(t>1)?t-=t:++t);
        print("mode: "+t+"\n"); //\n for newline for windows
    
      // drawn in JAVA
      //image(tex_velocity,5,5);
      //image(tex_direction,grid_w +15 ,5 );
    
      warping.set("vel_texture",tex_velocity);
      warping.set("vel_texture",tex_direction);
      rect(0,0,width,height);
    }
    float x_offset, y_offset ;
    void noise_img(PImage dst, int max, float ratio_x, float ratio_y) {
        noiseSeed((int)random(10000));
        for(int x = 0 ; x < dst.width ; x++) {
            x_offset += ratio_x ;
            for(int y = 0 ; y < dst.height ; y++) {
                y_offset += ratio_y ;
                float v = map(noise(x_offset,y_offset),0,1,0,max);
                v = (int)map(v,0,max,0,g.colorModeX);
                int c = color(v,v,v,g.colorModeA) ;
                dst.set(x,y,c);
            }
        }
    }
    

    @Stanlepunk

    so their is already a blending mode predef.
    like an The X-Files serial: trust no one.
    looks like blend_mode alpha minus one (who knows for sure)

    test

    PShader shdr;
    void setup() {
      size(640, 360, P2D);
      shdr=loadShader("https:"+"//pastebin.com/raw/VzY22k8b","https:"+"//pastebin.com/raw/W3nKbJL0");
      shdr.set("tex[0]", loadImage("https:"+"//processing.org/examples/moonwalk.jpg"));
      shdr.set("tex[1]", loadImage("http:"+"//processing.org/img/processing-web.png"));
    }
    void draw() { filter(shdr);shdr.set("t",frameCount*.01f);}
    
  • edited September 2017

    thx to go deep in my code, but what's happen exactly more than my own code???? It's like the same result than my work, just move all the picture. the goal is move each pixel with information of the texture, the first texture give the direction and the other give the distance. like this animation i do with a processor rendering, the idea is report this part on the GLSL to growth the framerate instagram_stanlepunk

    plus I must modify the vert part from vec2 to Vec4 vTexCoord

    #version 150
    in vec2 position;
    out vec4 vTexCoord;
    void main() {
      gl_Position = vec4(position.xy,0.,1.);
      //scale and flip
      vTexCoord.xy =- position *.5 +.5;
    }
    
  • here a most explicit picture to explain my purpose Capture d’écran 2017-09-23 à 10.33.55 In the code example given, i have replaced the algorithm stable fluid by a noise algorithm. but the idea is the same.

  • edited September 2017

    @Stanlepunk

    no difference. I cant solve you problem, I have no idea of fluids. This is also an topic you can spend lot of time.

    I just want to introduce you modern Shader Programing :)
    define PROCESSING_TEXTURE_SHADER //Processing 2.x

    I did some research, OpenGL fluids - their are tones of exampels and found this looks useful at first sight https://github.com/prideout/fluidsim //he uses a 3D texture, nice
    https://www.shadertoy.com/view/MdKXRy

    Tones of exampels https://github.com/diwi/PixelFlow

    Nice instagram, Keep it coming!

  • edited September 2017

    @nabr the glsl is a new world for me, very mathematical one !!!! I've to understand the way of coding in pixel flow but it's very very complex the coding steps and to add in my own code. I'm going to look your other link with attention. My purpose is keep the stable fluid in Processing to keep the access to the grip position for the other stuff and just change the pixel position in the GLSL...

    I hope find the algo to solve my problem.

  • @Stanlepunk

    i understand. Fluid Dynamics is pain in the ass : )

    what is can suggest:
    + start with something simpel
    + reading texture from backbuffer
    https://forum.processing.org/two/discussion/22508/chaining-shaders-and-feedback/p1#Comment_98790

    https://forum.processing.org/two/discussion/22385/#Comment_99803

    Maybe @T_D have some time :)

  • very intersting post, I hope I have time to work deep on it and back with new question !

Sign In or Register to comment.