-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
Add support for stencil buffer #3373
Comments
This was already discussed in a proposal a while ago, and also in an issue: #1930, godotengine/godot#23721 The consensus is that built-in stencil shadows will not be added, but a stencil buffer may be exposed in a future 4.x release (not 4.0 due to time constraints). This stencil buffer can then be used in custom shaders to create stencil shadows and other effects.
The In the meantime, consider using blob shadows using a Sprite3D + RayCast setup (or in 4.0, a Decal node) 🙂 |
I'm not at all saying you're wrong since I know next to nothing here, but why would adding a feature already within gles be difficult? Doesn't godot simply convert a godot shader into a gles shader internally, wouldn't that be about as complicated as adding some string-altering code? |
It's not that adding the feature is difficult. We consider the current GLES renderers to be in maintenance mode, and we'd like to avoid introducing regressions in them. We also need to be 100% sure that any features added to them can be replicated in Vulkan, so that projects can be ported from Godot 3.x to Godot 4.x without too much effort. Implementing a stencil buffer in Godot is more than just adding some lines of shader code. A convenient API needs to be designed, in line with the Best practices for engine contributors #6. We also need to ensure that there's no performance cost when you don't make use of the feature in a project (in a way similar to godotengine/godot#38926).
I presume GLES2 doesn't mandate stencil support (or only in limited form), which makes things even more difficult. We don't want to add desktop-only features to the GLES rendering engines, as they are intended to work on mobile/web platforms as well. |
I plan to eventually have ports of Inochi2D to off the shelf engines like Godot, so bumping this since Inochi2D extensively uses the stencil buffer to handle constraining rendering of parts to other parts (eg. forcing the iris to stay within the sclera (eye whites) for eye rigging, forcing shadows to only overlap specific parts, etc.), shader based alternatives to stencil buffers would be considerably slower since they're used so often. |
I think a stencil buffer would be needed to allow shaders to place materials on top of faces behind them. For instance, billboarding 3D sprites explosions clip partially into walls if the player isn't looking directly at the wall it's been instanced at, and disabling depth test just makes the sprite appear on top of everything, including geometry in front of it. As far as I know, a stencil buffer is needed to write a shader that can perform a depth test and always keep the billboard sprite on top of faces behind it. |
You can enable proximity fade in SpatialMaterial to make it blend softly with solid surfaces. |
If it's an animated 3D sprite, there isn't any way to use spatial material, is there? Since it would have animation frames, I'm not sure how that could work. I tried adding a Material Override with an AnimatedTexture, but it didn't seem to work. |
A proposal in another repository regarding Outlines and Silhouettes, which probably requires stencil buffers alfredbaudisch/GodotShaderCollection#3 |
Yes, most outlines require stencil buffers. |
Another use-case for stencil buffers involves covering the holes in meshes created by cross-sectioning the geometry in shaders. If the stencil buffer were exposed, I would be able to project a textures like albedo and normal map atop where the backface is visible to the camera to create effects like a liquid surface. This is theoretically possible without a stencil buffer, but far more difficult. |
I managed to implement this fairly straightforward, at least for Forward+. See my related comment here: alfredbaudisch/GodotShaderCollection#3 (comment) Godot already has a working stencil buffer of course, and all it took was exposing the relevant I suppose the question is whether or not that's a good enough solution. It's easy to imagine scenarios where per-material settings aren't very convenient, such as portals. Additionally, it's not super beginner-friendly. I suppose the stencil buffer never is, but it'd be nice to have a simple |
We have been discussing this in a bit of detail on Rocketchat. So I would like to summarize some of the discussion and provide my input on this. Some general comments
My thoughts:
|
This would be insufficient for Inochi2D, but I've found a workaround based on writing my own renderer "from scratch" using RenderingDevice exposed in Godot 4. Does mean some platforms won't be supported but there's nothing I can do about that I think. |
I'm also interested in using the stencil buffer to pixelize single objects (make models look like pixel perfect 2d 8bit 32x32 sprites). Having this buildin or allowing this setup from the shader would be highly appreciated :) |
I think that while those 3 effects make up the majority of use cases the engine should still support custom usage of the stencil buffer as it makes several effects much easier to achieve. Speaking from my own perspective I'm currently investigating using the stencil buffer for an underwater effect so even just exposing bitwise operations on the stencil buffer would be incredibly useful. An example of this would be exposing the 8 bits of the stencil buffer we currently allocate as a texture and allowing materials to write to a particular bit of the stencil buffer when drawn. This would make most effects simple to implement given enough effort while allowing the most common effects to still be included by default by reserving the first few bits if the community decides that they want them. |
A little extra on the use cases, I don't know how i forgot them before. examples of this are
So it would be quite important to also be able to have geometry intersect with stencil surfaces (like n2) |
@LunaTheFoxgirl could you expand on your usecase? |
My usecase is in a 2D character rendering system that I develop. Stencil buffer is needed in a fixed function manner where I can before rendering a "part" set up masks by cutting in to and out of the stencil buffer. This allows the end user of my software to for example keep the iris of their character only rendering when it overlaps the sclera. Or create otherwise complex rendering masks. |
I see. I don't think it's possible to use the raw stencil function from the gpu for 2D object (as far as i know stencil is set only for the full mesh, and you can't use transparent textures with it?) but should be solved instead by the clipping of canvas items. That should already be available in Godot4 without using stencil buffer |
I feel like it's easy enough to implement these with basic stencil ops and depth functions. That said, an easy to use
For any stencil effects which do also write depth, it would be incorrect to draw depth for pixels which would later be stenciled out and not drawn. However, xray/outline effects do not usually draw depth, so this won't affect them.
First, as a user, I expect I do think that an additional sorting solution could be found, but I personally feel it's unnecessary. Maybe a good solution would be to have a system of named layers, arranged in the project settings, which automatically set the |
Canvas item clipping is not suitable for the needs of Inochi2D, as I need to be able to cut in to and out of the mask by re-rendering items that was previously rendered in to the stencil buffer; but as I said RenderingDevice does expose the needed features. My plan is to just add a Inochi2D puppet node type which internally renders to 3 textures which then can be used in conjunction with a mesh and material in godot. |
Thank you for your explanation @LunaTheFoxgirl ! |
anecdotally, +1 vote for exposing stencil buffer for full usage, instead of just being limited to: |
Since it'll be a bit before 4.x is open for features (4.1 release) can we put together a list of stencil operations we want andconsider minimal enough feature set? I think in order to make stencil more easy to use we could have preset configurations and leave a "custom" option that unfolds the whole option set? |
These have already been mentioned, but i'm hoping to be able to use stencil shadows for a project i'm working on (and silhouettes would also be nice), so +1 vote for those features. |
Spent some time looking at how Unreal and Unity do it so I can finally propose a workflow for this. This is a proposed 3D workflow. I have no idea how to use it with 2D. I wouldn't support 2D for now. Stencil is composed of three components: write, test and read. WriteStencil write as far as i understand is severly limited by the mesh: either you write the whole mesh to stencil, or you don't. So, on EDIT: updated with increase/decrease op A bit of info in that mockup:
TestTest configuration should be on the Once #7117 is implemented it will make more sense to see stencil as a property of the shader rather than a render_mode. I don't think we should support it in a render mode unless it's strictly necessary. It adds overhead to the shader compiler and i don't think it's necessary since this is a pipeline state (?) and not a shader program property (correct me if i'm wrong on this, i'm severly out of my turf here) As above, compare op and compare mask are mutually exclusive fields. ReadAdd a shader built-in called For visual shader I don't know yet what to expose, but i imagine the tricky part is bitmask comparison? To be defined how this is used, for the time being it can be an expression block. ConsiderationsThis is mostly inspired by Unreal's stencil because honestly I couldn't understand Unity's one, but I tried to add a little extra to what Unreal offered and to adapt it to Godot's structure. I don't know if there's any effect that is not doable with this setup, please let me know. |
@QbieShay: I'm also out of my turf here, but I'd really like to have stencil buffers for fake lighting like in wind waker. So to put in my two-penny worth… MinionsArt explained it here for Unity in greater detail than Simon's paper which the video is based on (might help you understanding Unity's way). The way I understand your proposal,
What I wonder about is at 5:14-5:45 you require an interaction with z testing. And afaik Godot can only do sth. similar using And no idea how to translate |
Achieve sth. similar using normal lights? Maybe… Speaking for our stylistic context, I don't know the limits of Godot's light projection to enforce a certain shape (octagon or sth.) and I'd need to test if I can output the pure diffuse texture rgb values unaffected of shadows if no light is hitting the object (cannot use unlit/unshaded if we use normal lights)…
Do you mean: "I'm checking if the value is 0, and if it is, increase/decrease by 1" ? I'm no shader wizard, sadly, but my programmer heart tells me Unity's Stencil operation values are a good way (also in combination with a different write operation based on whether stencil passed, failed or depth test failed). If I understand your proposal correctly, the write operation is only done if the depth condition AND stencil test are both I'll take a look at Unreal's approach tomorrow; they should have sth. similar… |
yes, that's the idea. Unreal's one is much simpler than Unity, exposes a lot less knobs. I'd prefer to sit somewhere in the middle with Godot, because Unity's one is really too hard to understand. unreal's one in comparison is veeeery simple but i fear also very limited. |
@clayjohn pointed out in chat that having it on the mesh itself is a bad idea since it would prevent using multiple draw passes with different stencil operations, de-facto invalidating the desired workflow of easy to do outlines. Stencil write should probably be moved on |
So, I took a short look at Unreal's approach and noticed that it goes wholly via post-processing. It's completely different to Unity's approach. So they can offload a lot of logic to the post-processing shader. Not sure what kinds of repercussions that has. From what I read and seen so far, the stencil buffer is for creative use of masking effects. Simplifying it more than what Unity does feels wrong to me… If most users just want the "x-ray" and "outline", they can use the G-Buffer (geometry buffer) according to this comment. If they still need the stencil buffer because the g-buffer is not enough, then for just those 2 use cases, writing tutorials sounds the best way to go. That's it from me for now, I don't want to ping everybody any more than necessary. |
No,the g buffers are not sufficient to do these effects. Also the PR you linked is not merged. As for the lights of wind waker, it's a really specific usecase. I have a feeling it should be possible to achieve it in some other way with a light shader 🤔 but regardless i believe that it should be achievable with what I proposed. |
I'd have to rewatch it again (or better, reading it :https://www.patreon.com/posts/wind-waker-style-78831006) to see if the required operations are covered. It really is not that easy to wrap your head around. But complex uses never are x) and then there's the question about the ztest and colormask... I'll try out a stencil PR to see if it's achievable once we have one.
And yes, read and write at the same moment is must
No,the g buffers are not sufficient to do these effects. Also the PR you linked is not merged
I referenced someone who should know better than I, so I cannot comment on g-buffer's usefulness... And the PR is readier than stencil support: Only vulkan version is missing
Am 21. Juni 2023 21:44:49 UTC schrieb QbieShay ***@***.***>:
…No,the g buffers are not sufficient to do these effects. Also the PR you linked is not merged.
As for the lights of wind waker, it's a really specific usecase. I have a feeling it should be possible to achieve it in some other way with a light shader 🤔 but regardless i believe that it should be achievable with what I proposed. `replace` is already possible with the options we're exposing. I think that stencil buffer should allow to read and write in the same moment. So you'd enable test, test against previous stencil, and enable write. that should achieve everything, i think? I had a hard time following the video x)
--
Reply to this email directly or view it on GitHub:
#3373 (comment)
You are receiving this because you are subscribed to this thread.
Message ID: ***@***.***>
|
Awe too bad, that's super disappointing to hear :( |
@jordo I understand the disappointment, but please understand this work is already complicated :D when I said "I wouldn't support 2D for now" doesn't mean "we'll never support 2D" but rather "I'm already overwhelmed trying to make sense of this in 3D that I don't have the bandwidth to deal with the 2D side" There's different considerations to be done there, namely there is no depth prepass in 2D so there isn't a proper place to write to stencil yet, which is just yet more stuff to think about. I want to approach this in a step by step manner. I hope that clears why i said "no 2D for now" ^^ |
Ok I see. I guess I kind of thought the stencil interface/api would at least be exposed by the rendering server/layer, (or whatever the equivalent is in 4.0 is now renderingdevice???), so that we can use it fully there. Which I thought may likely be simpler in 2D than in 3D. |
I am not sure how'd it work for 2D, but i personally specialize in 3D so I can't be of much help there. |
Closing in favor of #7174 |
Describe the project you are working on
I'm working on a game that visually I want to resemble old 2000's games. So I wanted to make shadow volumes with a shader and some gdscript, but I can't.
Describe the problem or limitation you are having in your project
Without a stencil buffer, I can't get it to work. I've got very close by using depth and/or alpha + multiple passes but there is always some kind of flaw that makes it unusable for the project.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
With a stencil buffer (...or a way to alter a previous pass), I'd be able to make it work.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I'm not sure how a stencil buffer works if I'm honest, I just know thats what I'd ideally need.
If this enhancement will not be used often, can it be worked around with a few lines of script?
No, I can't find a single way to do this with the tools godot provides.
Is there a reason why this should be core and not an add-on in the asset library?
I don't know if something like this COULD be added as an addon?
And I think simply having a stencil buffer seems like a reasonable thing to want as a core feature.
I know the plan is to add custom buffers or something in 4.0 but I'm making this as a request for at least a stencil buffer to be ported into 3.x. I'm one of the people who doesn't want to move to 4.0, this would be my one sole reason to do that and I don't think its worth the trouble.
The text was updated successfully, but these errors were encountered: