🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Deffered Rendering - Light volume optimizations

Started by
2 comments, last by Lewa 3 years, 6 months ago

So, i'm in the process of porting some of my deferred rendering code from OpenGL to a new Vulkan backend and stumbled upon an issue with regards to light volumes for the lighting pass. (Specifically point lights in this case.)

One of techniques of optimizing overdraw in rendering light volumes is to utilize the stencil buffer where you render the light volume (sphere in case of point lights) with a stencil pass (to check where the light volume intersects with the geometry) and then render it again with a regular render pass to apply lighting. (The optimization is that only the fragments with the positive stencil test are affected which reduces overdraw.)

This technique i'm speaking of is show in this tutorial: http://ogldev.atspace.co.uk/www/tutorial37/tutorial37.html
​Now, the issue is that i can't really find an easy/efficient way of porting this to vulkan without requiring two pipeline changes for each light with vkCmdBindPipeline (one for the stencil-, one for the lighting pass).

The only real solutions I was able to find are:

  1. Don't use the stencil test and render light volumes with the lighting pass only (doesn't require renderpass/pipeline changes in the command buffer but creates unnessecary overdraw)
  2. Simply render each point light with two seperate renderpasses as said before (alternating between stencil>light>stencil>light, etc…) which would avoid the overdraw but goes against vulkans best practices/optimization possibilities (and incurs performance hits due to renderpass/pipeline changes).
  3. Use VkPipelineDynamicStateCreateInfo with extensions such as VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT which would add the nessecary state change commands to fully implement the technique without having seperate renderpasses (but it's not in the vulkan standard thus i'm worried about driver support)
  4. Scratch this technique and implement tiled based deferred lighting?

Another possible solution that i thought of is to simply remove the stencil test, render all point lights in a single renderpass but pass the depth buffer of the scene to the lighting shader to do a range check if the distance between the lights origin and the current fragments position (which can be reconstructed from the depth buffer) is ≤ the light radius. (If true then proceed with the computation else call discard; ) Though this is likely bad practice. (Haven't measured performance yet.)

From the information that i've been able to gather online it seems that number 4. is the technique which meshes the best with vulkans core principles. But it requires compute shaders for the tiling calculation of lights.
(It probably would be the best idea to implement that but as of right now i don't have support for compute shaders in my vulkan backend. Implementing that would cost additional development time especially as i've never touched computes shaders before.)
So having a semi performant solution without resorting to implementing tiled-based rendering would be acceptable to me (for now).


So has anyone any reccomendations/additional input with regards to this problem? I wasn't able to find a lot of ressources with regards to deferred rendering/lighting on a vulkan based backend online.

/edit: Typo in the title :/

Advertisement

I'd look into tile based light culling, which has been around for a while and is generally considered today's best practice. Well, today it's extended by adding depth bins as well, making screen aligned voxels or “froxels” as it's called, and is generally used for optimizing any number of things such as per tile shader lists and volumetric fog.

But tiled light culling is the place to start, especially if you're re-writing a backend entirely anyway. Here's a nice overview: https://wickedengine.net/2018/01/10/optimizing-tile-based-light-culling/

Will look into this technique. But it also seems to be based on compute shaders.

Seems that i've to simply deal with overdraw for the time being and look into implementing compute shader support to hopefully move towards a tile-based approach in the near future for the most optimal results.

This topic is closed to new replies.

Advertisement