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

WebGLUniformsGroups: Support for array of Uniform Buffer Object #27293

Merged
merged 7 commits into from
Dec 4, 2023

Conversation

RenaudRohlinger
Copy link
Collaborator

@RenaudRohlinger RenaudRohlinger commented Dec 2, 2023

Description:
Support for array of Uniform Buffer Object and included a demo of 51 unique mesh sharing a light UBO consisting of 300 point lights.

The way I implemented is that you can blend arrays of UBOs and simple UBOs among the same Group:

glsl:

uniform LightingData {
  vec4 lightPosition[POINTLIGHTS_MAX];
  vec4 lightColor[POINTLIGHTS_MAX];
  float pointLightsCount;
};

js:

const ubo = new THREE.UniformsGroup();
ubo.setName( 'LightingData' );
ubo.add([new THREE.Uniform(),new THREE.Uniform(),new THREE.Uniform(),...]) // array of vec4 lightPosition
ubo.add([new THREE.Uniform(),new THREE.Uniform(),new THREE.Uniform(),...]) // array of vec4 lightColor
ubo.add(new THREE.Uniform()]) // float pointLightsCount

Important to know, if we add a size of array of uniform !== than the size specified in the shader it will break, which is pretty normal behavior IMO. Should we fill with empty clones or throw a warning somewhere if it's not the case?

Next it could be great to add support to struct format (doesn't break but driver issues), I added a TODO for another PR.
Also I believe there is not Integer support in the UBOs so far, added a TODO for this one so we don't forget.

Preview: https://raw.githack.com/renaudrohlinger/three.js/ubo-patch3/examples/webgl2_ubo_arrays.html
image

Copy link

github-actions bot commented Dec 2, 2023

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
668.9 kB (166.1 kB) 669.1 kB (166.1 kB) +121 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Filesize dev Filesize PR Diff
450 kB (109 kB) 450.1 kB (109 kB) +53 B
@@ -2091,6 +2091,8 @@ class WebGLRenderer {

const group = groups[ i ];

if ( group.uniforms.length === 0 ) continue;
Copy link
Collaborator

@Mugen87 Mugen87 Dec 4, 2023

Choose a reason for hiding this comment

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

I understand you have added this line to prevent a processing from a uniforms group without defined uniforms.

But is this a real use case? Why should a developer setup an instance of UniformsGroup like that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would say that's coming from a bad habits of always wanting to protect most use case even if I don't encounter the issues in my code. But I understand that's not something we would want in threejs as the shader will break if the developer forget to bind the UBO.
Anyway UBOs are something pretty advanced, as you mentioned in the other comment let's wait and see if developers complains.

For the moment I removed it 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also regarding UBOs errors are sometimes misleading.

For example if you forget to bind it in JS it will throw the error GL_INVALID_OPERATION: It is undefined behaviours to use a uniform buffer that is too small..

Maybe we can add another PR in the future just to help developers to make it easier to understand.

// TODO: Should we unbind in the renderer instead?
return;

}
Copy link
Collaborator

@Mugen87 Mugen87 Dec 4, 2023

Choose a reason for hiding this comment

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

I'm not sure we need this kind of validation. IMO, UniformsGroup should be used like geometries or textures. After the first render, devs should not alter the number of uniforms in their group. If this is required, they can call dispose() and create a new group.

Changing the layout of uniforms means the shader changes so a call of dispose() on the respective shader material is required as well.

Make example code more consistent to other demos.
@Mugen87
Copy link
Collaborator

Mugen87 commented Dec 4, 2023

Do you mind removing the build files from the PR?

It was a good idea to update the files so it's possible to preview the demo but for the merge it's better to remove them.

Side note: I have slightly updated webgl2_ubo_array via b630bfa to make its structure more similar to other demos.

@Mugen87
Copy link
Collaborator

Mugen87 commented Dec 4, 2023

The changes in WebGLUniformsGroups look good, btw!

@Mugen87 Mugen87 added this to the r160 milestone Dec 4, 2023
@Mugen87
Copy link
Collaborator

Mugen87 commented Dec 4, 2023

Important to know, if we add a size of array of uniform !== than the size specified in the shader it will break, which is pretty normal behavior IMO.

That sounds good to me! I would not add further validation checking until devs start requesting such a feature.

@RenaudRohlinger
Copy link
Collaborator Author

Should be good to go! Next I will try to add Integers and Struct support in two other PR.

@Mugen87 Mugen87 merged commit fa93997 into mrdoob:dev Dec 4, 2023
12 checks passed
AdaRoseCannon pushed a commit to AdaRoseCannon/three.js that referenced this pull request Jan 15, 2024
…ob#27293)

* ubo array support

* dpr to 1

* update ubo

* Update webgl2_ubo_arrays.html

Make example code more consistent to other demos.

* Update WebGLUniformsGroups.js

Clean up.

* feedbacks

* checkout build folder from dev

---------

Co-authored-by: Michael Herzog <michael.herzog@human-interactive.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants