Seamlessly changing the render target from on-screen to a larger off-screen graphic


#1

Hi folks,

Summary: I’d like to change my p5.js rendering target (ie. destination, or graphics buffer) from the on-screen physical window, to an off-screen graphics buffer, by just using some “setRenderTarget()” call, but not changing the basic code from eg. “line(x1, y1, x2, y2)” to “offScreenBuffer.line(x1, y1, x2, y2)”.

Detail: I’ve got a nice p5.js prog rendering some dense 2D digital art into the screen buffer, typically 1200 x 900 pixels, or I can go to say 2400 x 1800 for better quality. Call it a very dense Victor Vasarely style of thing if you like. Now I’d like to create an off-screen buffer with say “bigBuf = createGraphics(8000, 6000)”, and render the same art into it. Which could then be saved to a file and printed down at my Digital Art Print shop (at considerable expense :unamused: ).

I’d like to just re-target the normal rendering calls, ie. stroke(), fill(), point(), line(), quad() to the new buffer with something like …

if (mode === "Production") {  
    setRenderTarget(bigBuf); 
    scale(someFactor, someFactor);
   // other minor adjustments maybe

} else if (mode === "Development") {
   // do nothing, target remains normal screen buffer.
   // or ..
   setRenderTarget(screenBuf);  // where we have got a handle to screenBuf somehow previously.
}

// And now we can use the same code, for either the screen, or the off-screen buffer

fill(1,2,3,4);
line(...);
triangle(...);

However as far as I can see, p5.js requires explicit targeting of each render call to bigBuf, eg.

 bigBuf.fill(1,2,3,4);
 bigBuf.line(...);
 // etc

So, is there a way to just switch the target of all rendering calls to be a particular off-screen buffer as above ?

I guess I could interlude all the calls I use with “function myFill(arg, arg, arg, arg)” and inside myFill() render to screen or bigBuf as required, but that seems clumsy.

Hope that’s fairly clear, I gave some context of what I’m doing to assist the reader.

ATdhvaannkcse for any responses.

(Edit: I forgot to say, I have searched fairly thoroughly in old and new Processing/p5.js forums, and StackOverflow p5.js topics, and Google generally. But you can miss the key phrase: you search for “change render target” but the hit you need is under “set render buffer” or “specify graphics destination”).


#2

Ok, I found a workable solution. I created a bunch of interludes like:

function quad_(...args) {
  quad(...args);            // render to onscreen canvas
  buf.quad(...args);        // render to offscreen buffer 
}

function noStroke_() {      // no args needed here
  noStroke();
  buf.noStroke();
}

and in the main app (sketch) I call “quad_(args)”, which uses the “…rest” syntax to collect the args, and the identical looking “…spread” operator to send them on to the real call. (Not really identical of course - JS knows that one is in the formal parameters of a function definition, and the other is in the argument list of a function call). I only needed to interlude about 25 calls which was fine.

In fact this method gives some finer control than what I originally wanted. For things that don’t need to appear in the high-definition offscreen “artwork” buffer, like help text, and on-screen debug text, and construction lines and curves and other ephemeral markers, they can continue to call just “text()” or “line()” etc. and appear only in the on-screen canvas.

I’d still be interested in any response to my original question - can I re-target all p5.js rendering calls by calling some “setRenderTarget(someGraphicsContext)”, and in particular swapping between the on-screen canvas and an off-screen buffer. I recall this was how it was done in OpenGL. There was always just one current active graphics context, I think.

Ciao, GE.