Невозможно применить Texture2D Atlas к материалу - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь создать игру, подобную кубовому миру, в которой я постепенно создаю атлас текстур, чтобы объединить все мои текстуры в одну. Затем я создаю кубы (сделанные из квадратов), к которым я хочу применить атлас текстуры (с указанием, конечно же, uvs). Проблема, с которой я столкнулся, состоит в том, что для визуализированных кубов (или кусков) применяется серебряный материал по умолчанию, который не применяется ни к одной из моих текстур. Может кто-то увидеть, где я иду не так.

Вот репо для всего кода: https://github.com/JoshPJackson/BlockGame

Current

Общий поток логи c:

  1. Создание текстурного атласа (и сохранение тектов)
  2. Создание 6 четырехугольников для создания куба
  3. Добавить me sh рендеринг в квадроциклы
  4. Укажите uvs
  5. Примените текстуру атласа текстуры для quad me sh рендерер

В нескольких нижних строках блока. В файле cs я применяю атлас текстуры к материалу рендеринга me sh

Создатель моего атласа текстуры:

using System.Collections.Generic;
using System.IO;
using UnityEngine;
using System;

namespace Game.Textures
{
    public class TextureAtlasMapper
    {
        public Texture2D atlas;

        public Texture2D[] textures;

        public Rect[] rects;

        public Dictionary<string, Rect> mappedTextures;

        protected float individualHeight = 32.0f;

        protected float individualWidth = 32.0f;

        public TextureAtlasMapper()
        {
            UnityEngine.Object[] objects = Resources.LoadAll("textures") as UnityEngine.Object[];
            textures = new Texture2D[objects.Length];

            for (int i = 0; i < objects.Length; i++)
            {
                textures[i] = (Texture2D) objects[i];
            }

            atlas = new Texture2D(2048, 2048);
            atlas.name = "myatlas";
            rects = atlas.PackTextures(textures, 2);
            mappedTextures = new Dictionary<string, Rect>();

            for (int i = 0; i < rects.Length; i++)
            {
                mappedTextures[textures[i].name] = rects[i];
            }
        }

        public float GetImageHeight()
        {
            return atlas.height;
        }

        public float GetImageWidth()
        {
            return atlas.width;
        }

        public Vector2[] GetMappedUVs(string textureName)
        {
            if (!mappedTextures.ContainsKey(textureName))
            {
                Debug.Log("missing entry: " + textureName);
            }

                Rect rect = mappedTextures[textureName];


            Vector2[] list = new Vector2[4];

            float u1 = rect.x + rect.width;
            float u2 = rect.x;
            float u3 = u2;
            float u4 = u1;

            float v1 = rect.y + rect.height;
            float v2 = v1;
            float v3 = rect.y;
            float v4 = v3;

            list.SetValue(new Vector2(u1, v1), 0);
            list.SetValue(new Vector2(u2, v2), 1);
            list.SetValue(new Vector2(u3, v3), 2);
            list.SetValue(new Vector2(u4, v4), 3);

            return list;
        }
    }
}

Моя четверка * sh класс:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Game.Textures;
using Game.Blocks;

namespace Game.Meshes
{
public class QuadMesh
{
    Vector3[] allVertices = new Vector3[8];

    Vector3[] vertices = new Vector3[4];

    Vector3[] normals = new Vector3[4];

    Vector2[] uvs = new Vector2[4];

    public Mesh mesh; 

    int[] triangles = new int[6] { 3, 1, 0, 3, 2, 1 };

    public QuadMesh(Block.Cubeside side)
    {
        SetAllVertices();

        mesh = new Mesh();

        normals = GetNormalCollection(Vector3.up);

        switch (side)
        {
            case Block.Cubeside.BOTTOM:
                vertices = GetVertexCollection(new int[] { 0, 1, 2, 3});
                normals = GetNormalCollection(Vector3.down);
                break;
            case Block.Cubeside.TOP:
                vertices = GetVertexCollection(new int[] { 7, 6, 5, 4 });
                break;
            case Block.Cubeside.LEFT:
                vertices = GetVertexCollection(new int[] { 7, 4, 0, 3 });
                normals = GetNormalCollection(Vector3.left);
                break;
            case Block.Cubeside.RIGHT:
                vertices = GetVertexCollection(new int[] { 5, 6, 2, 1 });
                normals = GetNormalCollection(Vector3.right);
                break;
            case Block.Cubeside.FRONT:
                vertices = GetVertexCollection(new int[] { 4, 5, 1, 0 });
                break;
            case Block.Cubeside.BACK:
                vertices = GetVertexCollection(new int[] { 6, 7, 3, 2 });
                break;
        }

        mesh.vertices = vertices;
        mesh.normals = normals;
        // mesh.uv = uvs;

        Vector2 uv00 = new Vector2(0f, 0f);
        Vector2 uv10 = new Vector2(1f, 0f);
        Vector2 uv01 = new Vector2(0f, 1f);
        Vector2 uv11 = new Vector2(1f, 1f);
        mesh.uv = new Vector2[] { uv11, uv01, uv00, uv10 };

        mesh.triangles = triangles;
        mesh.RecalculateBounds();
    }

    private void SetAllVertices()
    {
        allVertices.SetValue(new Vector3(-0.5f, -0.5f, 0.5f), 0);
        allVertices.SetValue(new Vector3(0.5f, -0.5f, 0.5f), 1);
        allVertices.SetValue(new Vector3(0.5f, -0.5f, -0.5f), 2);
        allVertices.SetValue(new Vector3(-0.5f, -0.5f, -0.5f), 3);
        allVertices.SetValue(new Vector3(-0.5f, 0.5f, 0.5f), 4);
        allVertices.SetValue(new Vector3(0.5f, 0.5f, 0.5f), 5);
        allVertices.SetValue(new Vector3(0.5f, 0.5f, -0.5f), 6);
        allVertices.SetValue(new Vector3(-0.5f, 0.5f, -0.5f), 7);
    }

    private Vector3[] GetVertexCollection(int[] indices)
    {
        Vector3[] toReturn = new Vector3[4];

        for (int i = 0; i < indices.Length; i++)
        {
            toReturn.SetValue(allVertices[indices[i]], i);
        }

        return toReturn;
    }

    private Vector3[] GetNormalCollection(Vector3 normal)
    {
        return new Vector3[4]
        {
            normal,
            normal,
            normal,
            normal
        };
    }
}
}

И мой базовый блок класса:

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.U2D;
using Game.Meshes;
using Game.Textures;
using Game.Chunks;

namespace Game.Blocks
{
    abstract public class Block
    {
        // cube sides
        public enum Cubeside { BOTTOM, TOP, LEFT, RIGHT, FRONT, BACK };

        // block types
        public enum BlockType { AIR, DIRT, GRASS }

        // uvs
        public virtual string[] textureNames { get; }

        public bool isSolid = true;

        // global position
        public Vector3 globalPosition;

        public Vector3 localPosition;

        // parent chunk
        public Chunk chunk;

        // position inside chunk
        public Vector3 positionInChunk;

        public Cubeside[] renderedSides;

        public Mesh mesh;

        public GameObject parent;

        public WorldBuilder worldBuilder()
        {
            return chunk.parent.parent;
        }

        public void Render()
        {
            if (this.GetType() != typeof(Air)) {
                if (HasAirBack())
                {
                    CreateQuad(Cubeside.BACK);
                }

                if (HasAirBelow())
                {
                    CreateQuad(Cubeside.BOTTOM);
                }

                if (HasAirFront())
                {
                    CreateQuad(Cubeside.FRONT);
                }

                if (HasAirAbove())
                {
                    CreateQuad(Cubeside.TOP);
                }

                if (HasAirLeft())
                {
                    CreateQuad(Cubeside.LEFT);
                }

                if (HasAirRight())
                {
                    CreateQuad(Cubeside.RIGHT);
                }
            }
        }

        public bool HasAirAbove()
        {
            int maxHeight = ChunkColumn.chunksPerColumn * Chunk.size;

            if (globalPosition.y + 1 > maxHeight - 1)
            {
                return true;
            }

            Block blockAbove = worldBuilder().GetBlockAtGlobalPosition(new Vector3(
                globalPosition.x,
                globalPosition.y + 1,
                globalPosition.z
            ));

            return blockAbove.GetType() == typeof(Air);
        }

        public bool HasAirBelow()
        {
            if (globalPosition.y - 1 >= 0)
            {

                Block blockAbove = worldBuilder().GetBlockAtGlobalPosition(new Vector3(
                    globalPosition.x,
                    globalPosition.y - 1,
                    globalPosition.z
                ));

                return blockAbove.GetType() == typeof(Air);
            }

            return true;
        }

        public bool HasAirLeft()
        {
            if (globalPosition.x - 1 >= 0)
            {
                Block blockAbove = worldBuilder().GetBlockAtGlobalPosition(new Vector3(
                    globalPosition.x - 1,
                    globalPosition.y,
                    globalPosition.z
                ));


                return blockAbove.GetType() == typeof(Air);
            }

            return true;
        }

        public bool HasAirRight()
        {
            if (globalPosition.x + 1 < worldBuilder().Size.x * Chunk.size)
            {
                Block blockAbove = worldBuilder().GetBlockAtGlobalPosition(new Vector3(
                    globalPosition.x + 1,
                    globalPosition.y,
                    globalPosition.z
                ));

                return blockAbove.GetType() == typeof(Air);
            }

            return true;
        }

        public bool HasAirBack()
        {
            if (globalPosition.z - 1 >= 0)
            {
                Block blockAbove = worldBuilder().GetBlockAtGlobalPosition(new Vector3(
                    globalPosition.x,
                    globalPosition.y,
                    globalPosition.z - 1
                ));

                return blockAbove.GetType() == typeof(Air);
            }

            return true;
        }

        public bool HasAirFront()
        {
            if (globalPosition.z + 1 < worldBuilder().Size.x * Chunk.size - 1)
            {
                Block blockAbove = worldBuilder().GetBlockAtGlobalPosition(new Vector3(
                    globalPosition.x,
                    globalPosition.y,
                    globalPosition.z + 1
                ));

                return blockAbove.GetType() == typeof(Air);
            }

            return true;
        }

        public virtual void CreateQuad(Cubeside side)
        {
            string[] textures = new String[6];

            if (textureNames.Length == 1)
            {
                for (int j = 0; j < 6; j++)
                {
                    textures[j] = textureNames[0];
                }
            } else
            {
                textures = textureNames;
            }

            for (int i = 0; i < textures.Length; i++)
            {
                QuadMesh quadMesh = new QuadMesh(side);

                TextureAtlasMapper mapper = Game.currentGame.mapper;
                Vector2[] uvs = mapper.GetMappedUVs(textures[i]);

                GameObject quad = new GameObject("Quad");

                quad.transform.position = globalPosition;
                quad.transform.parent = chunk.GameObject.transform;
                MeshFilter meshFilter = (MeshFilter)quad.AddComponent(typeof(MeshFilter));
                Mesh myMesh = quadMesh.mesh;
                myMesh.uv = uvs;
                myMesh.RecalculateBounds();
                myMesh.name = "my mesh";
                meshFilter.mesh = myMesh;

                MeshRenderer renderer = quad.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
                renderer.material = new Material(Shader.Find("Standard"));
                renderer.material.mainTexture = mapper.atlas;
            }
        }
    }
}

1 Ответ

0 голосов
/ 26 апреля 2020

Мне пришлось изменить нижнюю строку на:

renderer.material = (Material) Resources.Load("mymaterial", typeof(Material));
renderer.material.mainTexture = mapper.atlas;
...