[solved] DirectX 11: rendering obj-mesh

Started by
10 comments, last by DEADC0DE 12 years, 8 months ago
Hello,

I dispair of rendering an obj-quad-mesh with DirectX 11. My meshloader seems correct, because the wireframe mode is shown properly.

I found out that obj-meshes are oriented counterclockwise, but DirectX normally is clockwise.
So I set the rasterizer "FrontCounterClockwise" to true and outputtopology of my Hullshader to "triangle_ccw".

The big confusion comes with the constant Hullshader and Domainshader. I tired to make a sketch of one quad (because all my meshes are quad-meshes)

[source lang="cpp"]
// patch[3]
// +--------- e1 ---------+ patch[2]
// | in1 in1 |
// | | | |
// UV.y e0 ---+--in0-----+---- e2
// | | | |
// | | | |
// +--------- e3 ---------+ patch[1]
// patch[0]
// UV.x

// e = edge, in0 = inside[0], in1 = inside[1], UV = SV_DomainLocation of Domainshader

HS_CONSTANT_Out ConstantHS(InputPatch<VS_Out, INPUT_PATCH_SIZE> patch, uint PatchID : SV_PrimitiveID){
HS_CONSTANT_Out output;

output.Edges[0] = 2; //left edge
output.Edges[1] = 3; //upper edge
output.Edges[2] = 2; //right edge
output.Edges[3] = 3; //lower edge
output.Inside[0] = 3; //horizontal
output.Inside[1] = 2; //vertical

return output;
}
[/source]

So, first why is DirectX so weird: is there an explanation for the edges being clockwise? Did I forget to set some value?

Furthermore my mesh isn't drawn correctly. I can see through it and some patches are culled although they are in front of everything. (see attachment)
Looks like the depthbuffer is not cleared, but my render-function is doing "ClearDepthStencilView"

I'm trying to fix that issue since a week or so but I only get even more strange results.

Does someone has a clue or can give me an advice what I could do to find the error?

Thank you very much!


[EDIT: pictures deleted, better ones see below]
[EDIT 2: (just information) not only the edges are clockwise, everything in the shaders is clockwise! Even with FrontCounterClockwise set!]
Advertisement
Any suggests?
What do you mean DirectX is weird? The output topology is specified with the function attribute 'outputtopology', like so:

// Setting for clockwise winding
[outputtopology("triangle_cw")]


Without seeing your code for the whole pipeline it is hard to say why you are seeing through your mesh, but it sounds like you are calculating a custom tessellation factor for each quad, is that right? If so, then you need to ensure that the tessellation factors applied to the two edges neighboring one another are precisely the same, otherwise you can get gaps between the two sets of output tessellations.

Also, if you are seeing rendering issues, then it would be good to check the application with PIX. Then you can see what state the depth buffer is in before and after the draw call. It might also be beneficial to render the model with the reference device too, just to make sure you aren't dealing with a driver bug.

EDIT: After looking at your images again, it seems clear that the second image is a reverse vertex winding issue - you are culling only the front faces in that image...
Thank you for your answer. ;)

Well, the whole pipeline isn't so small that it can be posted.

Topic outputtopology: I set the outputtopology to triangle_ccw, but the edges are still clockwise.
I find that a bit strange. Is there a reason for that? (another option to set?)

I'll try out PIX... That sounds like it's a good point to continue. Thanks.

Can reverse vertex winding occur even if the wireframe is shown/culled correctly? (cause wireframe's ok)

Thank you for your answer. ;)

Well, the whole pipeline isn't so small that it can be posted.

Topic outputtopology: I set the outputtopology to triangle_ccw, but the edges are still clockwise.
I find that a bit strange. Is there a reason for that? (another option to set?)

I'll try out PIX... That sounds like it's a good point to continue. Thanks.

Can reverse vertex winding occur even if the wireframe is shown/culled correctly? (cause wireframe's ok)


Can you post a screen shot of the wireframe version, and then the same image with the filled version? It can be tricky to tell if the culling is working properly just by a wireframe mesh - maybe it just looks like it is being rendered correctly.

About the pipeline information, if you take a frame capture with PIX, then you will be able to compare your pipeline state right before the draw call with what you are expecting it to be. That way, you can rule out any silly mistakes like setting the wrong winding or anything like that.

Have you also checked the CullMode parameter of the D3D11_RASTERIZER_STATE? If you have that set to cull back faces or cull front faces, then you could have some incorrect results too...
Wireframe coming.... :)

The advice with PIX helped me out! I found a something.
I bound a custom (extra) rendertarget/depthstencil to the shader-pipeline. If I don't do that (and use "DXUT-standard"), everything looks good.
So the shaders should be right (same shaders in both pipelines). If I switch to "new" pipeline and back to standard-pipeline (while program is running), the "mesh" is broken again!

What I'm doing:
1) create Texture2D for rendertarget/depthstencil with rendertargetview and depthstencilview

2) render:
- clearrendertargetview/cleardepthstencilview
- set shaders, rasterizerstate, inputlayout, constantbuffers
- set vertexbuffer, indexbuffer
- set primitivetopology (quads => 4_control_point_patchlist)
- OMSetRendertarget (with rendertargetview and depthstencilview)
- drawindexed
- reset everything that was set above

Did I forgot something?

Rasterizer:
[source lang="cpp"]
//solid
D3D11_RASTERIZER_DESC RasterDesc;
ZeroMemory(&RasterDesc, sizeof(D3D11_RASTERIZER_DESC));
RasterDesc.FillMode = D3D11_FILL_SOLID;
RasterDesc.CullMode = D3D11_CULL_BACK;
RasterDesc.FrontCounterClockwise = TRUE; //counterclockwise!
RasterDesc.DepthClipEnable = TRUE;
V_RETURN(pd3dDevice->CreateRasterizerState(&RasterDesc, &_g_pRasterizerStateSolid));

//wireframe
RasterDesc.FillMode = D3D11_FILL_WIREFRAME;
V_RETURN(pd3dDevice->CreateRasterizerState(&RasterDesc, &_g_pRasterizerStateWireframe))
[/source]
In Hullshader outputtopology is triangle_ccw, mesh ist loaded from obj (counterclockwise) with indexbuffer (=> drawIndexed)


[EDIT: I added a depthstencilstate and switched the depth-test off => "mesh"-bug was mirrored: the missing corner in face of bigguy is then on the left side! I don't understand this...]
Do you get any error messages when you try to render? If it works ok with the existing set of render targets, and not when you use your created ones, then it sounds to me like the depth buffer doesn't match the render target. You have to ensure that the size, type (i.e. texture array or not), and multisample count all match.
[EDIT: sorry, that was a wrong idea... deleted]
Wohoo! I got it! It's the viewport!

If I comment the viewport out, everything is shown right (in both pipelines!). At least it seems to be right.
(except that the mesh is too small and in the upper-left corner, because of "old" viewport)

Thanks very much Jason Z ;)
In case someone has the same problem. Here's the solution:

[source lang="cpp"]
D3D11_VIEWPORT old;
UINT viewport_nr = 1;
pd3dImmediateContext->RSGetViewports(&viewport_nr, &old);

D3D11_VIEWPORT vp;
ZeroMemory(&vp, sizeof(D3D11_VIEWPORT));
vp.Height = static_cast<FLOAT>(Height);
vp.Width = static_cast<FLOAT>(Width);
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.MinDepth = 0; //attention: DO set this value (standard is 0)
vp.MaxDepth = 1; //attention: DO set this value (standard is 1)
pd3dImmediateContext->RSSetViewports(1, &vp);

//render (set up shaders..., DrawIndexed, reset shaders...)

//reset viewport (in my case because of supersampling => so that hud stays the same)
pd3dImmediateContext->RSSetViewports(viewport_nr, &old);
[/source]

This topic is closed to new replies.

Advertisement