Skip to main content

Running multiple rendering pipelines in parallel

So far we have only used the default P5Asciifier instance provided by the p5asciify object, which applies ASCII conversion to the main canvas. However, you can create multiple P5Asciifier instances to run different rendering pipelines in parallel on any texture or the main canvas. This is useful for creating complex visual effects or combining different rendering techniques with varying fonts, font sizes, grids, and other parameters.

Example

// Define a variable to store the default `P5Asciifier` instance
let defaultAsciifier; 

// Define a variable to store the custom `P5Asciifier` instance
let customAsciifier; 

// Framebuffer the custom asciifier will asciify
let customFramebuffer; 

function setup() {
    setAttributes('antialias', false);
    createCanvas(windowWidth, windowHeight, WEBGL);
}

function setupAsciify() {
    // Fetch the default `P5Asciifier` instance provided by the library
    defaultAsciifier = p5asciify.asciifier();

    // Create a new asciifier instance and apply it to a custom framebuffer
    customFramebuffer = createFramebuffer();
    customAsciifier = p5asciify.add(customFramebuffer);

    // Set the font size for both asciifiers
    defaultAsciifier.fontSize(16);
    customAsciifier.fontSize(32);

    defaultAsciifier.renderers().get("brightness").update({
        enabled: true,
        characters: " .:-=+*#%@",
        characterColor: "#ffffff",
        characterColorMode: 'sampled',
        backgroundColor: "#000000",
        backgroundColorMode: 'fixed',
        invertMode: false,
        rotationAngle: 0
    });

    customAsciifier.renderers().get("brightness").update({
        enabled: true,
        characters: " .:oO@",
        characterColor: "#ffffff",
        characterColorMode: 'sampled',
        backgroundColor: "#000000",
        backgroundColorMode: 'fixed',
        invertMode: true,
        rotationAngle: 0
    });

    // Make the background of both asciifiers fully transparent.
    defaultAsciifier.background([0, 0, 0, 0]);
    customAsciifier.background([0, 0, 0, 0]);
}

function draw() {
    directionalLight(255, 255, 255, 0, 0, -1);

    // Draw anything on the custom framebuffer for the custom asciifier to asciify
    customFramebuffer.begin();
    clear();
    fill(255);
    rotateX(radians(frameCount * 3));
    rotateZ(radians(frameCount));
    box(400, 100, 100);
    customFramebuffer.end();

    // Draw anything on the canvas for the default asciifier to asciify
    clear();
    normalMaterial();
    rotateX(radians(frameCount * 3));
    rotateY(radians(frameCount));
    torus(150, 100);
}

function drawAsciify() {
    background(0); // Set the background to black, removing everything previously drawn

    // Draw both asciifier textures on top of each other
    image(defaultAsciifier.texture, -width / 2, -height / 2);
    image(customAsciifier.texture, -width / 2, -height / 2);
}

function windowResized() {
    resizeCanvas(windowWidth, windowHeight);
}

Explanation

In the example above, we fetch the default P5Asciifier instance into defaultAsciifier and create a new P5Asciifier instance in setupAsciify() using p5asciify.add(). This new instance is stored in the customAsciifier variable. The newly added P5Asciifier instance is applied to the customFramebuffer texture, which is created anywhere during setup.

The newly added P5Asciifier instance has the same properties and renderers defined as the default one, but you can customize it to your liking. For example, you can set a different font, font size, or grid size for the new instance. You can also add or remove renderers from the new instance without affecting the default one.

Within the draw() loop, we now draw varying content to the customFramebuffer and the main canvas. While our default P5Asciifier instance is still applied to the main canvas and generates the ASCII representation of it, the new P5Asciifier instance creates an ASCII representation of the customFramebuffer texture.

To provide total freedom to the user, using multiple P5Asciifier instances requires you to utilize the drawAsciify() function to draw the respective textures containing the ASCII representations to the main canvas. In drawAsciify(), we first clear the main canvas and then draw the textures containing the ASCII representations in any order/position/size/rotation/.. to the main canvas.