jmonkeyengine icon indicating copy to clipboard operation
jmonkeyengine copied to clipboard

provide access to glscissors

Open stephengold opened this issue 4 years ago • 12 comments

Requested at the Forum/Hub: https://hub.jmonkeyengine.org/t/next-release-of-the-engine/44988/9

PR #267 provides a possible starting point.

stephengold avatar Oct 24 '21 01:10 stephengold

Proposed (re-)implementation inspired by Retzinsky's PR 267:

  • new cloneable/serializable math class IntRectangle defines a rectangle in 2-D (similar to com.jme3.font.Rectangle, but with integer coordinates)
  • add an IntRectangle field, with getter/setter, to each Geometry (in window coordinates, using null to disable clipping)
  • add void clip(IntRectangle) to the Renderer interface
  • add state to GLRenderer to track whether the GL_SCISSOR_TEST enumerator is enabled and also the current glScissor() box
  • in Material.render(), invoke r.clip() with the geometry's clip rectangle

stephengold avatar Nov 10 '21 19:11 stephengold

The weird thing about clipping is that a spatial can be in any number of viewports. When I tried to mess with this before, that was the ultimate sticking point. The nifty JME interface already has some backdoor access to clip(rect) stuff and unfortunately it did not easily translate to the general "spatial can be in multiple viewports" case.

pspeed42 avatar Nov 10 '21 20:11 pspeed42

The only real usecase that comes into my mind is creating some texture atlas. (Shared shadwos maps ...) Even for the "Gui" usecase using clipping breaks if any rotations are allowed. I fail to see the point where a per geometry clip rect is usefull at all.

zzuegg avatar Nov 10 '21 20:11 zzuegg

Yes, a Spatial can be rendered in multiple viewports. Is that a detail that needs to be addressed in this PR?

I fail to see the point where a per geometry clip rect is useful

A likely use case would be to render labels in a GUI.

stephengold avatar Nov 11 '21 06:11 stephengold

The most likely use case would be for things like scroll panels, etc.... but that would require this on the spatial level.

I looked at this some time back ready to dive in and got stumped by how ugly things got when considering multiple viewports. I started implementing a map(Viewport, Clip) of clipping areas per spatial but it gets nasty fast.

For just a single geometry, for the limited use cases that require it, it's better to just build the facility into the shader. Way simpler and all the same viewport problems/limitations without dirtying up scene graph code with what amounts to a partial solution.

pspeed42 avatar Nov 11 '21 07:11 pspeed42

Retzinsky's PR 267 implemented Node.enableClipping() by recursively applying it down the scene graph to the geometries. I cut that from my design to simplify, thinking it's something apps can easily do on their own using a scene-graph visitor. If node-level clipping were implemented in a sophisticated way, with local clips at each level and caching of the effective global clip, would that enable more use cases?

I'm not worrying about multiple viewports. Many applications have only a single viewport per geometry, and as you said, it gets nasty fast.

stephengold avatar Nov 11 '21 19:11 stephengold

  • add void clip(IntRectangle) to the Renderer interface
  • add state to GLRenderer to track whether the GL_SCISSOR_TEST enumerator is enabled and also the current glScissor() box

It turns out none of this is necessary, since Renderer already has setClipRect() and clearClipRect() methods and GLRenderer implements it (using float and boolean instead of a rectangle object).

So is there also a mechanism to specify a clip rectangle for a Material? I'm not seeing it.

stephengold avatar Nov 12 '21 01:11 stephengold

Note: that at the Geometry level, clipping is nearly useless and can already be done by 1-2 lines in a material. That's also why I was not really a fan of the previous PR... it was only a partial solution and didn't really solve any real-world problems that weren't already solvable by a Viewport.

That's why simply pushing the traversal onto the application isn't really a solution, either.

The most common use-case I know of, and the reason I invested some large number of hours looking into this already, is the idea of a scroll panel in a UI. In that case, you want everything under a node to be clipped by some area... but to be better than a Viewport you will also want some change in how things are sorted, too. Else two separate sibling nodes with overlapping clip regions may behave unintentionally. The down side of using Viewports is that we cannot control the order at all through JME's API.

In a pure scene graph implementation that does not make JME's optimizations of compiling a geometry list, this sort of clipping is relatively trivial as things are rendered as the scene graph is traversed. This scene graph approach is undesirable for a lot (lot lot) of reasons but often when thinking about environmental effects like clipping, it comes up.

When I looked into this before, not only was the geometry-level style approach not useful but it was completely vestigial/superfluous in the presence of better solutions. That being said, "perfect is the enemy of good" and just because I can't imagine a use-case for and cannot see a reason that I would ever in a million years use a feature, doesn't mean that we shouldn't have it.

As to the existing clipping support and whether Material allows it, keep in mind that clip rect back doors exist for the NiftyJmeDisplay stuff. So you might find that code is the only caller of the methods you've discovered.

...but if one were thinking of putting clipping on the Geometry then putting it on the Material seems equally as cromulent.

pspeed42 avatar Nov 12 '21 02:11 pspeed42

can already be done by 1-2 lines in a material

How would one add clipping to a Material in the current Engine?

stephengold avatar Nov 12 '21 05:11 stephengold

When I forked my own font shader to better support BM font features, it was a vec4 I passed that would discard every fragment outside that range. And I still only used it one place. (In the modern engine, we could even use material parameter overrides on a whole tree that way... I could not at the time.)

pspeed42 avatar Nov 12 '21 07:11 pspeed42

The down side of using Viewports is that we cannot control the order at all through JME's API.

I had an idea: perhaps the Picture class could be used to implement scroll panels. Then the Z-coordinates of the pictures would control overlapping, and no new scene-graph features would be needed.

you might find that code is the only caller of the methods you've discovered.

With that hint, I found where setClipRect() is used in jme3-niftygui.

stephengold avatar Nov 12 '21 23:11 stephengold

Given that there's a way to implement clipping in materials, and no plausible use case for dynamic scene-graph clipping, I've decided to defer this project indefinitely.

stephengold avatar Nov 19 '21 08:11 stephengold