-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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: Add WEBGL_clip_cull_distance
support.
#27371
Conversation
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
I'm new to When I understand the extension correctly, it allows clipping in the vertex shader which means it is an alternative to Do you mind explaining why
Even if this works would you mind not doing this 😇 ? Setting the read-only |
It's an array to handle more complex culling I believe, for example multiple culling shapes or handling a view frustum culling directly in the vertex shader. For example: // Define frustum planes in clip space
// Near and far planes
gl_ClipDistance[0] = gl_Position.z + 1.0; // near plane z = -1
gl_ClipDistance[1] = -gl_Position.z + 10.0; // far plane z = 10
// Left and right planes
gl_ClipDistance[2] = gl_Position.x + 5.0; // left plane x = -5
gl_ClipDistance[3] = -gl_Position.x + 5.0; // right plane x = 5
// Bottom and top planes
gl_ClipDistance[4] = gl_Position.y + 5.0; // bottom plane y = -5
gl_ClipDistance[5] = -gl_Position.y + 5.0; // top plane y = 5 Also there is |
Each vertex may have up to 8 clip distance values; they are interpolated across primitives as regular varyings. During primitive rasterization, pixels that have negative clip distance values are discarded. This should be more efficient than using For example, here's how you can turn a unit quad into an octagon using only a vertex shader: void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
gl_ClipDistance[0] = dot(gl_Position, vec4( 1, 0, 0, 0.5));
gl_ClipDistance[1] = dot(gl_Position, vec4(-1, 0, 0, 0.5));
gl_ClipDistance[2] = dot(gl_Position, vec4( 0, 1, 0, 0.5));
gl_ClipDistance[3] = dot(gl_Position, vec4( 0, -1, 0, 0.5));
gl_ClipDistance[4] = dot(gl_Position, vec4( 1, 1, 0, 0.70710678));
gl_ClipDistance[5] = dot(gl_Position, vec4( 1, -1, 0, 0.70710678));
gl_ClipDistance[6] = dot(gl_Position, vec4(-1, 1, 0, 0.70710678));
gl_ClipDistance[7] = dot(gl_Position, vec4(-1, -1, 0, 0.70710678));
} |
Drawing points without specifying |
Updated with the feedbacks. FYI since I'm using a builtin material I attached a custom object material = new THREE.MeshNormalMaterial();
material.extensions = {
clipCullDistance: true,
}; Are you ok with this logic or do you have anything better in mind @Mugen87? For example we could move the |
For now, let's make an example based on |
Style clean up.
@RenaudRohlinger I've updated the example to ensure formatting matches all other examples 👍 . |
Beyond potential performance benefits of performing plane clipping with this extension vs using discard in the fragment shader is that it seems to enable a hardware anti-aliased edge on the clipped edges: #22172 implements AA on edges using alpha to coverage but this solution would be better, I think. I'd say this should be used to implement Material.clipPlanes but I don't know if supporting |
Updated the material with |
@gkjohnson FYI |
Since clipping distances are set per-vertex, each primitive gets its own clipping half-space. For instance, this could be used to make it look like clipping happens against a "sphere". |
@lexaknyazev I wonder how we could integrate the extension in the material system so it can be used without writing custom shader code. Do you think it is sufficient if an engine provides the possibility to set clipping distances on material level like with clipping planes? How common is it to define additional vertex data attributes (next to vertex normals, colors etc.) to configure clipping distances per vertex? |
It could be used for HW acceleration of regular clipping planes, not explicitly exposed to users at all. Anything beyond that would likely require a custom shader.
Never saw such usage. Clip distances are supposed to be dynamically computed akin to |
That is something we could try to tackle after this PR is merged. |
Simplify example.
@RenaudRohlinger I've simplified the example so the focus lies more on the extension handling. It is not that visually appealing like your original draft but maintenance aspect and simplicity is more important right now. |
Awesome! LGTM, thanks @Mugen87 |
WEBGL_clip_cull_distance
support
WEBGL_clip_cull_distance
supportWEBGL_clip_cull_distance
support.
* init WEBGL_clip_cull_distance support * remove unecessary conditions webgl2 * try fix directx * feedbacks * remove unecessary code * Update webgl_clipculldistance.html Style clean up. * Update WebGLExtensions.js * Update webgl_clipculldistance.html * replace material with shader * remove unused time const * Update webgl_clipculldistance.html Simplify example. * Update clipping example. * Revert builds. * ShaderMaterial: Update `extensions` and docs. --------- Co-authored-by: Michael Herzog <[email protected]>
WEBGL_clip_cull_distance is now supported by default on the latest version of Chrome and Safari.
This PR adds support for the new
WEBGL_clip_cull_distance
extension. Made an example to demonstrate how to use the extension. Added the build for testing purpose. Will remove it once it's approved.Here the live demo. Also in this example I'm tricking the renderer by enabling
isPoints = true
on the mesh and not specifying thegl_PointSize
in the shader which seems to produce a cool bug, I think it looks cool so I would like to let it like that:https://raw.githack.com/mrdoob/three.js/dev/examples/webgl2_clipculldistance.html