Aedoro
Aedoro

Reputation: 898

Multisampling, how to read back "unique" texels

I am looking at how i am going to implement antialiasing in a deferred lighting renderer. So three passes, a geometry pass, a lighting accumulation pass, and then a 2nd geometry pass for shading.

With normal multisampling, MSAA, the goal is to only multisample pixels on polygon edges. And for each triangle only write the result of the fragment shader to the subpixels which it covers. But ofcourse it is a known problem that this is a little problematic with deferred lighting.

The goal is to avoid evaluating all the subpixels in the 2nd and 3th pass, since that would basically be supersampling. If anybody knows another (better/possible) way of achieving that, I would very much like to hear it. But here is my idea:

If you can make the fragment shader in the first pass only write to the first subpixel the triangle covers. It allowes you to ignore unwritten texels in the lighting pass. And then finally in the 2nd geometry pass, somehow read the back only the first subpixel that the triangle matches, which is the one we wrote to originally and then did lighting for (and now write to all of the covered texels as normal so the result can be resolved). This way only the "unique" texels will be evaluated in the 2nd and 3th pass.

Can somebody say how this can be done in glsl (or confirm it is not possible)? I do not really see a reason why this would theoretically not be possible, but also do not see any way to do it in glsl.

Upvotes: 0

Views: 361

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 474126

For a moment, I'm going to ignore the goal of your question and instead focus on the specific request:

  1. Can you write to the "first" sample only from a fragment shader?

Yes. What you have to do is have your fragment shader declare an input integer array using the decoration SampleMask (or, in GLSL parlance, use gl_SampleMaskIn, an array of signed integers). You would then iterate through this array bit-by-bit, to find the first bit that is set.

This bit is the "first sample". So you then declare an output integer array using the decoration SampleMask (in GLSL parlance, gl_SampleMask, an array of signed integers). You set the "first sample" bit to 1 and all others to zero.

  1. Can you know what the "first sample" that was written is for a particular pixel in a multisample image?

Not unless you write that data to some other piece of memory, like an SSBO or something. The multisample image does not know which samples have been written to, so it has no way to know which is first.

And even if you could:


Your whole idea will not work.

Multisampling is just supersampling based on a single simplifying assumption. Namely, that it is OK to give all of the samples generated by a triangle the same per-fragment values (except for depth). In all other respects, it is just supersampling: adding more samples per-pixel.

If two triangles overlap, then your "first sample" approach is meaningless. Why? Because there are two "first samples": the first sample from triangle 1 and the first sample from triangle 2. And triangle 2 may have overwritten the "first sample" from triangle 1.

Even if there was no overwriting of a first sample, you still don't know how many samples each triangle contributed. If one triangle contributed the right 50% of the pixel's samples, and an overlapping triangle contributed the bottom 50% of the pixel's samples, then you should only get 25% of the first triangle's contribution. How do you know to do that with your method?

Upvotes: 1

Related Questions