vulkanstencil-buffer

Is it possible to clear stencil buffer within indirect draw call?


I want to implement stencil shadows, and not have to work with individual lights on CPU side (recording buffers that alternate pipelines for each light) - i want to do all the lights in one go. I see it being possible with compute shaders; however I don't have access to ROPs from them, and while using atomics should be possible, it doesn't feel right (transforming R32UINT image into B8G8R8A8UNORM or whatever vkGetPhysicalDeviceSurfaceFormatsKHR may output). Having to do software rasterisation of shadow volumes also feels wrong. Simply using stencil, and outputting 0 color when drawing shadow volumes, then do a quad of actual light is nice, however i don't see any way to clear it inbetween draws. I've also thought of using blending and alpha value, but the only way i could thought of requires special clamping behaviour: not clamp blending inputs, but clamp outputs. And as far as I'm aware, its not possible to read pixels from framebuffer being drawn to in the very same draw call.


Solution

  • To clear stencil buffer within a draw command is not possible; However I was able to achieve the desired result with special stencil state, late depth-stencil tests, discard and some extra work within shader, at a cost of doing those very things and flexibility.

    How it works in my case(depth fail shadows):

    1. For differentiating between passes, I use GL_ARB_shader_draw_parameters for gl_DrawID, but it should be possible through other means
    2. Shadow pass:
      1. In fragment shader, if depth is to be passed, discard // thus, no color writes from it are ever done
      2. In stencil state, front-face fail(both depth and stencil) -> increment; back-face fail -> decrement; // there volumes are counted
    3. Light pass:
      1. If the light triangle is back-facing, output zero; Stencil state, back-face pass -> replace with reference; // there stencil is cleared
      2. Else, calculate color; Stencil state, front-face pass -> doesn't matter.