oframe / ogl

Minimal WebGL Library
https://oframe.github.io/ogl/examples
3.77k stars 213 forks source link

Feedback loop using Post #158

Closed Hugofgx9 closed 2 years ago

Hugofgx9 commented 2 years ago

Hey everyone,

Has anyone managed to make a feedback loop in ogl? I tried several versions using Post and a feedback Pass but I encounter many errors in the render loop or not the expected result. Here is the most successful version and that seems to me the most logical. I think there is a reference to the texture that I'm having trouble with but I can't figure out which one.

Thx for your help

// render the scene to the postfeedback texture, but not render on canvas
this.feedbackPass.enabled = false;
this.postFeedback.targetOnly = true;
this.postFeedback.render({ scene: this.scene });

//render the scene and showing it on the canvas
this.feedbackPass.enabled = true;
this.postFeedback.targetOnly = false;
this.postFeedback.render({ texture: this.feedbackPass.uniforms.tMap });

//copy the current render to tPreviousFrame
this.feedbackPass.uniforms.tPreviousFrame.value = this.postFeedback.uniform;
Hugofgx9 commented 2 years ago

also tried this one

    render() {
        // this.radialPass.uniforms.uTime.value = this.webgl.clock * 0.1;

        //draw to texture
        this.feedbackPass.enabled = false;
        this.postFeedback.targetOnly = true;
        this.postFeedback.render({ scene: this.scene, camera: this.camera, update: false, target: this.feedbackPass.uniforms.tPreviousFrame });

        //draw to canvas 
        this.feedbackPass.enabled = true;
        this.postFeedback.targetOnly = false;
        this.postFeedback.render({ scene: this.scene, camera: this.camera });

        // this.webgl.renderer.render({texture: this.feedbackPass.uniforms.tPreviousFrame.value})

    }
gordonnl commented 2 years ago

Hey there, What exactly are you trying to achieve? I'm not sure I understand, sorry!

Hugofgx9 commented 2 years ago

Hey, I'm trying to create a post processing effect, in which I mix the previous and the current frame. This kind of effect is called feedback loop in Touchdesigner and I would describe it as a kind of visual reverb. Here is the initialization and rendering method of my postprocessing class :

init() {

        const previousFrameTexture = new Texture(this.gl, {
            width: this.canvas.width,
            height: this.canvas.height
        });

        this.postFeedback = new Post(this.gl);
        this.feedbackPass = this.postFeedback.addPass({
            fragment: feedbackF,
            uniforms: {
                uResolution: { value: [this.canvas.width, this.canvas.height] },
                tPreviousFrame: { value: previousFrameTexture },
                // uFeedbackAmount: { value: 0.99 },
            },
        });

        this.previousFrameTex = previousFrameTexture;
}

onResize() {
        this.postFeedback.resize();
}

render() {

        //draw to texture
        this.feedbackPass.enabled = false;
        this.postFeedback.targetOnly = true;
        this.postFeedback.render({ scene: this.scene, camera: this.camera, update: false, target: this.feedbackPass.uniforms.tPreviousFrame });

        //draw to canvas 
        this.feedbackPass.enabled = true;
        this.postFeedback.targetOnly = false;
        this.postFeedback.render({ scene: this.scene, camera: this.camera });
}
Hugofgx9 commented 2 years ago

Here is a solution I found

render() {

    //render current scene
    this.postEmpty.targetOnly = true;
    this.postEmpty.render({ scene: this.scene, camera: this.camera });

    //merge current scene and previous frame + render it on target
    this.postFeedback.targetOnly = true;
    this.feedbackPass.enabled = true;
    this.postFeedback.render({ texture: this.postEmpty.uniform.value });

    //pass texture
    this.feedbackPass.uniforms.tPreviousFrame.value = this.postFeedback.uniform.value;

    //finally render on canvas
    this.postEmpty.targetOnly = false;
    this.postEmpty.render({ texture: this.postFeedback.uniform.value})
}