I'm implementing kind of 3D Model tools using DirectX 11 and I need to paint the collision area between 2 meshes with Pixel-level accuracy.
So I think I should do something in pixel shader but I don't have enough experience with shader programming.
here is my approximate solution and I'm not sure if it will work or not and whether it's effective or not.
first model is passed to the shader through inputlayout.
second model is passed to the shader through structuredbuffer.
when pixel shader draw first model, calculate collision algorithm in pixel shader
if it is true paint it red.
UAV is not required because there is no output from shader. it is used in pixel shader only.
is there any other good way? this solution have to check with all triangles in second model at every pixel.
I know there is the compute shader, but I've never use it before. if it is necessary, I will take this opportunity to study.
I think you should implement a screen-space approach. Here’s an approximate workflow.
When creating your render target, create extra depth buffer of the same size as your render target, with the same or similar format (e.g. if your depth is
DXGI_FORMAT_D32_FLOAT_S8X24_UINT, you don’t need stencil, you only needDXGI_FORMAT_D32_FLOAT). Create two views of that buffer,ID3D11DepthStencilViewto write, andID3D11ShaderResourceViewto read.Before drawing model A, render a depth-only pass of your model B into that separate depth buffer. Don’t forget to clear the view first. Use the same vertex/geometry shaders you’d normally use. You don’t need any pixel shaders (pass
nullptrintoPSSetShader), and be sure to unbind any render targets, you only need the depth-stencil bound on output. Once done that, revert to your main render target view and the main depth-stencil view.Now, when rendering model A, modify your pixel shader, should be something like this:
If you use MSAA, you'll need to replace
Texture2DwithTexture2DMSthere and adjust the shader accordingly.D3D11_COMPARISON_LESSdepth comparison, clear the second of them with 0 and render withD3D11_COMPARISON_GREATERdepth comparison. Also don’t forgetD3D11_CULL_FRONTwhen rendering into the second one. Once done, you’ll get 2 depth textures, together they tell you the range of depths of model B at each pixel. Then, when rendering model A’s triangles, read both depths and only paint red if the current pixel’s depth is within that interval. That’s not perfect still, gonna fails in some edge cases when your model B is a concave polyhedron, but performance-wise it’s very efficient. GPUs are asynchronous, the two depth-only passes of model B don’t have dependencies and will run in parallel. In general, GPUs are very fast at rasterizing triangles, as long as the shaders aren’t too complicated.Update: Also, it’s possible to compute both min and max depth textures with a single render pass. Setup two render targets, backed by textures of type
DXGI_FORMAT_R32_FLOAT. Initialize with ClearRenderTargetView() to 1.0 and 0.0. Setup a blend state for that pass that usesD3D11_BLEND_OP_MINfor the first RT andD3D11_BLEND_OP_MAXfor the second one. Write a pixel shader that outputs Z component of SV_Position into both render targets. Don’t use depth buffer, render your model B into these two RTs, both front faces and back faces i.e.D3D11_CULL_NONE. Might be slightly faster because this way vertices are only transformed once.