SketchPad

Some web space to sketch, doodle and make notes. Made using these tools. See more of my work here.

Don't clear the buffer

  1. Draw something partially transparent into a buffer
  2. Don't clear the buffer (or only partially clear it) before the next frame
  3. Optionally, periodically clear the buffer, to provide a sense of rhythm, etc.
		float increment, resetFrequency;
ofxTexturePlane plane;

void ofApp::setup(){
    increment = 0.0025;
    resetFrequency = 8;
    plane.setup("partially-transparent.png", 1.0, TEXTURE_OFFSET_TOP_LEFT);
}

void ofApp::update(){
    ofGetFrameNum() % resetFrequency == 0 ?
        plane.setTextureOffset(TEXTURE_OFFSET_TOP_LEFT) :
        plane.incrementTextureOffsetY(increment);
}

void ofApp::draw(){
    if(ofGetFrameNum() % resetFrequency == 0) {
        ofBackground(ofColor::white);
    }
    plane.draw();
}
	

Sketch 2015-07-28

        void ofApp::setup(){
    increment = 0.01;
    numLayers = 3;
    filename = "leaf-transp2.png";

    ofSetWindowShape(500, 500);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 12, 60);

    masker.setup(numLayers);
    plane.setup(filename);
    for(int i = 0; i < numLayers; i++) {
        layers.push_back(plane);
        masks.push_back(plane);
    }
    reset();
}

void ofApp::reset() {
    offsetIncrements.clear();
    scaleIncrements.clear();

    for(int i = 0; i < numLayers; i++) {
        layers.at(i).setTextureScale(ofRandom(0.1, 1.5));
        layers.at(i).setTexturePosition(ofRandom(2), ofRandom(2));
        masks.at(i).setTextureScale(ofRandom(0.1, 1.5));
        masks.at(i).setTexturePosition(ofRandom(2), ofRandom(2));
        offsetIncrements.push_back(ofVec2f(ofRandom(-increment, increment), ofRandom(-increment, increment)));
        scaleIncrements.push_back(ofRandom(-increment*20, increment*20));
    }
}

void ofApp::update(){
    if(ofGetFrameNum() % 12 == 0) {
        reset();
    }
    for(int i = 0; i < numLayers; i++) {
        masker.beginLayer(i);
        {
            if(ofGetFrameNum() % 3 == 0 && i == 0) {
                ofBackground(ofColor(ofColor::white, 64));
            }
            if(ofGetFrameNum() % 12 == 0) {
                ofBackground(ofColor(ofColor::white, 128));
            }
            layers.at(i).incrementTextureOffset(offsetIncrements.at(i));
            layers.at(i).incrementTextureScale(scaleIncrements.at(i));
            layers.at(i).draw();
        }
        masker.endLayer(i);

        masker.beginMask(i);
        {
            ofBackground(ofColor::white);
            masks.at(i).incrementTextureOffset(-offsetIncrements.at(i));
            masks.at(i).incrementTextureScale(-scaleIncrements.at(i));
            masks.at(i).draw();
        }
        masker.endMask(i);
    }
}

void ofApp::draw(){
    gif.begin();
    {
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Easing back and forth

Daily sketch

Sketch 2015-07-25

        void ofApp::setup(){
    increment = 0.0025;
    numLayers = 3;
    filename = "foil-large-transp.png";

    ofSetWindowShape(500, 500);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 8, 56);

    masker.setup(numLayers);
    plane.setup(filename);
    for(int i = 0; i < numLayers; i++) {
        layers.push_back(plane);
        masks.push_back(plane);
    }
    reset();
}

void ofApp::reset() {
    offsetIncrements.clear();
    scaleIncrements.clear();

    for(int i = 0; i < numLayers; i++) {
        layers.at(i).setTextureScale(ofRandom(4.5, 5.5));
        layers.at(i).setTexturePosition(ofRandom(2), ofRandom(2));
        masks.at(i).setTextureScale(ofRandom(4.5, 5.5));
        masks.at(i).setTexturePosition(ofRandom(2), ofRandom(2));
        offsetIncrements.push_back(ofVec2f(ofRandom(-increment, increment), ofRandom(-increment, increment)));
        scaleIncrements.push_back(ofRandom(-increment*6, increment*6));
    }
}

void ofApp::update(){
    if(ofGetFrameNum() % 8 == 0) {
        reset();
    }
    for(int i = 0; i < numLayers; i++) {
        masker.beginLayer(i);
        {
            layers.at(i).incrementTextureOffset(offsetIncrements.at(i));
            layers.at(i).incrementTextureScale(scaleIncrements.at(i));
            layers.at(i).draw();
        }
        masker.endLayer(i);

        masker.beginMask(i);
        {
            ofBackground(ofColor::white);
            masks.at(i).incrementTextureOffset(-offsetIncrements.at(i));
            masks.at(i).incrementTextureScale(-scaleIncrements.at(i));
            masks.at(i).draw();
        }
        masker.endMask(i);
    }
}

void ofApp::draw(){
    gif.begin();
    {
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Revealing a metallic surface

Daily sketch

Sketch 2015-07-18

        void ofApp::setup(){
    ofSetWindowShape(1000, 800);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 30, 75, 500, 500, ISOLATE_DRAWING);
    masker.setup(500, 500, 1, ISOLATE_LAYERS);
    masker.toggleOverlay();

    glass1.setup("glass.png", 500, 500, 2.0);
    glass2.setup("glass.png", 500, 500, 2.0);
    framesBeforeRefresh = 15;
}

void ofApp::update(){
    if(ofGetFrameNum() % framesBeforeRefresh == 0) {
        refresh = true;
        int offsetIndex = floor(ofGetFrameNum() / framesBeforeRefresh);
        offsetIndex = ((offsetIndex % 3) + 0) * 2;
        glass1.setTextureOffset(offsetIndex);
        glass2.setTextureOffset(offsetIndex);
        glass1.setTextureScale(3.0);
        glass2.setTextureScale(3.0);
    } else {
        refresh = false;
        glass1.incrementTextureScale(-0.05);
        glass2.incrementTextureScale(0.05);
    }
    
    masker.beginLayer(0);
    {
        glass1.draw();
    }
    masker.endLayer(0);
    
    masker.beginMask(0);
    {
        glass2.draw();
    }
    masker.endMask(0);
}

void ofApp::draw(){
    gif.begin();
    {
        ofEnableAlphaBlending();
        if(refresh) {
            ofSetColor(ofColor::red);
            ofRect(0, 0, gif.width, gif.height);
        }
        masker.draw();
        ofDisableAlphaBlending();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

"...a conscious, purposeful, and personal subject confronting an unconscious, purposeless, and impersonal universe..." (Richard Tarnas)

Daily sketch

Sketch 2015-04-25

        void ofApp::setupAnim() {
    current = 0;
    max = 80;
    for(int i = 0; i < max; i++) {
        glitches.push_back(templateGlitch);
        glitches.at(glitches.size()-1).allocate(width, height);
    }
    ofSetColor(ofColor::white);
}

void ofApp::drawAnim() {
    if(ofGetFrameNum() % 5 == 0) {
        ofClear(255,255,255);
    } else {
        ofEnableBlendMode(OF_BLENDMODE_MULTIPLY);
        glitches.at(ofGetFrameNum()%max).draw(0, 0);
        ofDisableBlendMode();
    }
}
    

Accessing chunks of memory that you're not supposed to access

Daily sketch

Multiple layer transforms

  1. Draw a partially transparent image into a layer
  2. Draw the same image into a mask, but transformed somehow
  3. Repeat for multiple layers, incrementing or adjusting transformations on each frame.
  4. Optionally experiment by adding and remixing source images across layers and masks.
		ofxLayerMask masker;
ofxTexturePlane plane;
vector<ofxTexturePlane> layers, masks;

void ofApp::setup(){
    increment = 0.02;
    numLayers = 3;
    filename = "translucent-image.png";

    masker.setup(numLayers);
    plane.setup(filename);
    for(int i = 0; i < numLayers; i++) {
        layers.push_back(plane);
        masks.push_back(plane);
    }
}

void ofApp::update(){
    for(int i = 0; i < numLayers; i++) {
        masker.beginLayer(i);
        {
            if(i == 0) { //Layer-specific transforms }
            layers.at(i).draw();
        }
        masker.endLayer(i);

        masker.beginMask(i);
        {
            ofBackground(ofColor::white);
            if(i == 0) { //Layer-specific transforms }
            masks.at(i).draw();
        }
        masker.endMask(i);
    }
}

void ofApp::draw(){
    ofBackground(ofColor::white);
    masker.draw();
}
	

Sketch 2015-07-27

        void ofApp::setup(){
    increment = 0.01;
    ofSetWindowShape(500, 500);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 116, 156);
    gif.fadeInOut(8, 2, ofColor::white, 1);
    masker.setup(3);
    transp1.setup("foil-large-transp.png");
    transp1.setTexturePositionY(0.5);
    transp2.setup("road-transp.png");
    transp2.setTexturePositionY(0.5);
    transp3.setup("road-transp.png");
    transp3.setTexturePositionY(0.5);
    transp4.setup("foil-large-transp.png");
    transp4.setTexturePositionY(0.5);
    transp5.setup("foil-large-transp.png");
    transp5.setTexturePositionY(0.5);
    transp6.setup("road-transp.png");
    transp6.setTexturePositionY(0.5);
}

void ofApp::update(){
    masker.beginLayer(0);
    {
        transp1.incrementTextureOffsetY(-increment);
        transp1.incrementTextureScale(-increment);
        transp1.draw();
    }
    masker.endLayer(0);

    masker.beginMask(0);
    {
        transp2.incrementTextureOffsetY(-increment);
        transp2.incrementTextureScale(-increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp2.draw();
    }
    masker.endMask(0);
    
    masker.beginLayer(1);
    {
        transp3.incrementTextureOffsetY(increment);
        transp3.incrementTextureScale(increment);
        transp3.draw();
    }
    masker.endLayer(1);
    
    masker.beginMask(1);
    {
        transp4.incrementTextureOffsetY(increment);
        transp4.incrementTextureScale(increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp4.draw();
    }
    masker.endMask(1);
    
    masker.beginLayer(2);
    {
        transp5.incrementTextureOffsetX(increment);
        transp5.incrementTextureScale(-increment);
        transp5.draw();
    }
    masker.endLayer(2);
    
    masker.beginMask(2);
    {
        transp6.incrementTextureOffsetX(-increment);
        transp6.incrementTextureScale(increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp6.draw();
    }
    masker.endMask(2);
}

void ofApp::draw(){
    gif.begin();
    {
        ofBackground(ofColor::white);
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Texture explosion

Daily sketch

Sketch 2015-07-24

        void ofApp::setup(){
    increment = 0.02;
    numLayers = 3;
    filename = "condensation-transp2.png";

    ofSetWindowShape(500, 500);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 240, 280);
    gif.fadeInOut(8, 2, ofColor::white, 1);

    masker.setup(3);
    plane.setup(filename);
    plane.setTexturePositionY(0.5);
    for(int i = 0; i < numLayers; i++) {
        layers.push_back(plane);
        masks.push_back(plane);
    }
}

void ofApp::update(){
    for(int i = 0; i < numLayers; i++) {
        masker.beginLayer(i);
        {
            if(i == 0) {
                layers.at(i).incrementTextureOffsetY(-increment);
                layers.at(i).incrementTextureScale(-increment);
            }
            if(i == 1) {
                layers.at(i).incrementTextureOffsetY(increment);
                layers.at(i).incrementTextureScale(increment);
            }
            if(i == 2) {
                layers.at(i).incrementTextureOffsetX(increment);
                layers.at(i).incrementTextureScale(-increment);
            }
            layers.at(i).draw();
        }
        masker.endLayer(i);

        masker.beginMask(i);
        {
            ofBackground(ofColor::white);
            ofSetColor(ofColor::white);
            if(i == 0) {
                masks.at(i).incrementTextureOffsetY(-increment);
                masks.at(i).incrementTextureScale(-increment*0.5);
            }
            if(i == 1) {
                masks.at(i).incrementTextureOffsetY(increment);
                masks.at(i).incrementTextureScale(increment*0.5);
            }
            if(i == 2) {
                masks.at(i).incrementTextureOffsetX(-increment);
                masks.at(i).incrementTextureScale(increment*0.5);
            }
            masks.at(i).draw();
        }
        masker.endMask(i);
    }
}

void ofApp::draw(){
    gif.begin();
    {
        ofBackground(ofColor::white);
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Based on the same technique from the 13th

Daily sketch

Sketch 2015-07-13

        void ofApp::setup(){
    increment = 0.01;
    ofSetWindowShape(500, 500);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 230, 279);
    gif.fadeInOut(8, 2, ofColor::white, 1);
    masker.setup(3);
    transp1.setup("road-transp.png");
    transp1.setTexturePositionY(0.5);
    transp2.setup("road-transp.png");
    transp2.setTexturePositionY(0.5);
    transp3.setup("road-transp.png");
    transp3.setTexturePositionY(0.5);
    transp4.setup("road-transp.png");
    transp4.setTexturePositionY(0.5);
    transp5.setup("road-transp.png");
    transp5.setTexturePositionY(0.5);
    transp6.setup("road-transp.png");
    transp6.setTexturePositionY(0.5);
}

void ofApp::update(){
    masker.beginLayer(0);
    {
        transp1.incrementTextureOffsetY(-increment);
        transp1.incrementTextureScale(-increment);
        transp1.draw();
    }
    masker.endLayer(0);

    masker.beginMask(0);
    {
        transp2.incrementTextureOffsetY(-increment);
        transp2.incrementTextureScale(-increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp2.draw();
    }
    masker.endMask(0);
    
    masker.beginLayer(1);
    {
        transp3.incrementTextureOffsetY(increment);
        transp3.incrementTextureScale(increment);
        transp3.draw();
    }
    masker.endLayer(1);
    
    masker.beginMask(1);
    {
        transp4.incrementTextureOffsetY(increment);
        transp4.incrementTextureScale(increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp4.draw();
    }
    masker.endMask(1);
    
    masker.beginLayer(2);
    {
        transp5.incrementTextureOffsetX(increment);
        transp5.incrementTextureScale(-increment);
        transp5.draw();
    }
    masker.endLayer(2);
    
    masker.beginMask(2);
    {
        transp6.incrementTextureOffsetX(-increment);
        transp6.incrementTextureScale(increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp6.draw();
    }
    masker.endMask(2);
}

void ofApp::draw(){
    gif.begin();
    {
        ofBackground(ofColor::white);
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Textures set loose to emerge

Daily sketch

Re-texturing an object

Transform the texture of an outlined "object" at variance to the outline or implied movement.

		ofxLayerMask masker;
ofxTexturePlane mask, texture;

void ofApp::setup(){
    masker.setup(1);
    mask.setup("black-and-white-mask.png");
    texture.setup("texture.png");
    increment = 0.02;
}

void ofApp::update(){
    mask.incrementTextureOffsetY(increment);
    texture.incrementTextureOffsetY(-increment);

    masker.beginLayer();
    {
        texture.draw();
    }
    masker.endLayer();

    masker.beginMask();
    {
        mask.draw();
    }
    masker.endMask();
}

void ofApp::draw(){
    masker.draw();
}
	

Sketch 2015-07-22

        void ofApp::setup(){
    ofSetWindowShape(1000, 800);
    numLayers = 6;
    gif.setup(ofGetTimestampString("out/%Y-%m-%d"), 80, 500, 500, ISOLATE_DRAWING);
    gif.fadeInOut(2, 4, 4);
    masker.setup(500, 500, numLayers, ISOLATE_LAYERS);
    masker.toggleOverlay();
    glass.setup("glass3.png", 500, 500, 2.0);
    wbw.setup("wbw.png", 500, 500, 0.5);
    for(int i = 0; i < numLayers; i++) {
        wbw.setTextureOffset(i);
        wbws.push_back(wbw);
    }
    bwb.setup("bwb.png", 500, 500, 0.25);
    for(int i = 0; i < numLayers; i++) {
        bwb.setTextureOffset(8-i);
        bwbs.push_back(bwb);
    }
}

void ofApp::update(){
    for(int i = 0; i < numLayers; i++) {
        wbws.at(i).incrementTextureOffset(-0.01, i % 2 == 0 ? -0.01 : 0.01);
        bwbs.at(i).incrementTextureOffset(i % 2 == 0 ? 0.01 : 0, i % 2 == 0 ? -0.01 : 0.01);
        
        masker.beginLayer(i);
        {
            if(i % 2 == 0) {
                ofSetColor(ofColor:: red);
                for(int y = i * 2; y < gif.height; y+=10) {
                    ofLine(0, y, gif.width, y);
                }
            } else {
                wbws.at(i).draw();
            }
        }
        masker.endLayer(i);
        
        masker.beginMask(i);
        {
            bwbs.at(i).draw();
        }
        masker.endMask(i);
    }
}

void ofApp::draw(){
    gif.begin();
    {
        glass.incrementTextureOffsetY(0.01);
        glass.draw();
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

An endless process

Daily sketch

Sketch 2015-07-21

        void ofApp::setup(){
    ofSetWindowShape(1000, 800);
    gif.setup(ofGetTimestampString("out/%Y-%m-%d"), 63, 500, 500, ISOLATE_DRAWING);
    masker.setup(500, 500, 3, ISOLATE_LAYERS);
    masker.toggleOverlay();
    mask.setup("face-mask.png", 500, 500, 0.0625, TEXTURE_OFFSET_MIDDLE_CENTER);
    glass.setup("glass3.png", 500, 500);
    shapeSystem.setup();
    for(int i = 0; i < 30; i++) {
        shape.setupGradientArc(60, ofRandom(10, 190), ofRandom(200, 400), ofRandom(180));
        shape.rotateZ(ofRandom(360));
        shape.setPosition(
            ofRandom(-60, gif.width + 60),
            ofRandom(-60, gif.width + 60));
        shape.setColor(ofColor(ofColor::white, ofRandom(5, 250)));
        shapes.push_back(shape);
    }
    for(int i = 0; i < shapes.size(); i++) {
        shapeSystem.add(shapes.at(i));
    }
}

void ofApp::update(){
    mask.incrementTextureOffsetY(0.03183098861838);
    glass.incrementTextureOffsetY(-0.03183098861838);
    glass.setTextureScale(ofMap(sin(ofGetFrameNum() * 0.1), -1, 1, 2, 4));
    mask.setTextureScale(ofMap(sin(ofGetFrameNum() * 0.1), -1, 1, 0.25, 1));
    for(int i = 0; i < shapes.size(); i++) {
        shapes.at(i).incrementRotateZ(i % 2 == 0 ? -5.71428571428571 : 5.71428571428571);
    }
    masker.beginLayer(0);
    {
        ofBackground(ofColor::black);
        mask.draw();
    }
    masker.endLayer(0);
    
    masker.beginMask(0);
    {
        ofBackground(ofColor::black);
        shapeSystem.draw();
    }
    masker.endMask(0);
    
    masker.beginLayer(1);
    {
        ofSetColor(ofColor::red);
        glass.draw();
    }
    masker.endLayer(1);
    
    masker.beginMask(1);
    {
        masker.drawLayer(0, false);
    }
    masker.endMask(1);
    
    masker.beginLayer(2);
    {
        ofBackground(ofColor::white);
        masker.drawLayer(1);
        masker.drawLayer(0);
    }
    masker.endLayer(2);
}

void ofApp::draw(){
    gif.begin();
    {
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

A shape system with gradient arcs

Daily sketch

Sketch 2015-07-15

        void ofApp::setup(){
    ofSetWindowShape(1000, 800);
    gif.setup(ofGetTimestampString("out/%Y-%m-%d"), 120, 500, 500);
    gif.fadeInOut(2, 4, ofColor::white);
    numLayers = 7;
    masker.setup(500, 500, numLayers + 1);
    masker.toggleOverlay();
    setupTransparencies();
    setupCardboards();
    setupIncrements();
    glass.setup("glass1.png", 500, 500, 2.0, TEXTURE_OFFSET_MIDDLE_CENTER);
    circle.setup("circle-feather3.png", 500, 500, 1.0, TEXTURE_OFFSET_MIDDLE_CENTER);
}

void ofApp::setupTransparencies() {
    image.setup("card-invert.png", 500, 500, 1.5, TEXTURE_OFFSET_MIDDLE_LEFT);
    transparencies.push_back(image);
    image.setup("card-invert.png", 500, 500, 0.75, TEXTURE_OFFSET_BOTTOM_RIGHT);
    transparencies.push_back(image);
    image.setup("card-invert.png", 500, 500, 1.25, TEXTURE_OFFSET_TOP_CENTER);
    transparencies.push_back(image);
    image.setup("card-invert.png", 500, 500, 1.5, TEXTURE_OFFSET_BOTTOM_LEFT);
    transparencies.push_back(image);
    image.setup("card-invert.png", 500, 500, 0.75, TEXTURE_OFFSET_TOP_RIGHT);
    transparencies.push_back(image);
    image.setup("card-invert.png", 500, 500, 1.25, TEXTURE_OFFSET_MIDDLE_CENTER);
    transparencies.push_back(image);
}

void ofApp::setupCardboards() {
    image.setup("cardboard.png", 500, 500, 2.0, TEXTURE_OFFSET_MIDDLE_LEFT);
    cardboards.push_back(image);
    image.setup("cardboard.png", 500, 500, 2.0, TEXTURE_OFFSET_BOTTOM_RIGHT);
    cardboards.push_back(image);
    image.setup("cardboard.png", 500, 500, 2.0, TEXTURE_OFFSET_TOP_CENTER);
    cardboards.push_back(image);
    image.setup("cardboard.png", 500, 500, 2.0, TEXTURE_OFFSET_BOTTOM_LEFT);
    cardboards.push_back(image);
    image.setup("cardboard.png", 500, 500, 2.0, TEXTURE_OFFSET_TOP_RIGHT);
    cardboards.push_back(image);
    image.setup("cardboard.png", 500, 500, 2.0, TEXTURE_OFFSET_MIDDLE_CENTER);
    cardboards.push_back(image);
}

void ofApp::setupIncrements() {
    incrementMultiplier = 0.0125;
    for(int i = 1; i <= numLayers / 2; i++) {
        increments.push_back(-incrementMultiplier * i);
        increments.push_back(incrementMultiplier * i);
    }
}

void ofApp::update(){
    glass.setTexturePosition(ofRandom(2), ofRandom(2));
    glass.setTextureScale(ofRandom(1.0, 6.0));
    masker.beginLayer(0);
    {
        ofSetColor(ofColor::red);
        glass.draw();
        ofSetColor(ofColor::white);
    }
    masker.endLayer(0);

    masker.beginMask(0);
    {
        circle.draw();
    }
    masker.endMask(0);

    for(int i = 1; i < numLayers; i++) {
        masker.beginLayer(i);
        ofPushStyle();
        {
            ofSetColor(ofColor(i * 20 + 140, 140, i * 20 + 140));
            ofSetColor(ofColor::red);
            cardboards.at(i-1).incrementTextureOffsetY(i % 2 == 0 ? -0.05 : 0.05);
            cardboards.at(i-1 % 2).draw();
        }
        ofPopStyle();
        masker.endLayer(i);
        
        masker.beginMask(i);
        ofPushStyle();
        {
            transparencies.at(i - 1).incrementTextureOffsetY(increments.at(i - 1) * ((i % 2 == 0) ? sin(ofGetFrameNum() * 0.005) : cos(ofGetFrameNum() * 0.005)));
            transparencies.at(i - 1).incrementTextureOffsetX(i % 2 == 0 ? -0.018 : 0.018);
            transparencies.at(i - 1).draw();
        }
        ofPopStyle();
        masker.endMask(i);
    }
    
    masker.beginLayer();
    {
        ofSetColor(ofColor::white);
        masker.drawLayers(0, numLayers - 1);
    }
    masker.endLayer();
    
    masker.beginMask();
    {
        ofSetColor(ofColor::white);
        circle.draw();
    }
    masker.endMask();
}

void ofApp::draw(){
    gif.begin();
    ofPushStyle();
    {
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        masker.draw();
    }
    ofPopStyle();
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Red, red, red

Daily sketch

Sketch 2015-06-15

        void ofApp::setupAnim() {
    masker.setup(width, height);
    layer1 = masker.newLayer();
    layer2 = masker.newLayer();
    
    image1.setup("foil.png");
    image2.setup("foil.png");
    
    image1.setOffsetX(0);
    image1.setOffsetY(0);
    image2.setOffsetX(1);
    image2.setOffsetY(1);
    
    pos = 0;
    size = width * 0.2;
}

void ofApp::updateAnim(){
    pos+=10;
    if(pos > height * 2) {
        pos = 0;
    }
    
    masker.beginLayer(layer1);
    {
        image1.incrementOffsetX(0.01);
        image1.incrementOffsetY(0.01);
        image1.draw();
    }
    masker.endLayer(layer1);
    
    masker.beginMask(layer1);
    {
        ofBackground(ofColor::black);
        ofSetColor(ofColor::white);
        for(int x = 0; x < size; x++) {
            if(x % 2 == 0) {
                ofRect(x * size, height - pos, size, height);
            }
        }
    }
    masker.endMask(layer1);

    masker.beginLayer(layer2);
    {
        image2.incrementOffsetX(-0.01);
        image2.incrementOffsetY(-0.01);
        image2.draw();
    }
    masker.endLayer(layer2);
    
    masker.beginMask(layer2);
    {
        ofBackground(ofColor::black);
        ofSetColor(ofColor::white);
        for(int x = 0; x < size; x++) {
            if(x % 2 != 0) {
                ofRect(x * size, pos - height, size, height);
            }
        }
    }
    masker.endMask(layer2);
}

void ofApp::drawAnim() {
    ofBackground(ofColor::black);
    masker.draw();
    masker.drawOverlay();
    
    if(ofGetFrameNum() == 100) {
        renderGif();
    }
}
    

Masking and texture planes are getting much easier

Daily sketch

Reveal a color

  1. Draw a flat color
  2. Draw a partially transparent texture over the color
  3. Transform the texture
		float increment;
ofxTexturePlane plane;

void ofApp::setup(){
    increment = 0.02;
    plane.setup("partially-transparent.png");
}

void ofApp::update(){
    plane.incrementTextureScale(-increment);
}

void ofApp::draw(){
    ofBackground(ofColor::red);
    plane.draw();
}
	

Sketch 2015-07-18

        void ofApp::setup(){
    ofSetWindowShape(1000, 800);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 30, 75, 500, 500, ISOLATE_DRAWING);
    masker.setup(500, 500, 1, ISOLATE_LAYERS);
    masker.toggleOverlay();

    glass1.setup("glass.png", 500, 500, 2.0);
    glass2.setup("glass.png", 500, 500, 2.0);
    framesBeforeRefresh = 15;
}

void ofApp::update(){
    if(ofGetFrameNum() % framesBeforeRefresh == 0) {
        refresh = true;
        int offsetIndex = floor(ofGetFrameNum() / framesBeforeRefresh);
        offsetIndex = ((offsetIndex % 3) + 0) * 2;
        glass1.setTextureOffset(offsetIndex);
        glass2.setTextureOffset(offsetIndex);
        glass1.setTextureScale(3.0);
        glass2.setTextureScale(3.0);
    } else {
        refresh = false;
        glass1.incrementTextureScale(-0.05);
        glass2.incrementTextureScale(0.05);
    }
    
    masker.beginLayer(0);
    {
        glass1.draw();
    }
    masker.endLayer(0);
    
    masker.beginMask(0);
    {
        glass2.draw();
    }
    masker.endMask(0);
}

void ofApp::draw(){
    gif.begin();
    {
        ofEnableAlphaBlending();
        if(refresh) {
            ofSetColor(ofColor::red);
            ofRect(0, 0, gif.width, gif.height);
        }
        masker.draw();
        ofDisableAlphaBlending();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

"...a conscious, purposeful, and personal subject confronting an unconscious, purposeless, and impersonal universe..." (Richard Tarnas)

Daily sketch

Sketch 2015-07-12

        void ofApp::setup(){
    increment = 0.02;
    ofSetWindowShape(500, 500);
    gif.setupPaused(ofGetTimestampString("out/%Y-%m-%d"), 105, 140);
    gif.fadeInOut(17, 4, ofColor::red, 1);
    masker.setup(1);
    transp1.setup("road-transp.png");
    transp1.setTexturePositionY(0.5);
    transp2.setup("road-transp.png");
    transp2.setTexturePositionY(0.5);
}

void ofApp::update(){
    masker.beginLayer(0);
    {
        transp1.incrementTextureScale(-increment);
        transp1.draw();
    }
    masker.endLayer(0);

    masker.beginMask(0);
    {
        transp2.incrementTextureScale(-increment*0.5);
        ofBackground(ofColor::white);
        ofSetColor(ofColor::white);
        transp2.draw();
    }
    masker.endMask(0);
}

void ofApp::draw(){
    gif.begin();
    {
        ofBackground(ofColor::red);
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    masker.drawOverlay();
}
    

Transparencies masking transparencies (against a red background)

Daily sketch

Reveal a shape system

  1. Draw a shape system
  2. Draw a partially transparent texture over the system
  3. Transform the shapes and the texture independently
		ofxShapeSystem shapeSystem;
ofxShape shape;
vector<ofxShape> shapes;
ofxTexturePlane plane;
float increment, shapeSize, thickness;

void ofApp::setup(){
    //Create a grid of shapes
    shapeSize = 100;
    thickness = 100;
    for(int i = 0; i < ofGetWidth(); i += shapeSize) {
        for(int j = 0; j < ofGetHeight(); j += shapeSize) {
            shape.setupHollowArc(30, thickness, shapeSize, 180);
            shape.setColor(ofColor::fromHsb(ofRandom(255), 255, 255));
            shape.setPosition(i + shapeSize * 0.5, j + shapeSize * 0.5);
            shapes.push_back(shape);
        }
    }

    //Add shapes to a system
    shapeSystem.setup();
    for(int i = 0; i < shapes.size(); i++) {
        shapeSystem.add(shapes.at(i));
    }

    //Prepare a texture
    increment = -0.005;
    plane.setup("partially-transparent.png");
}

void ofApp::update(){
    //Transform shapes
    for(int i = 0; i < shapes.size(); i++) {
        i % 2 == 0 ?
          shapes.at(i).incrementRotateZ(1) :
          shapes.at(i).incrementRotateZ(-1);
    }

    //Transform texture
    plane.incrementTexturePositionY(increment);
}

void ofApp::draw(){
    //Draw
    ofBackground(ofColor::black);
    shapeSystem.draw();
    plane.draw();
}
	

Sketch 2015-07-01

        void ofApp::setup(){
    ofSetWindowShape(500, 500);
    gif.setup(ofGetTimestampString("%Y-%m-%d"), 60);
    
    ofEnableSmoothing();
    shapeSystem.setup();
    masker.setup(8);

    for(int i = 0; i < 8; i++) {
        textures.push_back(texture);
        textures.at(i).setup("road" + ofToString(i % 4 + 1) + ".png", (i+1) * 0.3);
    }
    
    shapeSize = 100;
    thickness = 100;
    halfShapeSize = shapeSize * 0.5;
    
    for(int i = 0; i < gif.width; i += shapeSize) {
        for(int j = 0; j < gif.height; j += shapeSize) {
            shape.setupHollowArc(30, thickness, shapeSize, 180);
            shape.setColor(ofColor::fromHsb(ofRandom(255), ofRandom(100, 255), ofRandom(100, 255)));
            shape.setBlur(30);
            shape.setPosition(ofVec3f(i + halfShapeSize, j + halfShapeSize, 0));
            shape.rotateZ(ofRandom(360));
            shapes.push_back(shape);
        }
    }
    
    for(int i = 0; i < shapes.size(); i++) {
        shapeSystem.add(shapes.at(i));
    }
}

void ofApp::update(){
    for(int i = 0; i < shapes.size(); i++) {
        i % 2 == 0 ?
        shapes.at(i).incrementRotateZ(6) :
        shapes.at(i).incrementRotateZ(-6);
    }
    
    for(int i = 0; i < masker.numLayers(); i++) {
        textures.at(i % textures.size()).incrementTextureOffsetY(-0.03333333333);
        masker.beginLayer(i);
        {
            ofBackground(ofColor::black);
            ofEnableAlphaBlending();
            rotateScreen(90 * i);
            shapeSystem.draw();
            ofDisableAlphaBlending();
        }
        masker.endLayer(i);
        
        masker.beginMask(i);
        {
            ofEnableAlphaBlending();
            if(ofGetFrameNum() == 0) {
                ofBackground(ofColor::black);
            } else {
                ofSetColor(ofColor::black, 64);
                ofRect(0, 0, gif.width, gif.height);
            }

            ofSetColor(ofColor::white, 196);
            textures.at(i % textures.size()).draw();
            if(ofRandom(1) > 0.96) {
                for(int j = 0; j < 4; j++) {
                    ofSetColor(j % 2 == 0 ? ofColor(ofColor::white, ofRandom(64, 196)) : ofColor::black);
                    ofTriangle(ofRandom(-gif.width, 0), ofRandom(-gif.height, 0),
                               ofRandom(0, gif.width), ofRandom(0, gif.height),
                               ofRandom(gif.width, gif.doubleWidth), ofRandom(gif.height, gif.doubleHeight));
                    rotateScreen(90);
                }
            }
            ofDisableAlphaBlending();
        }
        masker.endMask(i);
    }
}

void ofApp::draw(){
    gif.begin();
    {
        ofBackground(ofColor::black);
        masker.draw();
    }
    gif.endAndCaptureFrame();
    gif.draw();
    
    masker.drawOverlay();
}

void ofApp::rotateScreen(float degrees) {
    ofTranslate(gif.halfWidth, gif.halfHeight, 0);
    ofRotate(degrees);
    ofTranslate(-gif.halfWidth, -gif.halfHeight, 0);
}
    

"You no longer require an internal model ... you simply need the ability to visually perceive ... and the experience to move" (source)

Daily sketch

Sketch 2015-06-23

        void ofApp::setupAnim() {
    paused = true;
    numLayers = 9;
    topLayer = numLayers - 1;
    spacing = 100;
    thickness = 50;
    offset = 0;
    increment = 2;
    masker.setup(numLayers);
    //masker.toggleOverlay();
    
    image.setup("surface.png", width, height, 1, TEXTURE_OFFSET_BOTTOM_LEFT);
    image.incrementTextureOffsetY(0.5);
}

void ofApp::updateAnim(){
    incrementOffset();

    for(int i = 0; i < numLayers - 1; i++) {
        masker.beginLayer(i);
        ofBackground(ofColor(0, 0, 0, 0));
        hue = ofMap(i, 0, numLayers, 20, 140);
        ofSetColor(ofColor::fromHsb(hue, 255, 255, 240));
        rotateScreen(i * 45);
        drawLines();
        masker.endLayer(i);
        
        masker.beginMask(i);
        ofBackground(ofColor::black);
        ofSetColor(ofColor::white);
        rotateScreen(i * 45);
        rotateScreen(90);
        drawLines();
        rotateScreen(-90);
        masker.endMask(i);
    }
    
    masker.beginLayer(topLayer);
    masker.draw();
    masker.endLayer(topLayer);
    
    masker.beginMask(topLayer);
    ofSetColor(ofColor::white);
    image.incrementTextureOffsetX(0.02857142857);
    image.draw();
    rotateScreen(180);
    image.draw();
    rotateScreen(90);
    image.draw();
    rotateScreen(180);
    image.draw();
    masker.endMask(topLayer);
    
}

void ofApp::drawAnim() {
    if(ofGetFrameNum() == spacing) {
        paused = false;
    }
    ofBackground(ofColor::black);
    masker.drawLayer(topLayer);
    masker.drawOverlay();
    if(ofGetFrameNum() == spacing + (spacing / increment)) {
        renderGif();
    }
}

void ofApp::incrementOffset() {
    offset+=increment;
    if(offset >= spacing) {
        offset = 0;
    }
}

void ofApp::drawLines() {
    for(int y = -height; y < doubleHeight; y += spacing) {
        ofRect(-width, y + offset, tripleWidth, thickness);
    }
}

void ofApp::rotateScreen(float degrees) {
    ofTranslate(halfWidth, halfHeight);
    ofRotateZ(degrees);
    ofTranslate(-halfWidth, -halfHeight);
}
    

Textures and computer graphics

Daily sketch