Convert Shader from Shadertoy.com for Processing

Hi all,

Seeing how efficient shaders are at applying an effect to video frames, is there a way to convert any shader from Shadertoy to work in processing?

Thanks, Charles

Answers

  • edited May 2017

    as long someone prepared a better answer this just a hit in the right direction, - where to start

    PShader Shrtoy;
    void setup() {
    size(640,360,P2D);
    noStroke();
    Shrtoy = loadShader("ShrtoyFrag.glsl"); 
    Shrtoy.set("iResolution", float(width), float(height));
    }
    void draw() {
    background(0);
    Shrtoy.set("iGlobalTime", millis() / 1000.0);
    filter(Shrtoy);
    }
    

    ShrtoyFrag.glsl

    uniform vec2 iResolution;
    uniform float iGlobalTime;
    
    void mainImage( out vec4 fragColor, in vec2 fragCoord ){
        vec2 uv = fragCoord.xy/iResolution.xy;
        fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
    }
    
    void main() {
    mainImage(gl_FragColor,gl_FragCoord.xy);
    }
    
  • edited May 2017

    @nabr Would you mind clarifying your answer?

    mainImage() is already present in all ShaderToy shaders, thus, should it be replaced or appended? If the latter, then are the arguments also appended?

    I understand that uniform are variables that can be accessed from Processing, is it also possible to change other variables using the set()function?

  • edited May 2017 Answer ✓

    @CharlesDesign Hello the mainImage is thought to make it easy to copy +paste from shadertoy mainImage to any kind of Shadercompiler like Processing. It is necessary to have a main function in the body of a shader. Shadertoy just hide it from you.

    "should it be replaced or appended? " replaced

    uniforms: I do not really understand, what you are trying to archive. uniform is just a instruction to the glsl Compiler, like int or float, string.

    int x;
    int i = 42;
    x=i;
    print(x)
    //out: 42
    

    do the same thing with a uniform

    the set() method overloads the ("declaration", value). you can change the value very easy Shrtoy.set("iGlobalTime", millis() / 1000.0); the millis are counted up, the value is changed every draw call. the iGlobalTime is a constant.

  • edited May 2017

    Based on your instructions I've converted the following Voronoi shader, however, I get the following error:

    Screen Shot 2017 05 02 at 10 11 06

    Here's the code directly from ShaderToy.com:

    #define NUM_POINTS 1024
    #define SEED 3
    
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
        int random = SEED;
    
        int a = 1103515245;
        int c = 12345;
        int m = 2147483648;
    
        vec2 o;
    
        float minDist = 10000000.0;
    
        for(int i = 0; i < NUM_POINTS; i++)
        {
            random = a * random + c;
    
            o.x = (float(random) / float(m)) * iResolution.x;
    
            random = a * random + c;
    
            o.y = (float(random) / float(m)) * iResolution.y;
    
            if(distance(fragCoord, o) < minDist)
            {
                minDist = distance(fragCoord, o);
                vec2 uv = o / iResolution.xy;
                uv.x = 1.0 - uv.x;
                fragColor = (texture(iChannel0, uv)) * (1.0 - minDist / 200.0);
            }
        }
    }
    

    Here's my sketch:

    PShader voronoi;
    
    void setup() {
      size (1280, 720, P2D);
      voronoi = loadShader("voronoi.glsl"); 
      voronoi.set("iResolution", float(width), float(height));
    }
    
    void draw () {
      surface.setTitle(nf(frameRate, 2, 2));
      background(255);
      voronoi.set("iGlobalTime", millis() / 1000.0);
      filter(voronoi);
    }
    

    And voronoid.glsl:

    uniform vec2 iResolution;
    uniform float iGlobalTime;
    
    #define NUM_POINTS 1024
    #define SEED 3
    
    void main() {
        mainImage(gl_FragColor,gl_FragCoord.xy);
    }
    
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
        vec2 uv = fragCoord.xy/iResolution.xy;
        fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
    
        int random = SEED;
    
        int a = 1103515245;
        int c = 12345;
        int m = 2147483648;
    
        vec2 o;
    
        float minDist = 10000000.0;
    
        for(int i = 0; i < NUM_POINTS; i++)
        {
            random = a * random + c;
    
            o.x = (float(random) / float(m)) * iResolution.x;
    
            random = a * random + c;
    
            o.y = (float(random) / float(m)) * iResolution.y;
    
            if(distance(fragCoord, o) < minDist)
            {
                minDist = distance(fragCoord, o);
                vec2 uv = o / iResolution.xy;
                uv.x = 1.0 - uv.x;
                fragColor = (texture(iChannel0, uv)) * (1.0 - minDist / 200.0);
            }
        }
    }
    
  • edited May 2017

    These are the unicorns on shadertoy. Whenever you use make sure you link it in your processing scetch.

    https://ibb.co/gnXi35

    Add to your scetch: voronoi.set("iChannel0",get());

    Add to your voronoid.glsl:uniform sampler2D iChannel0

  • edited May 2017 Answer ✓

    @CharlesDesign I discover some build in uniforms like on shadertoy

    https://codeanticode.wordpress.com/2014/05/08/shader_api_in_processing_2/

    voronoid.glsl:

    uniform vec2 iResolution;
    uniform float iGlobalTime;
    
    //build in sampler2D  uniform
    uniform sampler2D texture; 
    
    
    //to make it easier without going through all the code
    //define directive is kind copy paste text for the compiler 
    #define iChannel0 texture
    
    #define NUM_POINTS 1024
    #define SEED 3
    
    
    //at compile time mainImage() is not visibel in main()
    //your have to order the main function after 
    //definition of mainImage() or make a global declaration 
    //confuses me also, but i dont know how to explain it better :)
    //http://www.cprogramming.com/declare_vs_define.html
    
    void mainImage( out vec4 fragColor, in vec2 fragCoord );
    
    
    void main() {
        mainImage(gl_FragColor,gl_FragCoord.xy);
    }
    
    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
        vec2 uv = fragCoord.xy/iResolution.xy;
        //always initialise your especially! Color &or variables
        //otherwise it will fail on cross plattforms
        vec4 Color = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
    
        int random = SEED;
    
        int a = 1103515245;
        int c = 12345;
        int m = 2147483648;
    
        vec2 o;
    
        float minDist = 10000000.0;
    
        for(int i = 0; i < NUM_POINTS; i++)
        {
            random = a * random + c;
    
            o.x = (float(random) / float(m)) * iResolution.x;
    
            random = a * random + c;
    
            o.y = (float(random) / float(m)) * iResolution.y;
    
            if(distance(fragCoord, o) < minDist)
            {
                minDist = distance(fragCoord, o);
                vec2 uv = o / iResolution.xy;
                uv.x = 1.0 - uv.x;
               //the Color will added to previos value, not sure
              //if this gives your the effect you are going for
                Color += (texture(iChannel0, uv)) * (1.0 - minDist / 200.0);
            }
        }
        fragColor =Color;
    }
    

    Processing scetch: (no need to assign iChannel0)

    PShader voronoi;

    void setup() {
      size (1280, 720, P2D);
      voronoi = loadShader("voronoi.glsl"); 
      voronoi.set("iResolution", float(width), float(height));
    }
    
    void draw () {
      surface.setTitle(nf(frameRate, 2, 2));
      background(255);
      voronoi.set("iGlobalTime", millis() / 1000.0);
      filter(voronoi);
    }
    
  • @nabr -- "uniforms", not unicorns ;)

  • @nabr Super helpful, thanks!

Sign In or Register to comment.