Auxiliary framebuffers are immediately rendered to screen
AHilyard opened this issue · 5 comments
System Informatinon
- Minecraft Version: 1.17.1
- Canvas Version: 1.0.1932
- Operating System: Windows 10
- Graphics Card: nVidia GeForce GTX 1070
Other mods and versions installed
- fabric-api-0.37.2+1.17
- AdvancementPlaques-1.17.1-fabric-1.3.1
How you triggered the behavior
- Start Minecraft
- Log into any world
- Earn any advancement
What you expected would happen
- The advancement plaque icon would appear in the proper location. See https://www.curseforge.com/minecraft/mc-mods/advancement-plaques/screenshots for examples.
What actually happened
- The advancement plaque's icon appears in the lower left corner of the screen. This is my mod, and it uses an auxiliary frame buffer to render the advancement's icon offscreen in a frame buffer for blending. Canvas appears to be rendering the framebuffer to screen immediately once anything is rendered to it.
Logs and screenshots
- Log file: https://pastebin.com/1LKbuEVT
- Screenshot:
This code is a little invasive so I'm not sure how well it can be supported. Canvas has hooks in ItemRenderer and I don't know if this modified ItemRenderer will work with them or if it will matter.
That said, what I suspect is happening here is that Canvas is intercepting the draw calls and seeing a RenderLayer (has a different name in MojMap that I forget ATM) that it knows how to render, so it does. (If so, then Canvas' hooks are working in the modified ItemRenderer.)
Canvas thinks it knows how to render this RenderLayer because you aren't changing the target frame buffer in the RenderLayer but instead changing the FBO binding directly.
Building a custom render layer with a custom target would not work today, but I can add logic to Canvas to detect that and exclude that layer from its handling. (It currently checks for and excludes some other custom elements, but this is the first time I've seen a custom frame buffer target.)
Another option would be to draw directly to the frame buffer without using the normal rendering code. Or do this without a custom frame buffer. (Unclear to me why that is needed for this effect.)
How is this auxiliary framebuffer created and where/when is it bound? If it’s something separate you’ve created then Canvas would normally have no way to know about it.
For context, the framebuffer is created by an ItemRenderer subclass. The purpose is just to render items (for GUI) to a framebuffer, then draw that to screen, so it looks identical to end users but supports alpha values for rendered items. Here is the code where it happens: https://github.com/AHilyard/AdvancementPlaques/blob/1.17-fabric/src/main/java/com/anthonyhilyard/advancementplaques/CustomItemRenderer.java
The framebuffer is created in the constructor of the custom item renderer, and is bound for writing in the renderGuiItemWithAlpha method. The icon is rendered to screen on line 87 when it should be rendered to the iconFrameBuffer instead.
Thank you for the insight, that all makes sense. In my testing changing the target frame buffer in the RenderLayer (RenderType in moj mappings) caused blending issues when rendering 3D items, whereas this more invasive solution worked. That was with the Forge version of my mod though, and I don't know what if any differences there may be in Fabric.
I will look into drawing directly to the frame buffer as a workaround, thank you.