pseudo live coding shaders idea

edited December 2013 in GLSL / Shaders

Hello everyone! dont know if there's a way of doing this in P5 already but I wanted to share with y'all a simple way of doing it. This is based on the deform.pde sketch included in the examples. Just run the sketch as normal, open the deform.glsl shader with your editor of choice, type away, save changes, watch.

/**
 * Deform. 
 * 
 * A GLSL version of the oldschool 2D deformation effect, by Inigo Quilez.
 * Ported from the webGL version available in ShaderToy:
 * http://www.iquilezles.org/apps/shadertoy/
 * (Look for Deform under the Plane Deformations Presets)
 * 
 */

PImage tex;
PShader deform;

void setup() {
  size(displayWidth/2, displayHeight/2, P2D);  //  size(640, 360, P2D);

  textureWrap(REPEAT);
  tex = loadImage("tex1.jpg");

  deform = loadShader("deform.glsl");
  deform.set("resolution", float(width), float(height));
}

void draw() {
  if (frameCount % 60 == 0) {
    deform = loadShader("deform.glsl");
    deform.set("resolution", float(width), float(height));
  }

  deform.set("time", millis() / 1000.0);
  deform.set("mouse", float(mouseX), float(mouseY));
  shader(deform);
  image(tex, 0, 0, width, height);
}

I would love to hear suggestions for better ways of doing this or implementing something like shadertoy in P5. Saludos everyone! JLafarga

Answers

  • edited December 2013

    Hi JLafarga,

    That's basically the way I've been doing it so far. The if (frameCount % 60 == 0) is a nice touch.

    The main problem is that you have to relaunch the sketch when your shader crashes.

    If you could somehow check that the shader compiles and have that as a condition, this would be amazing. I have no idea how to achieve that in Processing though.

    Raphaël

  • you could use a try/catch block to handle the syntax errors in the shader:

    PImage tex;
    PShader deform;
    boolean loaded;
    
    void setup() {
      size(640, 360, P2D);
    
      textureWrap(REPEAT);
      tex = loadImage("tex1.jpg");
    
      textFont(createFont("Arial", 24));
    
      tryLoadShader();
    }
    
    void draw() {
      if (frameCount % 60 == 0) {
        tryLoadShader();
      }
    
      if (!loaded) {
        background(0);
        fill(255, 0, 0);
        textAlign(CENTER);
        text("SHADER COMPILATION ERROR!", width/2 , height/2);
        return;    
      }
    
      deform.set("time", millis() / 1000.0);
      deform.set("mouse", float(mouseX), float(mouseY));
      shader(deform);
    
      image(tex, 0, 0, width, height);
    }
    
    void tryLoadShader() {
      try {  
        deform = loadShader("deform.glsl");
        deform.set("resolution", float(width), float(height));
        loaded = true;
      } catch (RuntimeException e) {
        e.printStackTrace();
        loaded = false;    
      }
    }
    
  • edited December 2013

    @codeanticode: Hi Andrés. I tried making a minimal sketch out of your suggestion and it stopped working when I removed line 39. Apparently, try{} only catches the error when using the set() function. Simply using loadShader() doesn't cut it and the error is caught outside of the try{}.

    I reported the issue here: https://github.com/processing/processing/issues/2268

  • hi there, its not really an error or a bug its just that if you remove line 39 you are just not initialising the resolution variable in the shader, for this particular shader you need that variable, if you don't like line 39 just initialise the resolution variable inside your shader and everything will work fine.

  • edited February 2014

    @jlafarga: You are right that this is not a Processing related problem or bug as it won't appear at compile time, but live coding means you should be able to write a piece of code that can throw runtime errors without crashing the sandbox you are coding in.

    @sableRaph: Just wrap up the set(), shader() and image() calls in another try/catch block and you should be fine:

    PImage tex;
    PShader deform;
    String errorMessage;
    
    
    void setup() {
    
        size(640, 360, P2D);
        textureWrap(REPEAT);
        textAlign(CENTER);
        fill(255, 0, 0);
    
        tex = loadImage("tex1.jpg");
        textFont(createFont("Arial", 24));
    
        tryLoadShader();
    
    }
    
    
    void draw() {
    
        if(frameCount % 60 == 0)
            tryLoadShader();
    
        if(errorMessage != null) {
            resetShader();
            background(0);
            text(errorMessage, width / 2 , height / 2);
            return;
        }
    
        try {
            deform.set("time", millis() / 1000.0);
            deform.set("mouse", (float)mouseX, (float)mouseY);
            shader(deform);
            image(tex, 0, 0, width, height);
        } catch(Exception e) {
            errorMessage = e.getMessage();
        }
    
    }
    
    void tryLoadShader() {
    
        try {  
            deform = loadShader("deform.glsl");
            deform.set("resolution", (float)width, (float)height);
            errorMessage = null;
        } catch(Exception e) {
            errorMessage = e.getMessage();
        }
    
    }
    
Sign In or Register to comment.