No graphics after resetShader()

Hello everybody !

I come to you because I have been encountering a problem that I have a lot of struggle to solve. At this point I am almost sure it’s a bug but I’d rather have your opinion first !

My goal is to draw the background with an animated shader, then draw with basic P5 functions. The problem is that I cannot draw anything after resetting the shader with the proper function call. Did I forgot something ?

Here is the code of the main script.js file :

var _p
var _shaderMngr 
var _dataMngr = {
    getTimeRef : ()=>{
        return _p.frameCount *20
    }
}

let s = function( p ){
    _p = p
    
    p.preload =()=>{
        _shaderMngr =  new ShaderManager(p)
        _shaderMngr.loadShaders()
    }

    p.setup =()=> {
        p.createCanvas(window.innerWidth,window.innerHeight,p.WEBGL)
    }
    
    p.draw=()=>  {

        _shaderMngr.shaders.storm.run()
        p.quad(0,0,p.width,0,p.width,p.height,0,p.height)
        _shaderMngr.resetShader()

        p.fill([255,00,00])
        p.stroke([0,255,2])
        p.rect(-100,-150,200,200)
    }

    
}
let myp5 = new p5(s)

and the code in the other file managing my shader stuff :

class ShaderManager{
    p
    shaders = {}

    constructor(p){
        this.p = p   
    }

    loadShaders(){
        this.shaders.storm = new ShaderStorm(this.p)
    }

    resetShader(){
        this.p.resetShader();
    }
}

class ShaderStorm{
    p
    shader 
    
    constructor(p){
        this.p = p   
        this.shader = this.p.loadShader("datavisu.shader.storm.vert","datavisu.shader.storm.frag")
    //    this.shader.setUniform('iResolution',[p.width,p.height])
    }

    run (){
        // this.shader.setUniform('iTime',_dataMngr.getTimeRef())
        this.shader.setUniform('iTime',_dataMngr.getTimeRef()/1000)
        this.p.shader(this.shader)
    }

    update (){
        this.shader.setUniform('iTime',_dataMngr.getTimeRef()/1000)
    }
}

I have it set that way because I extracted it from my main project for further testing. Can you help me with this problem ? I have been stuck for quite sometimes now.
Thank you very much for your time !

1 Like

I have found a workaround with p.createGraphics(p,w,h,p.WEBGL) which handles my shader stuff and drawing this graphics when I need to in my non-webgl main p5 buffer.

I’m still curious I anyone has an explanation about the first behaviour.

1 Like

Honestly not sure – unfamiliar with the shader pipeline in p5.js. If you think it is a bug, at some point consider reporting it on https://github.com/processing/p5.js/issues

I ran into the same issue and also ended up using the workaround using createGraphics. I suspect the problem is that the vertex shader is not being reset by resetShader. I found that drawing in normalised space (0.0-1.0) using beginShape and vertex works after resetShader, so perhaps the original pixel space to clip space transformation is not reset.

1 Like

Thanks so much for sharing your experience.

If you have experience with a resetShader() issue and a workaround, would you be willing to report it as a new issue to the developers?

Hello there !
I’ve just run into the same issue, made some research, almost wrote a bug report, made some more experiments, and now I think I understand a little better what’s going on ^^

Because we are using WEBGL mode, everything is 3D (unlike in Processing where there is both P2D and P3D modes that are compatible with shaders).
Therefore, deciding what is on top of what depends on the z (depth) value, and not on the order of drawing anymore !

If you are doing 2D drawing and want to recover the default behavior, you can disable the depth test with these two lines after createCanvas :

const gl = canvas.getContext('webgl')
gl.disable(gl.DEPTH_TEST)

Here is a simple example : https://editor.p5js.org/JulesFouchy/sketches/beiJNt342

Hope this helps !

1 Like

Thank you so much, @JulesFouchy – that example is extremely helpful!