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

WebGLRenderer: option to enable multi_draw / gl_DrawID in vertex shader #27630

Merged
merged 6 commits into from
Jan 29, 2024

Conversation

vegarringdal
Copy link
Contributor

@vegarringdal vegarringdal commented Jan 27, 2024

Related issue: #XXXX

Description

Was trying to make a modified Batchedmesh, but I could not not use gl_DrawID in shader.

now it should be possible to enable it like this:

const material = new MeshStandardMaterial({
  color: 0x00ff00
});
material.extensions = { multiDraw: true };
material.onBeforeCompile = (shader) => {
  // magic 🪄 
});
 

See here for more information:

https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_multi_draw

Note: Although the extension name is named WEBGL_multi_draw, the extension must be enabled with the #extension GL_ANGLE_multi_draw directive to use the extension in a shader.

When this extension is enabled, the gl_DrawID built-in can be used in shader code. For any multi* draw call variant, the index of the draw i may be read by the vertex shader as gl_DrawID. For non-multi* calls, the value of gl_DrawID is 0.

<script type="x-shader/x-vertex">
  #extension GL_ANGLE_multi_draw : require
  void main() {
    gl_Position = vec4(gl_DrawID, 0, 0, 1);
  }
</script>
Copy link

github-actions bot commented Jan 27, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
673.5 kB (167.2 kB) 673.6 kB (167.3 kB) +163 B

🌳 Bundle size after tree-shaking

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

Filesize dev Filesize PR Diff
454.2 kB (110.1 kB) 454.4 kB (110.2 kB) +163 B
@gkjohnson
Copy link
Collaborator

gkjohnson commented Jan 28, 2024

Because objects are rearranged for object sorting and filtered for frustum culling the gl_DrawId isn't a useful field and not consistent between render. Users should use the batchId attribute if you want the object index in the shader.

@vegarringdal
Copy link
Contributor Author

Because objects are rearranged for object sorting and filtered for frustum culling the gl_DrawId isn't a useful field and not consistent between render. Users should use the batchId attribute if you want the object index in the shader.

How I understand it the gl_DrawId is upped+1 for each offsets/starts in the multiDrawElementsInstancedWEBGL
If you use a attribute to hold the id, it will need to be a lot bigger and match index, so basically position length/3.

Unless Ive missed something the size of the texture will be a lot smaller in most cases wont it ?
If you have batched 100 drawcalls on large meshes the texture still just need to be size 100 * element size of number you have.

In this presentation I found on khronos.org they also say on page 14

gl_DrawID is considered ‘uniformly varying’, so
texture lookups will be cached across a given draw.

Dunno if this is helpful compared to buffer attribute, I really do not know enough about this stuff.

@vegarringdal vegarringdal changed the title feat: option to enable multi_draw / gl_DrawID in vertex shader Jan 28, 2024
@gkjohnson
Copy link
Collaborator

How I understand it the gl_DrawId is upped+1 for each offsets/starts in the multiDrawElementsInstancedWEBGL
If you use a attribute to hold the id, it will need to be a lot bigger and match index, so basically position length/3.

Unless Ive missed something the size of the texture will be a lot smaller in most cases wont it ?

This is the case but you wind up using another one of your limited texture slots. I don't think it's worth changing BatchedMesh until it can be shown this is causing issues.

It does occur to me that a separate texture like this, though, can be used to render multiple of the same geometry in a single BatchedMesh without having to duplicate the data in the vertex buffers. So effectively we could cover instanced meshes and batched rendering all with a single object and draw call. An API with this in mind would need to be designed, though, which doesn't sound straight forward.

I suppose we can add this extension for experimentation, then. @Mugen87 is there anything else we need to change for adding support for the extension? I'm less familiar with what needs to be done.

@Mugen87 Mugen87 added this to the r161 milestone Jan 29, 2024
@gkjohnson gkjohnson merged commit 6daf300 into mrdoob:dev Jan 29, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants