Chapter 6: Textures (without ModelI/O)

Question withdrawn because I was completely missing the point and writing rubbish. I will return to the topic after more considered reflection :slight_smile:

Shouldn’t the uvcoords be going into index 2 when you setVertexBytes?

Have you tried looking at what the buffers contain using the GPU debugger?

Yes. Actually they do. I tried to simplify the version I sent you by removing some other uniforms such as colours and lights and I forgot to change the shader to 0. It’s done now.
Yes, I’ve been in the debugger too and I can see that the inputs to the vertices are correct but I don’t know how to check what comes out of the fragments.

Don’t waste your time on this Caroline. I can see now that I don’t really have three loops at all, just 8 draw calls.

Hey, I’m back with my thoughts on this

Firstly, I hope you’re all coping well with this pandemic. For me, it’s a good opportunity to play with Metal.

So I have my own home-baked mesh which consists of inter-locking hexagons (which themselves each comprise 6 triangles). I want to decorate each hexagon with one of eight possible textures (terrain pictures: desert, mountain, etc.) which will be determined somewhat randomly. Accordingly, I have structured my mesh as eight sub-meshes, each of which is associated with one unique terrain. Each sub-mesh may contain adjacent or non-adjacent hexagons.
The picture shows a small region when the sub-meshes are consolidated. I have addressed a few of the vertices and fragments just to illustrate my problem. Vertex 1 happens to be always associated with deserts but vertex 2’s association can only be determined at the level of the sub-mesh since it abuts three different terrain types. Accordingly it is hard to provide property information at the vertex level. For instance, to colour different terrains differently is not possible in the vertex shader. However, my sub-mesh structure makes it possible to colour the hexagons a uniform colour by passing different colours to the fragment shader when processing each sub-mesh. I thought I was making progress …

Now I want to go a bit further. I want to paint a texture onto each hexagon. Look at the picture to see the problem, first at the level of vertex and then at the level of fragment. Take even vertex 1 which is always desert: in fragment A, its uv is near the bottom right of the desert bitmap where for fragment B it is near the top right. In fact it’s in six different locations in six different fragments! (Don’t even ask about vertex 2 which spans sub-meshes too!!).

As a solution, I’ve considered producing even more sub-meshes - 6 times as many with one for each of the 6 different triangles in each terrain. Then I’d send six uv pairs with each vertex but I’d still need some way of deciding which of the pairs to select for each fragment. I can’t see how. And just look at the amount of tables and indices I need to produce for what is really a very structured mesh!!

Now I know people are able to do far more sophisticated work than I’m trying to do so the above discussion just illustrates that I don’t understand something. I’m sure Metal is capable of meeting my requirements and I need to reorganise my mesh and/or write more sophisticated shaders. Can anyone tell what I’m missing?

[NB The solution of going with, say, Blender is not a solution. Blender will produce a torus divided concentric circles which in turn are divided into triangles, it is true. However, my conventric circles are not equidistant (as in Blender) nor are my triangles right-angled. Maybe that could be achieved with lots of customisation, but my model produces a torus for any number of hexes as demanded. In any case, I’m doing this to understand Metal without relying on a ModelIO black-box.]

PS. I guess I shouldn’t overlook the obvious. If I set up eight sub-meshes each with a full set of appropriate vertices and their related UVs, clearly I should be able do this in a straightforward way. Each hex is, after all, almost planar. I will end up with every vertex reproduced 6 times (each is in three hexagons and used twice in each of these hexagons - 6 triangles = 18 vertices, 6 exterior vertices twice each + central vertex 6 times) so that, far from reaping the benefits of indexing, I’ll be multiplying the data footprint. Is this what is happening under the hood with the Blender file?

It’s exceedingly inelegant and I’m shocked the developers of Metal didn’t give us access to faces. Maybe they did?

Per my post in Face normal vs vertex normal - #17 by ericmock I really don’t think Metal provides a direct way to enter face normals. If it did, then the people that wrote ModelIO were not aware of it. I suspect this is because in the vast majority of cases you don’t want faceted surfaces like you and I do.

The way I’ve overcome this appears to be similar to how ModelIO overcomes it, by repeating vertices. You will need three times the number of vertices as is necessary to define you’re hexagon mesh. (Well, not exactly if the centroid of each hexagon is a vertex.) This way you can assign three different normals to a vertex that describes the position of a corner of your hexagon.

I’m not sure how you want to organize the data structures but I went with defining a MyPolygon class (Polygon conflicts with something) that contains all the information for each face. In hindsight it probably should be a struct, but… Once I had all the polygons I just iterated over them to build by vertices (position, normal, etc.) and indices. It’s inefficient from a memory standpoint because the data send to the GPU is very repetitive, put there are few vertices compared to what you’d have in a complex scene.

The other option I considered was making a buffer of UInts that would map vertex IDs to normals in a buffer of normals. This would be more memory efficient but I didn’t feel like figuring out how to do it. The issue is figuring out which face you’re rendering in the vertex shader. Using sub-meshes for each face like Caroline did is probably the best way.

Yes, I guess we’re agreed on the approach. I’ll look at it this week and send you the results if that’s of interest.