Circles & Triangle Fan Topology

Reporter: RobertBColton  |  Status: open  |  Last Modified: March 10, 2019, 02:29:49 PM

Long story short, some APIs, like Metal and Direct3D10 and above, do not support triangle fans. Further, triangle fans do not lend themselves to being batched together efficiently. I suppose it is for these reasons that YoYoGames dropped support for triangle fans in GMS2. For ENIGMA's D3D11 system, I have mapped the fan topology to 0 in the vertex backend until we work this out.

ENIGMA uses triangle fans internally in a few places for several reasons. The first place is for drawing filled circles and the second is for modeling the sides of 3D blocks and the ends of 3D cylinders. Prior to generalizing the model implementation in #1289 we were converting triangle fans to triangle lists so they could be easily batched with other primitives, but that was undone during the cleanup temporarily. It doesn't matter anyway because solving the issue at the model level of abstraction would not solve the problem for the lower-level vertex_* functions which can also use triangle fans.

So because the triangle fan conversion was not kept in the model class, and D3D11 does not support that topology, currently these systems will not draw circles or blocks properly. We need to decide together how we want to address this as there are several routes we can take or combine into a final solution to the problem.

  • We can simply remove the use of triangle fans from our internal code and warn the user they are not supported on some backends and devices. This is currently the approach taken by GMS2.
  • We can go back to converting triangle fans to triangle lists so that they can be combined with adjacent primitives in the model class. This would leave them broke when using the lower-level vertex_* functions directly.
  • We could convert the triangle fans to triangle lists in the vertex_* family of functions. But that may be challenging considering that the primitive topology is not specified until vertex_submit is called. This option would also be less efficient than converting them in the model class which would be able to automatically combine the triangle fans with other adjacent primitives.
  • If doing any of the above, we could do these conversions for only the systems that do not support the given topologies. However, it may be desirable to just convert the fans always so they are batched more efficiently.

Primitive Abstraction Layers

JoshDreamland  
Do we still not have arbitrary index buffer support in these systems? We can just emit our own index buffers to do what the other primitive types do. I recall having a discussion about this, earlier, but don't remember why we weren't populating our own index buffers at the time.
RobertBColton  

Do we still not have arbitrary index buffer support in these systems?

Yes, we have arbitrary index buffer support. It's quite good actually and I continue to test it. In fact, if you look at my diagram above, the tiles are implemented generically using index buffers. The only thing there is, I sort of haven't worked out the types/packing yet so I don't think 32 bit index buffers or the auto type we discussed work yet.

We can just emit our own index buffers to do what the other primitive types do.

Sure, we can do this if we work out the type issue I just discussed. Then we'd have to work on adding index buffers to the model class again, which is fine, we can do that too. And yes, using the index buffer to create the triangle fans in the model class would be most efficient and better lend the primitives to batching with other primitives. However, the only caveat is, this work will still not fix triangle fans submitted at the vertex_submit level. I mean, it won't fix triangle fans when the user uses the vertex buffer directly.

This issue is mainly discussing the best way to go about this. I am actually now considering a hybrid solution that will fix it at all levels. Triangle fans are very nice for expressing certain types of primitives, and I would not want to ugly up our code by not supporting them. Finally, I have been thinking about the implementation and believe I can reuse the same helpers to convert triangle fans into other primitives at the generic model level and the backend D3D11 level. So, I shouldn't have to actually write much code at all to pull this off.

I recall having a discussion about this, earlier, but don't remember why we weren't populating our own index buffers at the time.

It takes some time and thought to work out index buffers in the model class. I wanted to get the cleaned up and fixed models out to everybody quickly though because they were a lot more efficient and fixed several graphical anomalies. Some of those anomalies, were directly the fault of duplicate index buffer logic that had flawed batching conditions.

JoshDreamland  

Eh, okay. More time is fine. I just wanted to make sure that my stance on this issue is clear—to the extent of my knowledge, managing our own index buffers is the best strategy, be it for models or primitive batching, and once we're doing that, tranglefan and quadlist become easy to support.
Please sign in to post comments, or you can view this issue on GitHub.