Skip to content

Feature:: Add FBO support + Grid-Displacement-Mouse effect demo #74

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

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

Robpayot
Copy link
Contributor

@Robpayot Robpayot commented Mar 1, 2025

  1. Adding FBO effects support
  2. Adding a demo section 14 with the new grid Displacement Mouse effect.

FBOs

To have a FBO effect you need at least one program running in parallel of the "Kampos effect". I preferred to manage the FBO data in a separate object called fbo.

Example when creating a Kampos effect that needs a FBO map:

    // init kampos
  const  instance = new Kampos({
        target,
        effects: [gridMouseDisplacement],
        fbo: {
            size: 256, // FBO texture size width and height
            effects: [flowmapGrid],
        },
    });

Your fbo effect can be different, In the example I made one for a flowMap grid effect in src/fbo/flowmap-grid.js . But we could add another one for a more simple flowmap effect in src/fbo/flowmap.js and do something like this example

Notes: For now this should be only used for flowmap I think, other FBO like GPGPU effects can be more complex and needs more textures: Example here (tutorial) where it's using a velocityMap to move particles

Modifcation in core.js

If using a FBO when creating a Kampos() instance. the core.js js will create a FBO program _initFBOProgram(gl, plane, fbo) in a object that gather all important information: fboData .
Then if fboData exists, the draw function will call drawFBO where all the FBO drawing logic exists. Notice that they are other thing to take care of if fboData exists like binding textures that I couldn't put in drawFBO for order reason.

Notes: For the grid effect I had to use a gl.FLOAT type texture, so I created a function for that. But I think in the future we might want a default Texture in a FBO effect. In that case we could add a parameters say textureType and use default or float texture based on that.

Demo

The demo is using grid-mouse-displacement.js effect with different parameters. Some of them like aspectRatio needs to be updated both in the effect and the fboEffect programs.

grid-effect.mp4

@@ -117,10 +117,13 @@ const SHADER_ERROR_TYPES = {
* @param {boolean} [config.noSource]
* @return {{gl: WebGLRenderingContext, data: kamposSceneData, [dimensions]: {width: number, height: number}}}
*/
export function init({ gl, plane, effects, dimensions, noSource }) {
export function init({ gl, plane, effects, dimensions, noSource, fbo }) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Interesting, my initial thought was to allow a programs property to allow providing multiple programs instead of effects. Do you this that would make sense? Or just be an overkill?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see what you mean but the fbo programs needs to be rendered in a specific order to draw / clear framebuffers and textures, and then "classic" effects can be drawn. So I think if we put all the logics in the same effets array, it might be difficult/overkilled to sorts them or do the checks on these rather than a separated object right?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not same effects array. I meant you could specify something like programs: { effects, plane }[]. But I can do this generalization later.


if (vao) {
extensions.vao.bindVertexArrayOES(vao);
if (fboData) _enableVertexAttributes(gl, attributes);
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we're using VAO here why do we need to reenable attributes here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For some reason I need to enable the positions here otherwise the program is invisible (only with FBO program rendered before). It might be because after clearing the framebuffer it needs to enable the other program's attributes?

But let me know if you find a solution to make it work only using the vao.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, cool, don't get stuck on it, I'll try investigating later

src/core.js Outdated
// bind fbo texture
gl.activeTexture(startTex);
gl.bindTexture(gl.TEXTURE_2D, fboData.oldInfo.tex);
gl.uniform1i(gl.getUniformLocation(program, 'u_flowMap'), 0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is very specific to the FlowMap effect. Either we use some generic uniform name here, or we extract this logic to be some how connected to the effect using the FBO?
I think I rather have the former

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, like I said here, I think for now the FBO is moslty meant to be for flowMaps. BUT I agree to make it more generic. I replaced it by u_FBOMap

Notes: For now this should be only used for flowmap I think, other FBO like GPGPU effects can be more complex and needs more textures: Example here (tutorial) where it's using a velocityMap to move particles

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, let's start with that

src/core.js Outdated

// // Set uniforms
_setUniforms(gl, uniforms);
gl.uniform1i(gl.getUniformLocation(program, 'u_flowMap'), 0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again, specific to FlowMap

src/core.js Outdated
@@ -766,6 +825,74 @@ function _getTextureWrap(key) {
return TEXTURE_WRAP[key] || TEXTURE_WRAP['stretch'];
}

function createFloatTexture(gl, data, width, height) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not API, internal:

Suggested change
function createFloatTexture(gl, data, width, height) {
function _createFloatTexture(gl, data, width, height) {

Comment on lines +848 to +849
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you use NEAREST because of the need to make the hard cut for the grid effect specifically?
Perhaps this should (at least later if not now) should be configurable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it was for that. I think like we discussed on Google Chat, in the future, it would be nice to make the FBO texture configurable in parameters like (textureType = FLOAT, textureCut = 'LINEAR' or 'NEAREST') ...

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, np

src/core.js Outdated
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess this is the coords for clip space? Could we use same ones used for the main program? I mean not the buffer/array itself, but perhaps the same config?

Copy link
Contributor Author

@Robpayot Robpayot Mar 5, 2025

Choose a reason for hiding this comment

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

Updated so now it's similar to the default attributes like for other effects

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