class Param { String name; int type; float minValue, maxValue; float value; int[] osciModes; Param(String name_, int type_, float minValue_, float maxValue_, int[] osciModes_) { name = name_; type = type_; //FLOATVAL or INTVAL minValue = minValue_; maxValue = maxValue_; osciModes = osciModes_; } } class Shader { int id; int pos, previousPos; boolean previousActive; String name; ArrayList params = new ArrayList(); ArrayList paramValues = new ArrayList(); boolean paramChanged = true; PGraphics canvas = createGraphics(renderer.width, renderer.height); PGraphics result; int direction = 0; int directionParamIndex = -1; Shader() { canvas.beginDraw(); canvas.image(renderer, 0, 0, canvas.width, canvas.height); canvas.endDraw(); } void getValuesFromGUI() { try { //problematic params = gui.bricks.get(pos).params; } catch(Exception e) { println(e); } //this is only for checking if a param has changed. paramValues could also be used for a save/load function if (paramValues.size() != params.size()) { for (int i = 0; i < params.size(); i++) { paramValues.add(0.0); } } paramChanged = false; for (int i = 0; i < params.size(); i++) { if (paramValues.get(i) != params.get(i).value) { paramValues.set(i, params.get(i).value); paramChanged = true; } } if (pos != previousPos) { paramChanged = true; } previousPos = pos; try{ if (previousActive != gui.bricks.get(pos).active) { //fails if brick has not yet been loaded but shader has paramChanged = true; } previousActive = gui.bricks.get(pos).active; } catch (Exception e){ println("Brick not yet loaded, couldn't catch active state"); } if (!paramChanged) { if (imageChanged) paramChanged = true; for (int i = this.pos; i >= 0; i--) { if (gui.shaderList.get(i).paramChanged) paramChanged = true; } } if (frameRate < 1) println("Rendering " + this + " on position " + pos + "..."); } void changeParam(int paramNo, Param newParam) { gui.bricks.get(pos).params.remove(paramNo); gui.bricks.get(pos).params.add(paramNo, newParam); gui.bricks.get(pos).exchangeSlider(paramNo, newParam); paramChanged = true; } void shade() { if (renderSizeChanged || paramChanged) { this.setupCanvas(); this.apply(); this.render(); } else { // println("nothing changed"); renderer.beginDraw(); renderer.image(result, 0, 0); renderer.endDraw(); }/* this.setupCanvas(); this.apply(); this.render(); */ } void setupCanvas() { if (directionParamIndex >= 0) direction = (int)this.params.get(directionParamIndex).value; int cw = (direction == 0 || direction == 2) ? renderer.width : renderer.height; int ch = (direction == 0 || direction == 2) ? renderer.height : renderer.width; canvas = createGraphics(cw, ch); canvas.beginDraw(); canvas.imageMode(CENTER); canvas.clear(); canvas.pushMatrix(); canvas.translate(cw/2, ch/2); canvas.rotate((PI/2)*direction); canvas.image(renderer, 0, 0); canvas.popMatrix(); canvas.endDraw(); } void apply() { }; //override me with an actual fragment shader void render() { renderer.beginDraw(); renderer.imageMode(CENTER); renderer.pushMatrix(); renderer.translate(renderer.width/2, renderer.height/2); renderer.rotate(-(PI/2)*direction); renderer.image(canvas, 0, 0); renderer.popMatrix(); renderer.imageMode(CORNER); renderer.endDraw(); result = createGraphics(renderer.width, renderer.height); result.beginDraw(); result.image(renderer, 0, 0); result.endDraw(); if (pos == gui.bricks.size()-1) { //println("Finished rendering"); if (imageChanged) { //kind of hacky but it does synchronize the threads. sometimes. stepOne++; if (stepOne == 2) { stepOne = 0; imageChanged = false; } } } } @ Override String toString() { return getClass().getName(); } } int stepOne = 0;