GameTechDev/MaskedOcclusionCulling

Orthographic projection?

ingramb opened this issue · 11 comments

Any suggestion for using this to cull a view using orthographic projection (directional shadow for example)? Ortho projection isn't compatible with z = 1/w transform used by library (w is always 1 for ortho). Is there any trick to make this work?

Hi Ingramb,

Unfortunately there's no support for orthographic projection at the moment, but it sounds like it might be a useful feature. Could you tell us a bit more about the use case, will you be doing culling only using the library? The z-buffer generated by the library is approximate, so it may not be directly useful for shadowmapping.

I think you can work around this by doing your own transformations. Instead of submitting a matrix to RenderTriangles(), use the TransformVertices() utility function to transform your vertices to clip space. Once in clip space you can multiply the x/y components of each vertex by its w component. That should cancel out the projection, but keep the depth values intact, so the depth test still works.

Regards,
Jon

I was hoping to integrate this library for culling both primary and shadow views. I've had some success using it to cull the main camera already. I'm not planning on using the software depth buffer as a shadowmap directly (although now that I type that, it's an interesting idea), but just want to reduce draw calls and vertex overhead for my regular GPU shadowmap pass.

Once in clip space you can multiply the x/y components of each vertex by its w component

Don't quite understand this. Once in clip space, w will be 1 for every vertex, if using orthographic projection. I tried multiplying xyw by z component...this way z value transferred to w (so the library will use it). This didn't seem to work...I think multiplying xy by z before interpolation doesn't correctly cancel out the projection, which occurs with interpolated values. Not completely sure on this though.

It seems like maybe a second mode that used Z directly, and avoided W would be a useful library feature for orthographic views. Obviously that's more work to add.

Yeah, that was poor wording on my part. I meant multiplying the xyw components by the z-value just as you suggested (or copy the z-value to the w channel unless you are certain w = 1). I think it should work as far as the projection goes (i.e. the triangles should cover the expected pixels on screen), but it does change depth interpolation. If you instead multiply the xyw components by 1/z that might solve any interpolation issues you have. The library internally interpolates 1/w linearly, so if you multiply w by 1/z it would interpolate 1/(1/z) = z, which would be expected for orthographic projection I believe.

It would probably be best to comply with GL/DX conventions, and use w for projection and z for depth interpolation. I don't think it would affect the rasterizer part of the library significantly. Main caveat is that it requires fetching 4 values per vertex (at least when specifying vertices in clip-space), or some extra transform operations. This is usually fine, but vertex processing can be a pretty significant portion of the execution time for highly tessellated meshes.

I've played around with this a bit more, and multiplying by (1/z) as you suggest seems to do the trick. A dedicated orthographic mode could potentially fetch Z directly and skip fetching W, as well as skip dividing XY by W, so that could be just as efficient. I'm not sure if that's really necessary though, as this trick seems to work fine, without any real overhead.

I'll let you know if I find any problems with this, but for now I think this may work. Thanks for your help.

Awesome, glad you got it working. I might look into adding real ortho projection support at some point. Unfortunately I'm not working in this project anymore. I'd have to do it on my spare time, so that makes me a bit hesitant to promise anything :).

Hi Ingramb,

Feel free to drop me an email at Leigh.Davies@intel.com we can discuss the best way to move forward with this and if it make sense to add this as an official part of the lib.

Regards,
Leigh

It appears I'm running into the same issue as originally mentioned by @ingramb. I want to use the library for occlusion culling shadow rendering which is using an orthographic projection.

Using the trick described by @Hasselgren - multiplying the x, y and w components with 1/z - works fine for regular cases, but is giving me weird results when triangles clip the near plane. I'm not sure why this happens, but it looks like the triangles 'flip'. My guess is that that this occurs because my w becomes negative, and we do the clipping 'before' we apply the perspective correction on x and y? I've attached a screenshot of how it looks using the ComputePixelDepthBuffer debug info, before and after the triangle clips the near plane. (Mesh is just a test quad consisting of 2 triangles).
before_after_ortho_near_plane_clip

I've quickly tried adapting the source by adding a template parameter BinTriangles<ORTHO>, which calls a custom ProjectVertices<ORTHO> that does more or less what @ingramb suggested: skipping the XY division by W. (I'm already passing in per-transformed vertices with w == viewspace z, so no need to fetch Z instead of W). The result looks correct in that case.
using ortho

So now to the actual questions I have:

  1. Am I misunderstanding something, or does the 1/z trick not work for orthographic clipping?
  2. Is there still any plan or possibility to get orthographic projections as an official feature, or would there be interest in me creating a very basic pull request with what I have?)

Note that a solution for this problem can be found in the orthographic branch:
https://github.com/GameTechDev/MaskedOcclusionCulling/tree/Ortho

Sorry for the late reply (1 year later!) but I am also in the same situation. I grabbed the Ortho branch, but I don't think it's working correctly for me.
Also, I guess TestRect would still expect ndc values?

Many thanks.

Hi @plekakis!
If I recall correctly I did manage to get this working. I'm not sure if I had to do anything special - it's been a year after all. Make sure to call the SetOrtho function. I would assume TestRect behaves the exact same indeed.

Could you elaborate about the issues you're seeing?