I want to have a particular geometry that I am rendering manually to always render behind everything else (including skyboxes). I thought rendering the geometry first (using the code below) and disabling depth testing+writing would do the trick, but that results in the geometry being rendered in front. What should I do?
Rendering it first would work… but I don’t think you are not rendering it first. I think material.render() is just queuing it up. It’s also super weird to call it directly.
If you can explain what you are actually trying to to do then it might help frame an answer better. (Because it already sounds weird to render something behind the skyboxes… as you might as well not render it all then.)
The geometry is a billboarded quad that covers the whole screen, and is the output for deferred shading.
I’m having trouble explaining this abstractly, so here is an example:
This scene consists of a hovertank model (opaque bucket), a sphere (transparent bucket), and a skybox (sky bucket). The GBuffer and deferred shading passes render the opaque bucket to a quad stretching over the entire screen. Then other passes render the sky bucket, then the transparent bucket.
My problem is that only the tank is visible, because the deferred shading quad is rendered over everything else in the scene. Here is the same scene, but the deferred shading quad is discarded (the background is green):
Basically, there is a hovertank-shaped hole in the scene, due to the depth texture, with the background peeking through it. If the deferred quad were instead rendered behind everything, the tank would be completely visible through that hole.
(Unless I’m entirely mistaken, this is the way Johnkkk’s deferred rendering works. And I’m working with his code, so…)
I’m making that particular render call as part of the viewport rendering process (RenderManager#renderViewPort) during the deferred shading pass. It’s the same way Johnkkk was doing it, and I’m more or less copying his logic to a cleaner API.
Note: My pass objects in the code are called “modules” so they won’t be confused with Johnkkk’s passes. I plan to rename them after cleaning things up.
Assuming you have the depth texture from the gbuffer pass bound and not cleared, disable depth write and set depth testing to the reversed function. GreaterEqual i think it is.
Render the quad at depth 1 using RenderManager.renderGeomerty()
Everything is now visible, but for deferred objects only the emissions are displayed, for some odd reason. The tank still is drawn in front of everything else, regardless of actual depth.
Here is the DeferredShadingModule where this render occurs:
For reference, here is DeferredShadingPass (written by Johnkkk), which works:
If the tank is never rendered behind the the sphere then it must be one of the following:
a) depth has been cleared before the transparent pass
b) depth map has been altered by the lighting pass
c) depth map is not bound
d) forced renderstates have been used and not cleared up
I don’t know how much of the framegraph stuff is tested. afaik it all was a work in progress and “will be fixed later”.
Beside that i think if you want to implement a new technique you do your self not a favor by using a verbose/complex experimental lib as base.
At least the support on that features is going to be zero.
I wrote a simple filter to display the depth texture. It shows the depth texture to be in order, and not outside the 0 to 1 range, so I believe that eliminates A, B, and C. (I had set the alpha of the deferred lighting quad to 0.01 to do that, because that quad was being rendered over the post-processing quad). I guess that leaves issue D, which I haven’t tackled yet.
What really bugs me is the lengths we’re going to to make this work, when Johnkkk’s implementation didn’t do anything all that special. It would be really nice to know why his works and ours doesn’t.
I discovered that the issue with only the emissive sections showing up was due to rendering via RenderManager#renderGeometry. When I reverted to using the material’s render method, the problem “went away.” Though, that seriously makes me question the robustness of the deferred lighting shader.
I agree, which is why I wrote my own framegraph API from the bottom up instead of using Johnkkk’s. I’m still using his logic and shaders, but at this point, I’m this close to rewriting those, too. Also, I’m not adding anything brand new right now beyond what features Johnkkk already had working.
Purly from looking at the code snippets you posted it seems the shader needs the lightlist supplied. So i guess this is not for rendering back the result but for applying the light calculcations. Dont know what kind of data/location requirements the shader has.
The light list is supplied by the GBufferModule through the framegraph using a sort of “parameter connection system.” Every frame before execution the deferred lighting pass pulls the necessary resources, including the light list, from this system. I know it’s working correctly because the tank is being lit (I mean, now that I fixed a different bug).
In the screenshot the tank does not seem to be lit. If it works with material.render and does not work with rendermanager.render it would hint to the lights, but in the last 15? years of jme dev i never needed to call material.render myself so it smells fishy. (without any reason)
I agree, it doesn’t seem proper to directly use the material to render, but I don’t think it is that important right now. I’ve tested with both methods and neither have any impact on the main issue (that objects are drawn in the wrong depth order). For now, I’ve split RenderManager#renderGeometry into two methods, so that I can use the light list from the GBuffer pass for rendering but still render properly via the render manager.
I recently had an issue that was very difficult to debug without Renderdoc. It was a little tricky to figure out how to properly launch the JVM for use with it, but I found that by launching the jME application with the following Gradle config and attaching to the running application with Renderdoc worked beautifully: