Question

I want to be able to access the polygon id (PrimitiveID) of the the front facing polygons of a mesh. I can only see this happening after the rasterizer stage, in the pixel shader.

I was thinking about creating an append buffer but since the pixel shader is executed multiple times it might append the same polygon id more than once.

I also thought about creating an array boolean variables and using the primitive id from the input assembler stage in the pixel shader as an index and set it to true, but then I will have to set all of them to false first which can't be done with an UAV buffer, unless I'm missing something there.

can anybody give me some possible solutions.

EDIT #1: I am implementing a "Show Face Normals" feature for a 3D Model viewer. I want to only be able to see the face normal of the drawn faces when in wire-frame mode.

EDIT #2 (possible solution): Right now I am trying to implement this with either cuda or opencl. I figured I don't really need sv_primitiveId if I just perform the dot product against the primitive inside the viewing frustrum. This was suggested on the answer by Drop.

Was it helpful?

Solution

"There's more than one way to skin a cat" ;)

Disclaimer: I never tried any of this, and not even sure if it works or even implementable. Just ideas, food for thought.

BTW, I'm still curious why would you need this ;)

  1. Probably, you can emulate back-face culling yourself, before real hardware clipping

    • Run your vertex and tessellation shaders as usual
    • Transform and walk through your triangles in geometry shader (or in vertex shader, with tricks)
    • Calculate dot product between camera's view direction and triangle's plane normal
    • If (dot > 0): append triangle to output, if (dot < 0): do not append (cull)
    • You can read stream output data if you need it on CPU side
    • You can somehow add SV_PrimitiveID to output if you need to know which primitives exactly was passed and which was clipped
    • Then you can proceed with rendering in second pass. Your geometry already transformed, so no need for pre-rasterization stages.
    • If your target hardware supports multiple streams (Shader Model 5.0), you can output one stream to buffer (to read on CPU) and rasterize second one. So all stuff dove in single pass.
  2. With your approach of output id from pixel shader:

    • If you access output buffer on CPU side, you can sort it, iterate through it, remove or just ignore duplicates. std::vector + <algorithm> will do the trick.
    • If you want to continue on GPU, you can do some sort of same thing in shader (pixel or compute), but this can be inefficient
    • I think, you can use integer textures instead of structured buffers, if you want compatibility with Shader Model 4.
    • More than one primitive can map to single pixel. So, you will not get indices of invisible primitives, those whose pixels was rejected on depth test (if primitive is completely overlapped with another). Depending on your needs this can be significant. Probably, you can disable depth testing and figure out how to write different
  3. With bool array approach, you, probably, cannot use AppendStructuredBuffer, but if you know primitive count before rendering, you can use StructuredBuffer, initialize it with zeros and simply write to it instead of appending.

  4. And of course, any time you can do it purely on CPU side. But that's not so funny.

  5. Added due to comment. Wow, when you said "drawing something on each polygon face", a SolidWireframe sample from Nvidia DirectX 10 SDK instantly popped up in my mind. It is an ideal usage for geometry shader. Basically:

    • in GS you can provide each vertex with texcoords, depending on which face it belongs to
    • hardware back-face culling will happen during rasterization
    • in PS you sample your face texture with those texcoords
    • as alternative, you can probably do texcoords in vertex shader. You could trick with instancing and SV_VertexID, SV_InstanceID: each first vertex id, each second vertex id, each third vertex id. It will cause branching, but will work even on SM 3.0 hardware, hopefully.
    • corner case : you can precalculate alternative texcoord set for vertices offline. Hope, some 3D editors, such as 3dsMax supports it. So, no need to mess on runtime at all.

Hope it helps. Please leave comment if it will =)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top