NVlabs / nvdiffrast

Nvdiffrast - Modular Primitives for High-Performance Differentiable Rendering
Other
1.35k stars 144 forks source link

backface culling #9

Closed Speido closed 3 years ago

Speido commented 3 years ago

First of all, thank you for this library, it's really fast, scales very well and brings differentiable rendering to a usable level for me.

Nvdiffrast seems to render double sided. Is there any way to disable this behaviour?

s-laine commented 3 years ago

Hi Speido. Enabling backface culling in the rendering step can be done by adding a glEnable(GL_CULL_FACE); somewhere towards the end of rasterizeInitGLContext() in nvdiffrast/common/rasterize.cpp. By default, OpenGL considers counter-clockwise winding to indicate a front face. If needed, this can be changed to clockwise faces with glFrontFace(GL_CW);. The Khronos page on Face Culling has the details.

However, if enabling backface culling changes the result of the rasterization, there is a danger that the antialiasing operation won't work properly. Currently, the silhouette edges are detected by checking if both connecting triangles are on the same side of the edge after projection. Also, edges that connect to just one triangle are considered silhouettes. Backface culling can introduce additional silhouettes by removing arbitrary triangles from the image, but the current antialiasing operation will not detect this. Hence, the silhouettes that appear only because of backface culling will not be antialiased and consequently they won't obtain coverage gradients.

It would be possible to extend the antialiasing operation with a mode that makes its definition of silhouettes match back-face culled rendering, but this would be a slightly more involved modification. With closed meshes, backface culling shouldn't change the picture, and in these cases the current silhouette detection method works equally well.

Speido commented 3 years ago

I enabled backface culling using your advice and it does work with the caveats you mentioned. For my purpose it's fine. Thank you!

yifita commented 1 year ago

Hi, is there an example to set this through nvdiffrast.torch?

s-laine commented 1 year ago

Backface culling is not a supported feature, so there is no option to turn it on in the API. You will need to edit the code of the plugin to do that.

ShenhanQian commented 1 year ago

Thanks for suggesting glEnable(GL_CULL_FACE);! This also works for my purpose.

When working with the CUDA backend, I came across the following code snippet. https://github.com/NVlabs/nvdiffrast/blob/c5caf7bdb8a2448acc491a9faa47753972edd380/nvdiffrast/common/cudaraster/impl/TriangleSetup.inl#L56-L57

It effectively performs backface culling, but is not executed due to the following line: https://github.com/NVlabs/nvdiffrast/blob/c5caf7bdb8a2448acc491a9faa47753972edd380/nvdiffrast/torch/torch_rasterize.cpp#L96

Changing it to the following enables backface culling:

cr->setRenderModeFlags(enablePeel ? CR::CudaRaster::RenderModeFlag_EnableDepthPeeling : CR::CudaRaster::RenderModeFlag_EnableBackfaceCulling); // enable backface culling.