Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FilterRenderer2D for a 2d-Build #7409

Merged
merged 18 commits into from
Dec 17, 2024

Conversation

perminder-17
Copy link
Contributor

@perminder-17 perminder-17 commented Dec 5, 2024

This PR makes a separate class which will handle filter() function in 2D mode using mini WEBGL renderer.
We can use this for future when we try to make a 2D-build for p5.js.

@perminder-17 perminder-17 changed the title 2dFilterRenderer still a work in progress PR, needs to do some todo t… FilterRenderer2D for a 2d-Build Dec 5, 2024
@perminder-17 perminder-17 changed the title FilterRenderer2D for a 2d-Build [WIP]: FilterRenderer2D for a 2d-Build Dec 5, 2024
@perminder-17 perminder-17 marked this pull request as ready for review December 7, 2024 13:45
@perminder-17
Copy link
Contributor Author

This PR is ready for review. It's working as expected. @davepagurek, any thoughts or suggestions on the code structure?

Many tests are still failing and will look into it very soon and also needs some code cleanups and proper testing. Thanks

// Identity matrices for projection/model-view (unsure)

// TODO: FIX IT
const identityMatrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are dealing with 2D models here, do you think making the matrices identity works well? I tested them and results look good to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense!

Copy link
Contributor

@davepagurek davepagurek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good so far! I haven't looked into the tests just yet, but I left some initial thoughts on some things we might need.

src/image/filterRenderer2D.js Outdated Show resolved Hide resolved
this.filterRenderer = new FilterRenderer2D(this, operation, value);
}

this.filterRenderer.applyFilter();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a different filter is rendered (e.g. a blur then a threshold) I think we'll need to update the addressee used here. Might need to add an update method, and maybe also cache the shaders by their type instead of just having one cached

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I guess if a custom filter shader is passed in, we don't need to cache that, since the user holds on to the shader instance themself in that case

@perminder-17
Copy link
Contributor Author

perminder-17 commented Dec 8, 2024

If a different filter is rendered (e.g. a blur then a threshold) I think we'll need to update the addressee used here.

Thanks for catching that. I have fixed that now, do you think that looks good to you.

And I guess if a custom filter shader is passed in, we don't need to cache that, since the user holds on to the shader instance themself in that case

Okay, I thought custom filterShaders will be only used for webgl graphics and not in a 2d canvas. Added a logic for users using custom filter shaders as well. Do you think that looks good? Currently I need to test the whole filter but do you think that looks good to you or have any other suggestions for improving code quality? @davepagurek

* Initializes the shader program if it hasn't been already.
*/
_initializeShader() {
if (this._shader) return; // Already initialized
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like once we set this._shader, it will never update. I think that will cause this scenario to apply the first filter twice instead of doing each one once:

function draw() {
  filter(BLUR)
  filter(THRESHOLD)
}

I think maybe we should structure this in a way where we have this.filterShaderSources (storing the fragment shaders) and this.filterShaders (storing the initialized p5.Shader, if it exists). So in _initializeShader, we could just return the custom shader if a custom shader has been provided, and if not, return the stored this.filterShaders[this.operation] if it already exists, and if not, initialize a shader and store it in this.filterShaders.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be instead of having separate filter renderers per shader as you have it right now. The browser has a pretty low limit for the number of active WebGL contexts it can maintain (it's something like 6, and lower on phones), so we'd want to have just one filter renderer per 2D context, and have it have multiple shaders.

@davepagurek
Copy link
Contributor

Hm actually we might need to do a bit of refactoring here when we initialize custom filter shaders now that we won't have a filter graphics layer:

shader.ensureCompiledOnContext(this._renderer.getFilterGraphicsLayer());

Maybe what we do is always pass in this, and then in the p5.Shader.ensureCompiledOnContext implementation, we do something like context._renderer._filterRenderer || context._renderer to grab the 2D filter renderer if it exists.

this._renderer = context._renderer;

@@ -66,6 +67,9 @@ class Renderer2D extends Renderer {
}
this.scale(this._pixelDensity, this._pixelDensity);

if(!this.filterRenderer){
this.filterRenderer = new FilterRenderer2D(this);
Copy link
Contributor Author

@perminder-17 perminder-17 Dec 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw @davepagurek, my custom filterShader works for 2d mode now but I need to add my filterRenderer here as well and in pixel.js as well

      if (!this.filterRenderer) {
        this.filterRenderer = new FilterRenderer2D(this);
        this._renderer.filterRenderer = this.filterRenderer;
      }

any idea why this works only when I have initialized filterRenderer in both the places and by removing any of them, it stops to work?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this represents different things in both cases: in this file, it's a p5.Renderer2D, but in the pixels.js file, it's aninstance of p5. In that file, to access the one on the renderer, I think you need to check for this._renderer.filterRenderer.

@perminder-17
Copy link
Contributor Author

btw @davepagurek , the tests is passing for all 2d modes I think, the test which is currently failing is when we apply rectMode(), blendMode() or imageMode() in webgl modes. I think they are also failing in the actual dev-2.0 branch because I haven't changed the code for the webgl filter which uses the actual renderer.

Here's the result.

2D mode without blendMode

Screenshot from 2024-12-13 03-05-49

2D mode with blendMode (working correctly)

Screenshot from 2024-12-13 03-05-42

WEBGL mode without blendMode

Screenshot from 2024-12-13 03-05-22

WEBGL mode with blendMode (not correct)

Screenshot from 2024-12-13 03-04-49

Let me know if you have any thoughts, I think this is the main reason of the failing tests. What you think?

@perminder-17 perminder-17 changed the title [WIP]: FilterRenderer2D for a 2d-Build FilterRenderer2D for a 2d-Build Dec 12, 2024
Copy link
Contributor

@davepagurek davepagurek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, this looks great! Agreed, it looks like the failing WebGL filter tests probably weren't caused by these changes, so I think this PR is good to go!

@perminder-17
Copy link
Contributor Author

Screenshot from 2024-12-15 16-52-18

I think the issue is fixed now, but still tests doesn't passes for now :"). Also, resolved some merge conflicts, do you think that looks good to you @davepagurek

@davepagurek
Copy link
Contributor

turns out what was missing was a thing to handle default parameters (e.g. filter(BLUR) and not filter(BLUR, 3)), so I factored the code in the WebGL module that does that into its own file where both can reference it.

I also cached the p5.Texture we create so we can keep reusing it, and added a visual test that I was using for debugging. I think we're good to go now! Thanks for your work on this @perminder-17, I'm happy to see how minimal you managed to get this class to be 🙂

@davepagurek davepagurek merged commit 2e8cdaf into processing:dev-2.0 Dec 17, 2024
2 checks passed
@perminder-17 perminder-17 deleted the 2d-build-filter branch December 17, 2024 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants