Hello
I’ve ran into some trouble trying to use shaders in conjunction with createGraphics. The shader works fine drawing to the main canvas, and can be used within a createGraphics canvas once, however after that it breaks and can’t be used anywhere (within the same canvas, another createGraphics canvas, the main canvas – even if I loop() the sketch).
I’ve pasted the code below. For testing purposes it draws 4 circles onto the canvas, which the fragment shader should turn red. In my example I have illustrated the problem by initialising two identical shaders (‘shaderTest’ and ‘shaderTest2’) which each draw 2 circles. You can see that, ‘shaderTest’ stops working after it is used once, whereas ‘shaderTest2’ is used twice with no issue (therefore, only 3 out of the 4 circles are drawn). The only difference I can see is that I use ‘shaderTest’ within a createGraphics canvas, and I use ‘shaderTest2’ within the main canvas.
let shaderTest;
let shaderTest2;
function preload() {
//These are the same shader (turns what image red)
shaderTest = loadShader("basic.vert", "basic.frag");
shaderTest2 = loadShader("basic.vert", "basic.frag");
}
function setup() {
createCanvas(400, 400, WEBGL);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2); //Put origin back to 0,0
fill(0);
noStroke();
background(220);
//Draw first circle
cnv = createGraphics(width, height, WEBGL);
cnv.translate(-width / 2, -height / 2);
cnv.fill(0);
cnv.noStroke();
cnv.shader(shaderTest); //Uses first shader
cnv.ellipse(200, 50, 50, 50);
cnv.resetShader();
image(cnv, 0, 0);
//Draw second circle
cnv2 = createGraphics(width, height, WEBGL);
cnv2.translate(-width / 2, -height / 2);
cnv.fill(0);
cnv2.noStroke();
cnv2.shader(shaderTest); //Uses first shader again, but...
cnv2.ellipse(200, 150, 50, 50);
cnv2.resetShader();
image(cnv2, 0, 0); //This doesn't show up!!
//Draw third circle
shader(shaderTest2);
ellipse(200, 250, 50, 50);
resetShader();
//Draw fourth circle
shader(shaderTest2);
ellipse(200, 350, 50, 50);
resetShader();
}
function mouseClicked() {
loop();
noLoop();
}
Here is the vertex shader:
#ifdef GL_ES
precision highp float;
#endif
attribute vec3 aPosition;
attribute vec2 aTexCoord;
attribute vec4 aVertexColor;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
varying vec2 vTexCoord;
varying vec4 vVertexColor;
void main() {
// Apply the camera transform
vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0);
// Tell WebGL where the vertex goes
gl_Position = uProjectionMatrix * viewModelPosition;
// Pass along data to the fragment shader
vTexCoord = aTexCoord;
vVertexColor = aVertexColor;
}
Here is the fragment shader:
#ifdef GL_ES
precision highp float;
#endif
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
I’ve tried a few things (using different shaders, clearing the canvases, initialising them in setup rather than draw, using the shader within the same createGraphics canvas, etc), but after messing around with this for hours, reading all the p5 js documentation I can find and searching the web for similar issues, I’ve come up blank.
I’m relatively new to using shaders, so there’s probably something obvious I’ve missed. Or I may be trying to do something that is not possible without realising it. Either way I’d be extremely grateful for some guidance on this. If it would help to have a p5 js editor version up and running, you can find a link here: p5.js Web Editor. Likewise, if I’ve not explained this issue well, I’m happy to rephrase if it helps (or to explain what I’m trying to achieve in my main project).
Thanks for your time!