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

Clip geometry using plane and hiding part behind it #8462

Closed
2 of 12 tasks
manrajgrover opened this issue Mar 24, 2016 · 9 comments
Closed
2 of 12 tasks

Clip geometry using plane and hiding part behind it #8462

manrajgrover opened this issue Mar 24, 2016 · 9 comments

Comments

@manrajgrover
Copy link

Description of the problem

Consider a situation where I have a scene with various geometries and a clipping plane(not near and far plane) is needed to cut it leaving only front portion and removing everything behind it. This is something far clipping plane in camera does but I want to do it in small portion. This JS fiddle will explain it better. How to achieve this using ThreeJS? If not possible, any workaround?

https://jsfiddle.net/cxrctpk7/

Three.js version
  • Dev
  • r75
  • Version 49.0.2623.87 (64-bit)
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • Linux
  • Android
  • IOS
@manrajgrover manrajgrover changed the title Clip geometry using plane and hiding hiding part behind it Clip geometry using plane and hiding part behind it Mar 24, 2016
@erichlof
Copy link
Contributor

@manrajgrover

Do you mean like this?
https://jsfiddle.net/o0cwuzmp/

Please post your question on SO.
If you link to your SO post, I will be glad to explain what I did in detail - we can discuss further on SO.

@manrajgrover
Copy link
Author

@erichlof I believe what you did is you created a box of same color as background and attached it near the cube. This is something even I thought but is not an elegant solution nor good as I can have some other object near that camouflaged box.

This seriously does not look like an SO question to me and is more of a feature request. Please correct me if I'm wrong.

@erichlof
Copy link
Contributor

@manrajgrover Thanks for clarifying - yeah it's more of a quick hack. But if you need something truly robust, what you need is a stencil buffer mask. I hardly ever use the stencil buffer anymore, but some three.js experts on SO (like WestLangley) will most likely direct you toward the relevant algorithms or three.js examples. So yes, this would be technically a SO question because three.js already has the functionality you are looking for, via stencil buffer operations.

@tschw
Copy link
Contributor

tschw commented Mar 24, 2016

@manrajgrover

This seriously does not look like an SO question to me and is more of a feature request. Please correct me if I'm wrong.

Yes, you are actually right. There used to be glClipPlane in the fixed-function versions of desktop GL, but I doubt that anyone wants to implement it in Three.js. So whether your ticket gets closed labeled "Help (please use SO)" or "Feature Request" probably won't make much of a difference, I guess :-).

@erichlof

But if you need something truly robust, what you need is a stencil buffer mask.

An alternative, single-pass approach (when using your own shaders) is

if ( dot( pos, plane.xyz ) < plane.w ) discard;

in the fragment shader, where plane is a homogeneous plane and pos is the surface position given in the same coordinate system.

@erichlof
Copy link
Contributor

@tschw
Thank you for that alternate approach - I wouldn't have thought of that! So the glClipPlane used to actually clip the vertexes/geometry? Would the single-pass approach that you posted perform like the old glClipPlane, but at the fragment level? If so, it might be a worthwhile addition to three.js for masking purposes. I guess you could only use it with PhongMaterial or StandardMaterial, and not BasicMaterial though.

@tschw
Copy link
Contributor

tschw commented Mar 24, 2016

@erichlof

So the glClipPlane used to actually clip the vertexes/geometry?

It's supposed to clip vertices and reconstruct the edges of partially clipped polygons (see Red Book, Chapter 3, "Additional Clipping Planes"), which is effectively fragment level but takes more thinking to implement and saves instructions in the fragment shader - or the extra hardware, talking fixed-function GPUs. I also found this post, so some implementations may have defects in this regard.

There is still API support for user-defined clipping in the non-ES versions of OpenGL: It happens during Vertex Post-Processing based on the built-in vertex shader outputs gl_ClipDistance.

Would the single-pass approach that you posted perform like the old glClipPlane, but at the fragment level?

Yes. Would have to check the spec whether <, >, <= or >= gives identical behavior, though.

If so, it might be a worthwhile addition to three.js for masking purposes. I guess you could only use it with PhongMaterial or StandardMaterial, and not BasicMaterial though.

Yes, certainly. It'd also be useful for stereoscopic rendering - that's how the post got my intention (see the figure in this post).

@erichlof
Copy link
Contributor

Oh wow, what a handy function that glClipPlane was! (barring the implementation discrepancies on Mac as you noted). Back in the late 90's I used the fixed-function pipeline and I somehow missed this function - thanks for the links!

Sorry for prolonging this closed issue, but does Three.js currently clip/reconstruct the polygons against the view planes (app dev's responsibility), or does WebGL / OpenGL ES do this under-the-hood for us?

If it's the former case, could we just specify a temporary arbitrary extra 'viewing' plane against which to clip geometry (or extra dummy camera with this extra plane?), thus giving the functionality that the OP desires? If it's the latter case, I suppose we would have to do it at the fragment level, which wouldn't be such a bad trade-off or limitation (not being able to use BasicMaterial, etc.). And as you mentioned it would help with stereoscopic rendering (although not my area of expertise in the slightest :) )

@tschw tschw mentioned this issue Mar 25, 2016
@tschw
Copy link
Contributor

tschw commented Mar 25, 2016

[ ... frustum clipping ... ] does WebGL / OpenGL ES do this under-the-hood for us?

Yes, based on what the vertex shader outputs.

Clipping in JavaScript would be terribly slow. Geometries are static data uploaded to the GPU on first use, then positioned in the scene by a matrix transforming the vertex positions. Animation means mixing different positions or one position transformed by different additional matrices. This is the typical "vertex shader stuff".

The JavaScript side traverses the scene graph, multiplies the projection matrix with the inverse world matrix of the camera with the world matrix of each object. It then does frustum culling; checking whether a geometry can be visible according to bounding geometry tests. The remaining geometries are sorted; opaque geometries first, front to back (to minimize overpainting), then transparent geometries back to front (so blending happens in the correct order) . Finally, it issues the GL command stream, that is the render calls for the objects preceded by setting program, buffers, and uniforms (input such as the matrices telling the GPU program how to position the object, or the lighting setup). When a new program source code, texture, or buffer is encountered in the process, it's (compiled and) uploaded to the GPU.

That's how it all works, the rest is just the devil in the details.

I suppose we would have to do it at the fragment level, which wouldn't be such a bad trade-off or limitation (not being able to use BasicMaterial, etc.)

OK, apparently there is interest in this feature and I have a use for it, so I implemented it in #8465. Please follow the review and convince @mrdoob to merge it :-).

And as you mentioned it would help with stereoscopic rendering (although not my area of expertise in the slightest :)

Well, there are probably several more - just the one on the top of my head right now.

@erichlof
Copy link
Contributor

@tschw Thanks so much for the clarification and WebGL pipeline details. I am checking out #8465 right now! Thank you for the implementation! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants