Search Unity

Question UV mapping a procedurally generated dungeon/cave

Discussion in 'General Graphics' started by Predulus, Jul 23, 2022.

  1. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    So I have written some code to read in a tilemap and use it to generate a 3d mesh version of it, complete with some perlin noise on the verts.

    upload_2022-7-23_9-27-25.png

    At the moment the whole thing is built as a 32 x 32 grid of "cells" comprised of 2 layers of vertices on a grid, top and bottom layers. Faces that meet at a corner, share vertices, they do not have one duplicate of the vertex for each face.

    I now want to UV map it.

    I want to do something like the below:

    upload_2022-7-23_9-30-49.png

    In considering how to do this, and checking out what I could find about UV mapping of meshes in Unity, it seems that I cannot store UVs for a vertex on a per-triangle basis. Can anyone confirm please?

    Will I be stuck with having to duplicate vertices so that each face meeting in a corner vertex has its own copy of that vertex?

    TIA!
     
  2. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    665
    That's how it is usually done for static meshes.

    Alternatively, you could duplicate the vertices in a geometry shader. If the U/V calculation is not too expensive, you could also do it in the pixel shader.

    Maybe you could even generate the mesh on the fly in a compute shader, but haven't tried that myself.
     
  3. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    Thanks for your reply, @c0d3_m0nk3y :)

    Of the approaches you listed, which would you recommend? Anybody else, feel free to chime in with opinions too please :). There will be many of these such 32x32 voxel 'chunks', which are loaded from- and serialized to-, disk, and the player moves in and out of a certain radius from them.

    I have briefly dabbled with shaders before, and I think I could code what I need to, but I'm certainly not experienced at coding them.
     
    Last edited: Jul 23, 2022
  4. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,493
    Vertices number might not be a bottleneck, it might be worth trying brute forcing it and use quad for generating the level like they are tiles.

    Maybe I misunderstood, but don't serialized the mesh, just the underlying data to reconstruct the level. Generating the level might benefit from the highly coherent processing of data due to only using quad and be cache friendly, so the cost might be low.
     
  5. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    Yeah, that's what I meant.
     
  6. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    @neoshaman, did you mean creating quads with GameObject.CreatePrimitive, or creating them like this?

    https://docs.unity3d.com/560/Documentation/Manual/Example-CreatingaBillboardPlane.html
     
  7. joshuacwilde

    joshuacwilde

    Joined:
    Feb 4, 2018
    Posts:
    726
    Yeah I would absolutely go with just creating the mesh totally on the CPU. It's way overkill to even consider creating on the GPU unless your mesh had a couple orders of magnitude more vertices.

    It should be pretty easy too. You basically just need to project the vertices onto a plane. That's all UV mapping is in the first place anyway. So floor vertices you use the XZ plane. (uv.xy becomes vertex.xz), and for walls the XY and ZY planes. That will give you a good start at least. If your geometry becomes more deformed that won't look as good, but you can expand upon the idea.

    Another option might be to just prefab the different pieces (corner piece, wall piece, floor piece, etc) then assemble those instead of generating a big mesh for the level.
     
  8. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,493
    It doesn't matter, I mean done with 4 vertices and 2 triangles. You add all of them in the same mesh to reduce drawcalls because they share the same material.

    If I were to do it, I would, in a for loop scanning the the level data:
    - initialize an offset variable before the loop
    - first compute the position of the tile by sampling the underlying level data, skip if none
    - find the orientation, assuming axis aligned room
    - add the size of the tile to the position following the orientation plane, to get the other vertex position
    - figure out which atlas tile to sample
    - position the uv coordinate to the corner of that atlas tile position
    - add the atlas tile size to the uv coordinate to get the other vertex uv coordinate
    - get the triangles indexing of the vertex
    - offset the indexing by the offset var x 4 (ie every four vertices)
    - add the data to the mesh data
    - increment the offset by one. It's not the loop iteration variable if it is possible to skip.
    - after the loop check if offset different if zero as sanity check (ie degenerate data), if empty toss the result and throw an error.