createShader() not working on p5.Graphics

Not sure if this is a bug but when I try to use createShader() instead of loadShader() it doesn’t work on a p5.Graphics object.

Figured I’d post here before creating an issue in case I’m doing something wrong.

Below is a demo sketch and you can see it running on the web editor at: https://editor.p5js.org/duskvirkus/sketches/dWj7w-k3k

  • Doesn’t have a problem with the exact same sketch when loadShader() is used. To demonstrate this, use let useCreateShader = false;.
  • createShader() works when not trying to draw on a p5.Graphics object. See this at https://editor.p5js.org/duskvirkus/sketches/R_bjIjzNG

Any advice would be helpful. I’ll file an issue unless someone points out something I’m missing.

sketch.js

let useCreateShader = true;

let sh;

function preload(){
  if (!useCreateShader) {
    sh = loadShader('shader.vert', 'shader.frag');
  }
}

function setup() {
  createCanvas(400, 400, WEBGL);
  noStroke();
  
  if (useCreateShader) {
    sh = createShader(
      `
// vert
#ifdef GL_ES
precision mediump float;
#endif

attribute vec3 aPosition;

void main() {
  vec4 positionVec4 = vec4(aPosition, 1.0);
  positionVec4.xy = positionVec4.xy * 2.0 - 1.0; 
  gl_Position = positionVec4;
}
  `,
      `
// frag
#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;

void main() {
  vec2 st = gl_FragCoord.xy/u_resolution.xy; 
  gl_FragColor = vec4(st.x,0.0,1.0,1.0); // R,G,B,A
}
  `
    );
  }

}

function draw() {

  sh.setUniform('u_resolution', [width, height]);

  shader(sh);
  rect(0,0,width, height);
}

shader.vert

// vert
#ifdef GL_ES
precision mediump float;
#endif

attribute vec3 aPosition;

void main() {
  vec4 positionVec4 = vec4(aPosition, 1.0);
  positionVec4.xy = positionVec4.xy * 2.0 - 1.0; 
  gl_Position = positionVec4;
}

shader.frag

// frag
#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;

void main() {
  vec2 st = gl_FragCoord.xy/u_resolution.xy; 
  gl_FragColor = vec4(st.x,0.0,1.0,1.0); // R,G,B,A
}
1 Like

hi!! this seems super tricky. I made it working
https://editor.p5js.org/micuat/sketches/wW6KjbIBp

  1. createShader has to be a member of the graphics object
  2. rect doesn’t seem to have texcoord so you need to use a plane

(I didn’t see references but just guessed and made it work…)

2 Likes

just to clarify (because I was confused just right now) - the graphics object is fine with rect because the shader is taking the screen coordinate instead of texture coordinate (am I right?). But when you texture map this graphics to render on the main buffer, you need to use plane which has texcoord.

Hm interesting. I just spent awhile digging through p5 source code and thought I’d figured out the problem problem so I just created an issue. createShader() assumes _renderer causing bug when used with p5.Graphics · Issue #5099 · processing/p5.js · GitHub.

Interesting to see that plane fixed the problem. I’ll have to look into it more to understand if what I came up with is right.

I’m not sure that plane would be the best solution though because I’m trying to setup a library for gradients that fits with the fill() and stroke() paradigm of p5. The reason I’m using shaders is it seems like it’s the best way to make gradients without destroying performance. I seem to be pushing the boundaries of what they were intended for in p5.

1 Like

Thanks for opening the issue!

If what you need is only gradient maybe there’s workaround using canvas api
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors#gradients

You can access ctx from drawingContext
https://p5js.org/reference/#/p5/drawingContext

1 Like