TriangleList incompletely drawn by DrawUserPrimitives

I’m encountering a problem drawing a procedurally generated TriangleList. The symptom is that at certain camera angles some of the triangles which should be drawn are not (or possibly are drawn over by triangles behind them). The missing triangles are drawn at other view angles however. A visual sample of the symptom is below:

Rotated slightly, the area in the top, right is now drawn correctly instead of the triangles behind being drawn on top, but toward the bottom left, the white sections drawn within the green area are really on the back side of this isohedron and the green facets on the camera’s side are either not drawn or drawn over by the triangles behind them.

The triangles list itself does not seem to be the problem, as OpenGL draws this same isohedron correctly at all rotations:

Likewise, I’ve simplified down to an octohedron and inspected the coordinates of each triangle to confirm they match between the MonoGame and OpenGL programs and the MonoGame still draws the figure not in the expected way in all rotations.

The drawing behavior is identical in MonoGame whether using DrawUserPrimitives or filling and drawing from the VertexBuffer.

I am new to MonoGame and it is likely that I am missing some important parameter related to draw order or culling. The relevant source code parts at Draw time:

    graphics.GraphicsDevice.Clear (Color.Black);
    effect.World = Matrix.CreateTranslation (0, 0, 0);;
    effect.View = camera.ViewMatrix;;
    effect.Projection = camera.ProjectionMatrix;
    effect.VertexColorEnabled = true;
    RasterizerState rasterizerState = new RasterizerState ();
    rasterizerState.CullMode = CullMode.None;
    GraphicsDevice.RasterizerState = rasterizerState;
    foreach (EffectPass pass in effect.CurrentTechnique.Passes) {
    	pass.Apply ();
    	GraphicsDevice.DrawUserPrimitives (PrimitiveType.TriangleList, vpcTestVertexPerformance, 0, intFacetCount);

Any suggestions for correcting this are greatly appreciated!

UPDATE: If the camera is far outside the X, Y, and Z range of the isohedron the problem goes away. In the examples above, the camera is well outside the figure itself, but closer to the X-axis than the outer range of the figure. Is this a limitation of the MonoGame graphics engine or an oversight in my coding?

You have the following line here which sets the cull mode to none after setting a empty new rasterizerstate.

You maybe setting the RasterizerState up wrong in combination with the DepthStencilState if your intention is to not see thru the front of the sphere.

rasterizerState.CullMode = CullMode.None;

The above will draw both the front and back facing triangles of the sphere unless you have the depth buffer on. SpriteBatch begin can turn that off if you have turned it on which i don’t see in this block of code. With the depth buffer off farther pixels drawn behind and after closer pixels will be seen.

In general you want the entire spheres triangles to have the same winding then simply turn on either clockwise or counter clockwise culling. If you draw another object or objects behind it afterwards, then you still want to ensure the depth buffer is on. If the triangles in a object you are drawing are not wound properly or you are just testing then no cull is fine, but its going to do double the work drawing both the front and back of a object.

You want to set these in place of the those lines.

//RasterizerState rasterizerState = new RasterizerState ();
//rasterizerState.CullMode = CullMode.None;
//GraphicsDevice.RasterizerState = rasterizerState;
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;

Note you really want to use = RasterizerState.ClockWise or CounterClockwise though in general.

Also note if you are making your own new states don’t declare them inside your method it will create a ton of garbage define them at class scope.

public static RasterizerState MyRasterizerStateCullNoneSolid = new RasterizerState(){ FillMode = FillMode.Solid, CullMode = CullMode.None };

protected override void Draw(GameTime gameTime)
           // ...
           GraphicsDevice.RasterizerState = MyRasterizerStateCullNoneSolid;
           // ...
1 Like

The other possibility is that you have a depth buffer issue.

The triangles of the globe are drawn first and small inaccuracies in the depth calculation mean that the white triangles are rejected by the depth comparison.

I would try turning off the depth buffer to see what happens, and if it is a depth buffer issue you can add a depth bias when rendering the white triangles.

Thanks very much. That was exactly my problem; setting DepthStencilState solved the issue.

I didn’t realize the utility of CullClockwise and CullCounterclockwise for avoiding the unnecessary work of drawing the far side of the object and I will certainly manipulate the vertex order to take advantage of that!

Excellent reminder about minimizing extra work by declaring at the class level instead of the method level where appropriate, too.

Thanks very much for your extremely helpful response!