jMonkeyEngine / jmonkeyengine

A complete 3-D game development suite written in Java.
http://jmonkeyengine.org
BSD 3-Clause "New" or "Revised" License
3.8k stars 1.12k forks source link

provide access to glscissors #1628

Open stephengold opened 2 years ago

stephengold commented 2 years ago

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 commented 2 years ago

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

pspeed42 commented 2 years ago

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.

zzuegg commented 2 years ago

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.

stephengold commented 2 years ago

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.

pspeed42 commented 2 years ago

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.

stephengold commented 2 years ago

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 commented 2 years ago
  • 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.

pspeed42 commented 2 years ago

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.

stephengold commented 2 years ago

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

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

pspeed42 commented 2 years ago

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.)

stephengold commented 2 years ago

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 commented 2 years ago

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.