无法将Texture2D Atlas应用于材质

问题描述 投票:0回答:1

我正在尝试创建一个类似于cubeworld的游戏,在该程序中,我以编程方式创建了一个纹理图集,以将我所有的纹理组合为一个。然后,我要创建要应用纹理图集的立方体(由四边形组成)(当然也要指定uvs)。我遇到的问题是渲染的多维数据集(或大块)具有默认的银色材质,并且没有我的纹理。有人可以看到我要去哪里了。

这里是所有代码的仓库:https://github.com/JoshPJackson/BlockGame

Current

逻辑的一般流程:

  1. 创建纹理图集(并存储矩形)
  2. 创建6个四边形以创建一个立方体
  3. 将网格渲染器添加到四边形
  4. 指定uvs
  5. 将纹理图集纹理应用于四边形网格渲染器

在Block.cs文件的底部几行是将纹理图集应用于网格渲染器材料的位置

我的纹理图集创建者:

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;
        }
    }
}

我的四边形网格类:

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;
            }
        }
    }
}
c# unity3d mesh texture-mapping
1个回答
0
投票

我必须将底线更改为:

renderer.material = (Material) Resources.Load("mymaterial", typeof(Material));
renderer.material.mainTexture = mapper.atlas;
© www.soinside.com 2019 - 2024. All rights reserved.