Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by JWgames · Jun 02, 2019 at 07:40 AM · terrainproceduralprocedural meshvoxelminecraft

Texture mapping procedural mesh with texture atlas? (Minecraft style terrain gen)

Hey guys, I'm currently working on a small learning project where I'm trying to recreate minecraft style terrain gen. It's been going well so far, however, I've hit a brick wall with texturing different block faces with different textures.

Heres what my terrain looks like at the minute: alt text

As you can see, I've managed to get a single texture UV mapped on all sides of the cube fine, however I just can't seem to figure out how to make each face use a different texture.

Here's my terrain generation code:

  public void RenderChunk()
     {
         Mesh mesh = GetComponent<MeshFilter>().mesh;
         mesh.Clear(false);
 
         //Clear Lists
         vertices.Clear();
         uvs.Clear();
         triangles.Clear();
 
         foreach (KeyValuePair<Vector3, TYPE> position in positions)
         {
             if (position.Value == TYPE.BLOCK)
             {
                 List<int> neededVerts = CheckAdjacentPositions(position.Key);
                 if (neededVerts.Count > 0)
                 {
                     Block block = new Block();
                     List<Vector3> verts_ = block.GetBlockVertices(position.Key, neededVerts);
 
                     int vcount = 0;
                     int face = 0; //0 = front, 1 = back, 2 = top, 3 = bottom, 4 = right, 5 = left
                     int tri = 0; //Current triangle
                     int lastTri = 0; //Previous triangle
                     int firstIndex = 0; //First index to check.
 
                     foreach (Vector3 v in verts_)
                     {
                         vertices.Add(v);
                         triangles.Add(vertices.Count-1);
 
                         //Check which face the next six verts represent by checking the first 2 vertices of face.
                         if ((vcount == 0 || tri != lastTri))
                         {
 
                             if (neededVerts[firstIndex] == 0 && neededVerts[firstIndex + 1] == 2)
                                 face = 0;
                             else if (neededVerts[firstIndex] == 5 && neededVerts[firstIndex + 1] == 4)
                                 face = 1;
                             else if (neededVerts[firstIndex] == 0 && neededVerts[firstIndex + 1] == 7)
                                 face = 5;
                             else if (neededVerts[firstIndex] == 1 && neededVerts[firstIndex + 1] == 2)
                                 face = 4;
                             else if (neededVerts[firstIndex] == 2 && neededVerts[firstIndex + 1] == 3)
                                 face = 2;
                             else if (neededVerts[firstIndex] == 0 && neededVerts[firstIndex + 1] == 6)
                                 face = 3;
                             else
                             {
                                 Debug.Log(neededVerts[firstIndex] + "??" + neededVerts[firstIndex + 1] + "    " + firstIndex);
                             }
                             lastTri = tri;
 
                         }
 
                         //Assigns UVs based of face. Each number represents a face, break down of this is given above. 
                         if (face == 0 || face == 1)
                             uvs.Add(new Vector2(v.y, v.x));
                         else if (face == 2 || face == 3)
                             uvs.Add(new Vector2(v.x, v.z));
                         else if (face == 4 || face == 5)
                             uvs.Add(new Vector2(v.z, v.y));
                        
 
                       
                         //Increment vert count
                         if (vcount >=  5)
                         {
                             tri++;
                             vcount = 0;
                             firstIndex += 6;
                         }
                         else
                             vcount++;
 
                     }
                 }
             }
         }
 
         Vector3[] verts = new Vector3[(vertices.Count)];
         int[] tris = new int[triangles.Count];
         Vector2[] uvmap = new Vector2[uvs.Count];
 
 
         //Convert Vertices, Triangles and UV's lists into arrays.
         for (int i = 0; i < vertices.Count ; i++)
             verts[i] = vertices[i];
 
         for (int t = 0; t < triangles.Count ; t++)
             tris[t] = triangles[t];
 
         for (int z = 0; z < uvs.Count; z++)
             uvmap[z] = uvs[z];
 
         //Build the mesh
         mesh.vertices = verts;
         mesh.triangles = tris;
         mesh.uv = uvmap;
         mesh.Optimize();
         mesh.RecalculateNormals();
         GetComponent<MeshCollider>().sharedMesh = mesh;
 
     }


The code pretty much checks loops through all of the blocks in a chunk, checking which faces are visible and adding them to the mesh. I then check which face a vertice is a part of and assign the appropriate UV. This is perfect to get the single texture mapped, but is useless for what I want to get done.

If anyone has any experience with this or has any ideas of what I can try to fix this it would be much appreciated :) thanks.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Jun 02, 2019 at 09:30 AM

The way you generate your UV coordinates doesn't make much sense. You essentially just use the planar projected local space position of the vertex as UV coordinate. The UV space and the world / local space are two completely independent spaces. The UV space goes from 0 to 1 in both axis. You essentially define where this vertex is located on the texture by specifying a value between 0 and 1 (0 means left for the U coordinate and bottom for the V coordinate where as 1 means right for the U and top for the V coordinate).


When you generate a quad you will have to specify the 4 corners of the portion on the texture atlas you want to map to this quad. What you need is a a logical mapping of a certain "block type" + side (north,east,south,west,top,bottom) to a set of uv coordinates on the atlas. The "old" minecraft had a fix 256x256 texture with a fix grid of 16x16 texture patches where each patch was 16x16 pixels. To better support mods the texture atlas is now usually packed at initialization time when the game start. During packing individual textures into an atlas you have to keep track where on the atlas a certain texture is located (in the sense of UV coordinates).


If you want to support higher quality textures and you have many different textures they probably won't fit onto a single atlas. In such a case things get more complicated. To some degree you could use a special shader and use another vertex attribute to encode from which atlas it should sample the texture from. Another solution is to split a chunk into several seperate meshes depending to which atlast / material a block / face belongs. If you want to support transparent materials you probably have to do this anyways for those faces.


What's the best solution depends on what features you want to support, how your atlas(es) are setup / created, what platforms you want to support, etc...

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JWgames · Jun 02, 2019 at 02:57 PM 0
Share

Thanks, managed to get it working nicely now :) alt text

avatar image Bunny83 JWgames · Jun 02, 2019 at 05:46 PM 0
Share

Good to hear ;). Note you seem to use "Vector3" for the voxel coordinates. Since those coordinates are usually whole numbers you probably want to use "Vector3i" ins$$anonymous$$d. It's a similar struct but ins$$anonymous$$d of float values it has 3 integer values. This avoids many issues with rounding

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

139 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Creating caves in voxel procedural mesh 0 Answers

World Seed 2 Answers

Performance difference between combined mesh and procedural mesh? 0 Answers

How can I smoothen my cubic mesh using marching cubes? 0 Answers

Procedural mesh artifacts 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges