Esempio n. 1
0
        public static BillboardAsset CreateBillboardAsset(GBillboardCreatorArgs args)
        {
            BillboardAsset billboard = new BillboardAsset();

            billboard.SetVertices(args.Vertices);
            billboard.SetIndices(Triangulate(args.Vertices));
            billboard.width  = args.Width;
            billboard.height = args.Height;
            billboard.bottom = args.Bottom;

            Vector4[] texcoords    = new Vector4[args.Row * args.Column];
            Vector2   imageSize    = new Vector2(1f / args.Column, 1f / args.Row);
            Vector2   imageTopLeft = new Vector2(0, 0);

            for (int y = 0; y < args.Row; ++y)
            {
                for (int x = 0; x < args.Column; ++x)
                {
                    imageTopLeft = new Vector2(x * imageSize.x, y * imageSize.y);
                    texcoords[GUtilities.To1DIndex(x, y, args.Column)] = new Vector4(imageTopLeft.x, imageTopLeft.y, imageSize.x, imageSize.y);
                }
            }
            billboard.SetImageTexCoords(texcoords);
            billboard.name = args.Target.name + "_Billboard";
            return(billboard);
        }
        private void DoRenderPreview(bool shaded)
        {
            BillboardAsset billboardAsset = this.target as BillboardAsset;
            Bounds         bounds         = new Bounds(new Vector3(0f, (this.m_Height.floatValue + this.m_Bottom.floatValue) * 0.5f, 0f), new Vector3(this.m_Width.floatValue, this.m_Height.floatValue, this.m_Width.floatValue));
            float          magnitude      = bounds.extents.magnitude;
            float          num            = 8f * magnitude;
            Quaternion     quaternion     = Quaternion.Euler(-this.m_PreviewDir.y, -this.m_PreviewDir.x, 0f);

            this.m_PreviewUtility.m_Camera.transform.rotation   = quaternion;
            this.m_PreviewUtility.m_Camera.transform.position   = quaternion * (-Vector3.forward * num);
            this.m_PreviewUtility.m_Camera.nearClipPlane        = num - magnitude * 1.1f;
            this.m_PreviewUtility.m_Camera.farClipPlane         = num + magnitude * 1.1f;
            this.m_PreviewUtility.m_Light[0].intensity          = 1.4f;
            this.m_PreviewUtility.m_Light[0].transform.rotation = quaternion * Quaternion.Euler(40f, 40f, 0f);
            this.m_PreviewUtility.m_Light[1].intensity          = 1.4f;
            Color ambient = new Color(0.1f, 0.1f, 0.1f, 0f);

            InternalEditorUtility.SetCustomLighting(this.m_PreviewUtility.m_Light, ambient);
            if (shaded)
            {
                billboardAsset.MakeRenderMesh(this.m_ShadedMesh, 1f, 1f, 0f);
                billboardAsset.MakeMaterialProperties(this.m_ShadedMaterialProperties, this.m_PreviewUtility.m_Camera);
                ModelInspector.RenderMeshPreviewSkipCameraAndLighting(this.m_ShadedMesh, bounds, this.m_PreviewUtility, billboardAsset.material, null, this.m_ShadedMaterialProperties, new Vector2(0f, 0f), -1);
            }
            else
            {
                billboardAsset.MakePreviewMesh(this.m_GeometryMesh);
                ModelInspector.RenderMeshPreviewSkipCameraAndLighting(this.m_GeometryMesh, bounds, this.m_PreviewUtility, this.m_GeometryMaterial, this.m_WireframeMaterial, null, new Vector2(0f, 0f), -1);
            }
            InternalEditorUtility.RemoveCustomLighting();
        }
Esempio n. 3
0
        // Make a mesh out of the BillboardAsset that is suitable for previewing the geometry.
        // The vertices are expanded and made double-face.
        private void MakePreviewMesh(Mesh mesh, BillboardAsset billboard)
        {
            float width  = billboard.width;
            float height = billboard.height;
            float bottom = billboard.bottom;

            mesh.SetVertices(Enumerable.Repeat(
                                 billboard.GetVertices().Select(v => new Vector3(
                                                                    (v.x - 0.5f) * width,
                                                                    v.y * height + bottom,
                                                                    0)),
                                 // Repeat the sequence twice
                                 2).SelectMany(s => s).ToList());

            // (0,0,1) for the front-facing vertices and (0,0,-1) for the back-facing vertices
            mesh.SetNormals(
                Enumerable.Repeat(Vector3.forward, billboard.vertexCount).Concat(
                    Enumerable.Repeat(-Vector3.forward, billboard.vertexCount)).ToList());

            // make a new triangle list with second half triangles flipped
            var indices          = new int[billboard.indexCount * 2];
            var billboardIndices = billboard.GetIndices();

            for (int i = 0; i < billboard.indexCount / 3; ++i)
            {
                indices[i * 3 + 0] = billboardIndices[i * 3 + 0];
                indices[i * 3 + 1] = billboardIndices[i * 3 + 1];
                indices[i * 3 + 2] = billboardIndices[i * 3 + 2];
                indices[i * 3 + 0 + billboard.indexCount] = billboardIndices[i * 3 + 2];
                indices[i * 3 + 1 + billboard.indexCount] = billboardIndices[i * 3 + 1];
                indices[i * 3 + 2 + billboard.indexCount] = billboardIndices[i * 3 + 0];
            }
            mesh.SetTriangles(indices, 0);
        }
        private Mesh CreateBillboardMesh(BillboardAsset billboard)
        {
            Mesh m = new Mesh();

            Vector2[] uvs      = billboard.GetVertices();
            Vector3[] vertices = new Vector3[billboard.vertexCount];
            for (int i = 0; i < vertices.Length; ++i)
            {
                vertices[i] = new Vector3(
                    (uvs[i].x - 0.5f) * billboard.width,
                    uvs[i].y * billboard.height + billboard.bottom,
                    0);
            }
            ushort[] tris    = billboard.GetIndices();
            int[]    trisInt = new int[tris.Length];
            for (int i = 0; i < trisInt.Length; ++i)
            {
                trisInt[i] = tris[i];
            }

            m.vertices  = vertices;
            m.uv        = uvs;
            m.triangles = trisInt;
            m.name      = billboard.name;
            return(m);
        }
Esempio n. 5
0
        public static void vCreateNew_BillbardAsset_FromObjects(this GameObject obj, string directory, string billBoardAssetExtendname = "", bool applyNewToObj = true)
        {
            BillboardRenderer billboardRenderer = obj.GetComponentInChildren <BillboardRenderer>();

            if (billboardRenderer != null)
            {
                if (billboardRenderer.billboard == null)
                {
                    Debug.Log("Billboard is Null"); return;
                }
                BillboardAsset newBillboardAsset = new BillboardAsset();
                newBillboardAsset.width    = billboardRenderer.billboard.width;
                newBillboardAsset.height   = billboardRenderer.billboard.height;
                newBillboardAsset.bottom   = billboardRenderer.billboard.bottom;
                newBillboardAsset.material = billboardRenderer.sharedMaterial;

                string billboardAssetPath = directory + "/" + obj.name + billBoardAssetExtendname + "_Billboard.asset";
                AssetDatabase.CreateAsset(newBillboardAsset, billboardAssetPath);
                AssetDatabase.Refresh();
                if (applyNewToObj)
                {
                    billboardRenderer.billboard = newBillboardAsset;
                }
            }
        }
Esempio n. 6
0
 // Make a mesh out of the BillboardAsset that is used for rendering by SpeedTree billboard shader.
 // Vertices are expanded by the shader therefore the mesh vertices are not used (filled by zeroes).
 internal static void MakeRenderMesh(Mesh mesh, BillboardAsset billboard)
 {
     mesh.SetVertices(Enumerable.Repeat(Vector3.zero, billboard.vertexCount).ToList());
     mesh.SetColors(Enumerable.Repeat(Color.black, billboard.vertexCount).ToList());
     mesh.SetUVs(0, billboard.GetVertices().ToList());
     mesh.SetUVs(1, Enumerable.Repeat(new Vector4(1.0f, 1.0f, 0.0f, 0.0f), billboard.vertexCount).ToList());
     mesh.SetTriangles(billboard.GetIndices().Select(v => (int)v).ToList(), 0);
 }
Esempio n. 7
0
 private void MakeRenderMesh(Mesh mesh, BillboardAsset billboard)
 {
     mesh.SetVertices(Enumerable.Repeat <Vector3>(Vector3.zero, billboard.vertexCount).ToList <Vector3>());
     mesh.SetColors(Enumerable.Repeat <Color>(Color.black, billboard.vertexCount).ToList <Color>());
     mesh.SetUVs(0, billboard.GetVertices().ToList <Vector2>());
     mesh.SetUVs(1, Enumerable.Repeat <Vector4>(new Vector4(1f, 1f, 0f, 0f), billboard.vertexCount).ToList <Vector4>());
     mesh.SetTriangles((from v in billboard.GetIndices()
                        select(int) v).ToList <int>(), 0);
 }
Esempio n. 8
0
        private BillboardAsset CreateUnityBillboardAsset(string folder, string assetName, string assetPath)
        {
            var shaderBillboard = Shader.Find("G2Studios/Imposter/UnityBillboard");

            BillboardRendererMaterial = new Material(shaderBillboard);
            BillboardRendererMaterial.SetTexture("_ImposterBaseTex", BaseTexture);
            BillboardRendererMaterial.SetTexture("_ImposterWorldNormalDepthTex", PackTexture);

            BillboardRendererMaterial.SetFloat("_ImposterFrames", Frames);
            BillboardRendererMaterial.SetFloat("_ImposterSize", Radius);
            BillboardRendererMaterial.SetVector("_ImposterOffset", Offset);
            BillboardRendererMaterial.SetFloat("_ImposterFullSphere", IsHalf ? 0f : 1f);
            BillboardRendererMaterial.name = assetName + "_BR";
            EditorUtility.SetDirty(BillboardRendererMaterial);

            AssetDatabase.CreateAsset(BillboardRendererMaterial, folder + "/" + assetName + "_Imposter_BillboardMat.mat");
            BillboardAsset = new BillboardAsset
            {
                material = BillboardRendererMaterial
            };

            BillboardAsset.SetVertices(new Vector2[]
            {
                new Vector2(0.5f, 0.5f),
                new Vector2(0.0f, 0.0f),
                new Vector2(1.0f, 0.0f),
                new Vector2(1.0f, 1.0f),
                new Vector2(0.0f, 1.0f)
            });
            BillboardAsset.SetIndices(new ushort[]
            {
                2, 1, 0,
                3, 2, 0,
                4, 3, 0,
                1, 4, 0
            });
            BillboardAsset.SetImageTexCoords(new Vector4[]
            {
                new Vector4(0.5f, 0.5f, 0f, 0f),
                new Vector4(0.0f, 0.0f, 0f, 0f),
                new Vector4(1.0f, 0.0f, 0f, 0f),
                new Vector4(1.0f, 1.0f, 0f, 0f),
                new Vector4(0.0f, 1.0f, 0f, 0f)
            });

            BillboardAsset.width  = Radius;
            BillboardAsset.height = Radius;
            BillboardAsset.bottom = Radius * 0.5f;
            BillboardAsset.name   = "BillboardAsset";
            EditorUtility.SetDirty(BillboardAsset);
            AssetDatabase.AddObjectToAsset(BillboardAsset, assetPath);
            return(BillboardAsset);
        }
        public void UpdateBillboardMesh(BillboardAsset billboard)
        {
            if (BillboardMeshes.ContainsKey(billboard) && BillboardMeshes[billboard] != null)
            {
                GUtilities.DestroyObject(BillboardMeshes[billboard]);
                BillboardMeshes.Remove(billboard);
            }

            Mesh m = CreateBillboardMesh(billboard);

            BillboardMeshes.Add(billboard, m);
        }
Esempio n. 10
0
 public static Mesh GetMesh(BillboardAsset billboard)
 {
     if (!BillboardMeshes.ContainsKey(billboard))
     {
         BillboardMeshes.Add(billboard, null);
     }
     if (BillboardMeshes[billboard] == null)
     {
         Mesh m = CreateMesh(billboard);
         BillboardMeshes[billboard] = m;
     }
     return(BillboardMeshes[billboard]);
 }
        public Mesh GetBillboardMesh(BillboardAsset billboard)
        {
            if (BillboardMeshes.ContainsKey(billboard) && BillboardMeshes[billboard] != null)
            {
                return(BillboardMeshes[billboard]);
            }
            else if (BillboardMeshes.ContainsKey(billboard) && BillboardMeshes[billboard] == null)
            {
                BillboardMeshes.Remove(billboard);
            }

            Mesh m = CreateBillboardMesh(billboard);

            BillboardMeshes.Add(billboard, m);
            return(m);
        }
    public static int get_material(IntPtr l)
    {
        int result;

        try
        {
            BillboardAsset billboardAsset = (BillboardAsset)LuaObject.checkSelf(l);
            LuaObject.pushValue(l, true);
            LuaObject.pushValue(l, billboardAsset.material);
            result = 2;
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
    public static int constructor(IntPtr l)
    {
        int result;

        try
        {
            BillboardAsset o = new BillboardAsset();
            LuaObject.pushValue(l, true);
            LuaObject.pushValue(l, o);
            result = 2;
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
    public static int set_material(IntPtr l)
    {
        int result;

        try
        {
            BillboardAsset billboardAsset = (BillboardAsset)LuaObject.checkSelf(l);
            Material       material;
            LuaObject.checkType <Material>(l, 2, out material);
            billboardAsset.material = material;
            LuaObject.pushValue(l, true);
            result = 1;
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
    public static int set_bottom(IntPtr l)
    {
        int result;

        try
        {
            BillboardAsset billboardAsset = (BillboardAsset)LuaObject.checkSelf(l);
            float          bottom;
            LuaObject.checkType(l, 2, out bottom);
            billboardAsset.bottom = bottom;
            LuaObject.pushValue(l, true);
            result = 1;
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
Esempio n. 16
0
        private void MakePreviewMesh(Mesh mesh, BillboardAsset billboard)
        {
            float width  = billboard.width;
            float height = billboard.height;
            float bottom = billboard.bottom;

            mesh.SetVertices(Enumerable.Repeat <IEnumerable <Vector3> >(from v in billboard.GetVertices()
                                                                        select new Vector3((v.x - 0.5f) * width, v.y * height + bottom, 0f), 2).SelectMany((IEnumerable <Vector3> s) => s).ToList <Vector3>());
            mesh.SetNormals(Enumerable.Repeat <Vector3>(Vector3.forward, billboard.vertexCount).Concat(Enumerable.Repeat <Vector3>(-Vector3.forward, billboard.vertexCount)).ToList <Vector3>());
            int[]    array   = new int[billboard.indexCount * 2];
            ushort[] indices = billboard.GetIndices();
            for (int i = 0; i < billboard.indexCount / 3; i++)
            {
                array[i * 3]     = (int)indices[i * 3];
                array[i * 3 + 1] = (int)indices[i * 3 + 1];
                array[i * 3 + 2] = (int)indices[i * 3 + 2];
                array[i * 3 + billboard.indexCount]     = (int)indices[i * 3 + 2];
                array[i * 3 + 1 + billboard.indexCount] = (int)indices[i * 3 + 1];
                array[i * 3 + 2 + billboard.indexCount] = (int)indices[i * 3];
            }
            mesh.SetTriangles(array, 0);
        }
    public static int SetImageTexCoords(IntPtr l)
    {
        int result;

        try
        {
            int total = LuaDLL.lua_gettop(l);
            if (LuaObject.matchType(l, total, 2, typeof(List <Vector4>)))
            {
                BillboardAsset billboardAsset = (BillboardAsset)LuaObject.checkSelf(l);
                List <Vector4> imageTexCoords;
                LuaObject.checkType <List <Vector4> >(l, 2, out imageTexCoords);
                billboardAsset.SetImageTexCoords(imageTexCoords);
                LuaObject.pushValue(l, true);
                result = 1;
            }
            else if (LuaObject.matchType(l, total, 2, typeof(Vector4[])))
            {
                BillboardAsset billboardAsset2 = (BillboardAsset)LuaObject.checkSelf(l);
                Vector4[]      imageTexCoords2;
                LuaObject.checkArray <Vector4>(l, 2, out imageTexCoords2);
                billboardAsset2.SetImageTexCoords(imageTexCoords2);
                LuaObject.pushValue(l, true);
                result = 1;
            }
            else
            {
                LuaObject.pushValue(l, false);
                LuaDLL.lua_pushstring(l, "No matched override function SetImageTexCoords to call");
                result = 2;
            }
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
    public static int GetImageTexCoords(IntPtr l)
    {
        int result;

        try
        {
            int num = LuaDLL.lua_gettop(l);
            if (num == 2)
            {
                BillboardAsset billboardAsset = (BillboardAsset)LuaObject.checkSelf(l);
                List <Vector4> imageTexCoords;
                LuaObject.checkType <List <Vector4> >(l, 2, out imageTexCoords);
                billboardAsset.GetImageTexCoords(imageTexCoords);
                LuaObject.pushValue(l, true);
                result = 1;
            }
            else if (num == 1)
            {
                BillboardAsset billboardAsset2 = (BillboardAsset)LuaObject.checkSelf(l);
                Vector4[]      imageTexCoords2 = billboardAsset2.GetImageTexCoords();
                LuaObject.pushValue(l, true);
                LuaObject.pushValue(l, imageTexCoords2);
                result = 2;
            }
            else
            {
                LuaObject.pushValue(l, false);
                LuaDLL.lua_pushstring(l, "No matched override function GetImageTexCoords to call");
                result = 2;
            }
        }
        catch (Exception e)
        {
            result = LuaObject.error(l, e);
        }
        return(result);
    }
Esempio n. 19
0
    public void ExtractXMLTreePrototypeData()
    {
        TreeSystemPrototypeData[] data = m_ManagedPrototypes;

        for (int i = 0; i < data.Length; i++)
        {
            TreeSystemPrototypeData d = data[i];

            if (d.m_TreePrototype == null)
            {
                Debug.LogError("Nothing set for data at index: " + i);
                continue;
            }

            // Get the protorype's billboard asset
            BillboardRenderer bill = d.m_TreePrototype.GetComponentInChildren <BillboardRenderer>();

            if (bill == null)
            {
                Debug.LogError("Prototype: " + d.m_TreePrototype.name + " does not contain a billboard renderer! Items without billboard renderers are not supported at the moment!");
                continue;
            }

            BillboardAsset billAsset = bill.billboard;

            // Set sizes
            d.m_Size = new Vector3(billAsset.width, billAsset.height, billAsset.bottom);


            Vector4[] uvs = billAsset.GetImageTexCoords();

            // Ussualy 16
            d.m_VertBillboardUVs = new Vector2[uvs.Length * 4];
            // Just set the first UV's just to have something
            d.m_HorzBillboardUVs = new Vector2[4];

            for (int uvIdx = 0, billUv = 0; uvIdx < uvs.Length; uvIdx++, billUv += 4)
            {
                Vector4 extract = uvs[uvIdx];

                if (uvIdx == 0)
                {
                    d.m_HorzBillboardUVs[0] = new Vector2(extract.x, extract.y);
                    d.m_HorzBillboardUVs[1] = new Vector2(extract.x, extract.y) + new Vector2(0, Mathf.Abs(extract.w));
                    d.m_HorzBillboardUVs[2] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, Mathf.Abs(extract.w));
                    d.m_HorzBillboardUVs[3] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, 0);
                }

                // We are rotated
                if (extract.w < 0)
                {
                    d.m_VertBillboardUVs[billUv + 0] = new Vector2(extract.x, extract.y);
                    d.m_VertBillboardUVs[billUv + 1] = new Vector2(extract.x, extract.y) + new Vector2(0, Mathf.Abs(extract.w));
                    d.m_VertBillboardUVs[billUv + 2] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, Mathf.Abs(extract.w));
                    d.m_VertBillboardUVs[billUv + 3] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, 0);
                }
                else
                {
                    d.m_VertBillboardUVs[billUv + 0] = new Vector2(extract.x, extract.y);
                    d.m_VertBillboardUVs[billUv + 1] = new Vector2(extract.x, extract.y) + new Vector2(extract.z, 0);
                    d.m_VertBillboardUVs[billUv + 2] = new Vector2(extract.x, extract.y) + new Vector2(extract.z, extract.w);
                    d.m_VertBillboardUVs[billUv + 3] = new Vector2(extract.x, extract.y) + new Vector2(0, extract.w);
                }
            }

            Vector4 size = d.m_Size;
            size.w = 1;

            // Create the material with the texture references
            Material billboardMaterialBatch = new Material(m_BillboardShaderBatch);
            billboardMaterialBatch.SetTexture("_MainTex", bill.billboard.material.GetTexture("_MainTex"));
            billboardMaterialBatch.SetTexture("_BumpMap", bill.billboard.material.GetTexture("_BumpMap"));
            billboardMaterialBatch.SetVector("_Size", size);

            // Replace, don't delete
            // AssetDatabase.DeleteAsset(m_DataStorePath + "/" + d.m_TreePrototype.name + "_Mat.mat");
            AssetDatabase.CreateAsset(billboardMaterialBatch,
                                      m_DataStorePath + "/" + d.m_TreePrototype.name + "_Bill_Batch_Mat.mat");

            // Set the material
            d.m_BillboardBatchMaterial = billboardMaterialBatch;

            // Set billboard data
            TreeSystem.SetMaterialBillProps(d, d.m_BillboardBatchMaterial);
        }

        AssetDatabase.Refresh();
    }
Esempio n. 20
0
    private BillboardAsset CreateUnityBillboardAsset(string folder, string assetName, string assetPath)
    {
        //shader for unity billboards (billboardRenderer and BillboardAsset)
        var shaderBillboard = Shader.Find("XRA/IMP/UnityBillboard");

        //billboardRenderer material
        BillboardRendererMaterial = new Material(shaderBillboard);

        BillboardRendererMaterial.SetTexture("_ImposterBaseTex", BaseTexture);
        BillboardRendererMaterial.SetTexture("_ImposterWorldNormalDepthTex", PackTexture);

        BillboardRendererMaterial.SetFloat("_ImposterFrames", Frames);
        BillboardRendererMaterial.SetFloat("_ImposterSize", Radius);
        BillboardRendererMaterial.SetVector("_ImposterOffset", Offset);
        BillboardRendererMaterial.SetFloat("_ImposterFullSphere", IsHalf ? 0f : 1f);
        BillboardRendererMaterial.name = assetName + "_BR";
        EditorUtility.SetDirty(BillboardRendererMaterial);

        //create material
        AssetDatabase.CreateAsset(BillboardRendererMaterial, folder + "/" + assetName + "_Imposter_BillboardMat.mat");

        //TODO billboard renderer support
        //create billboard
        BillboardAsset = new BillboardAsset
        {
            //for billboardRenderer use an alternative shader
            material = BillboardRendererMaterial
        };

        //billboard renderer vertices must be within 0 to 1 range
        //and only vector2 so we need to swwap the Y Z in shader
        //in shader (*2-1)*0.5 to get back to original
        //also doesnt accept vertex normals
        BillboardAsset.SetVertices(new Vector2[]
        {
            new Vector2(0.5f, 0.5f),
            new Vector2(0.0f, 0.0f),
            new Vector2(1.0f, 0.0f),
            new Vector2(1.0f, 1.0f),
            new Vector2(0.0f, 1.0f)
        });
        BillboardAsset.SetIndices(new ushort[]
        {
            2, 1, 0,
            3, 2, 0,
            4, 3, 0,
            1, 4, 0
        });
        BillboardAsset.SetImageTexCoords(new Vector4[]
        {
            new Vector4(0.5f, 0.5f, 0f, 0f),
            new Vector4(0.0f, 0.0f, 0f, 0f),
            new Vector4(1.0f, 0.0f, 0f, 0f),
            new Vector4(1.0f, 1.0f, 0f, 0f),
            new Vector4(0.0f, 1.0f, 0f, 0f)
        });

        BillboardAsset.width  = Radius;
        BillboardAsset.height = Radius;
        BillboardAsset.bottom = Radius * 0.5f;
        BillboardAsset.name   = "BillboardAsset";
        EditorUtility.SetDirty(BillboardAsset);
        AssetDatabase.AddObjectToAsset(BillboardAsset, assetPath);
        return(BillboardAsset);
    }
        public static void ExtractBillboardData(BillboardRenderer billboardData, FoliageTypeSpeedTreeData data)
        {
            BillboardAsset billAsset = billboardData.billboard;

            Vector4 size = new Vector4(billAsset.width, billAsset.height, billAsset.bottom, 1);

            // UV Extraction
            Vector4[] uvs = billAsset.GetImageTexCoords();

            Vector2[] vertBillUV = new Vector2[uvs.Length * 4];
            Vector2[] horzBillUV = new Vector2[4];

            // Build the UV's
            for (int uvIdx = 0, billUv = 0; uvIdx < uvs.Length; uvIdx++, billUv += 4)
            {
                Vector4 extract = uvs[uvIdx];

                if (uvIdx == 0)
                {
                    horzBillUV[0] = new Vector2(extract.x, extract.y);
                    horzBillUV[1] = new Vector2(extract.x, extract.y) + new Vector2(0, Mathf.Abs(extract.w));
                    horzBillUV[2] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, Mathf.Abs(extract.w));
                    horzBillUV[3] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, 0);
                }

                // We are rotated
                if (extract.w < 0)
                {
                    vertBillUV[billUv + 0] = new Vector2(extract.x, extract.y);
                    vertBillUV[billUv + 1] = new Vector2(extract.x, extract.y) + new Vector2(0, Mathf.Abs(extract.w));
                    vertBillUV[billUv + 2] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, Mathf.Abs(extract.w));
                    vertBillUV[billUv + 3] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, 0);
                }
                else
                {
                    vertBillUV[billUv + 0] = new Vector2(extract.x, extract.y);
                    vertBillUV[billUv + 1] = new Vector2(extract.x, extract.y) + new Vector2(extract.z, 0);
                    vertBillUV[billUv + 2] = new Vector2(extract.x, extract.y) + new Vector2(extract.z, extract.w);
                    vertBillUV[billUv + 3] = new Vector2(extract.x, extract.y) + new Vector2(0, extract.w);
                }
            }

            // Build the UVs ready for the shader
            Vector4[] UV_U = new Vector4[8];
            Vector4[] UV_V = new Vector4[8];

            Vector2[] uv = vertBillUV;

            for (int i = 0; i < 8; i++)
            {
                // 4 by 4 elements
                UV_U[i].x = uv[4 * i + 0].x;
                UV_U[i].y = uv[4 * i + 1].x;
                UV_U[i].z = uv[4 * i + 2].x;
                UV_U[i].w = uv[4 * i + 3].x;

                UV_V[i].x = uv[4 * i + 0].y;
                UV_V[i].y = uv[4 * i + 1].y;
                UV_V[i].z = uv[4 * i + 2].y;
                UV_V[i].w = uv[4 * i + 3].y;
            }

            // Assign the data
            data.m_Size              = size;
            data.m_VertBillboardU    = UV_U;
            data.m_VertBillboardV    = UV_V;
            data.m_BillboardRenderer = billboardData;
            data.m_BillboardMaterial = GenerateBillboardMaterial(data);
        }
Esempio n. 22
0
    void BakeBillboard()
    {
        BillboardAsset billboard = new BillboardAsset();

        billboard.material = m_material;
        Vector4[] texCoords = new Vector4[8];
        ushort[]  indices   = new ushort[6];
        Vector2[] vertices  = new Vector2[4];

        //float height = 0.3333f * ratio;
        //float offsetY = 0.3333f * (1 - ratio) / 2;

        //height = 0.3333f;
        //offset = 0;

        texCoords[0].Set(0.3333f + offsetU, 0 + offsetV, sizeU, sizeV);
        texCoords[1].Set(0.6667f + offsetU, 0 + offsetV, sizeU, sizeV);
        texCoords[2].Set(0.0f + offsetU, 0.3333f + offsetV, sizeU, sizeV);
        texCoords[3].Set(0.3333f + offsetU, 0.3333f + offsetV, sizeU, sizeV);
        texCoords[4].Set(0.6667f + offsetU, 0.3333f + offsetV, sizeU, sizeV);
        texCoords[5].Set(0.0f + offsetU, 0.6667f + offsetV, sizeU, sizeV);
        texCoords[6].Set(0.3333f + offsetU, 0.6667f + offsetV, sizeU, sizeV);
        texCoords[7].Set(0.6667f + offsetU, 0.6667f + offsetV, sizeU, sizeV);

        ratio = sizeV / sizeU;

        //indices[0] = 0;
        //indices[1] = 3;
        //indices[2] = 1;
        //indices[3] = 3;
        //indices[4] = 4;
        //indices[5] = 1;
        //indices[6] = 1;
        //indices[7] = 4;
        //indices[8] = 5;
        //indices[9] = 1;
        //indices[10] = 5;
        //indices[11] = 2;

        indices[0] = 0;
        indices[1] = 3;
        indices[2] = 1;
        indices[3] = 2;
        indices[4] = 3;
        indices[5] = 0;

        //vertices[0].Set(0.47093f, 1);
        //vertices[1].Set(0.037790697f, 0.498547f);
        //vertices[2].Set(0.037790697f, 0.020348798f);
        //vertices[3].Set(0.58906996f, 1);
        //vertices[4].Set(0.95930207f, 0.498547f);
        //vertices[5].Set(0.95930207f, 0.020348798f);

        vertices[0].Set(0, 1);
        vertices[1].Set(0, 0);
        vertices[2].Set(1, 1);
        vertices[3].Set(1, 0);

        billboard.SetImageTexCoords(texCoords);
        billboard.SetIndices(indices);
        billboard.SetVertices(vertices);

        //billboard.width = 19.03616f;
        //billboard.height = 19.58068f;
        //billboard.bottom = -1.814002f;

        billboard.width  = width;
        billboard.height = width * ratio;
        billboard.bottom = 0;

        if (m_outputFile != null)
        {
            EditorUtility.CopySerialized(billboard, m_outputFile);
        }
        else
        {
            string path;
            path = AssetDatabase.GetAssetPath(m_material);
            path = path.Remove(path.Length - (m_material.name.Length + 4));
            AssetDatabase.CreateAsset(billboard, path + "resource/BillboardAsset.asset");
        }
    }
Esempio n. 23
0
        public void Save(string assetPath, string assetName, bool createBillboardAsset = false)
        {
            var lastSlash = assetPath.LastIndexOf("/", StringComparison.Ordinal);

            var folder = assetPath.Substring(0, lastSlash);

            EditorUtility.SetDirty(this);

            BaseTexture.name = "ImposterBase";
            var baseTexPath = WriteTexture(BaseTexture, folder, assetName);

            PackTexture.name = "ImposterPack";
            var normTexPath = WriteTexture(PackTexture, folder, assetName);

            AssetDatabase.Refresh();

            var importer = AssetImporter.GetAtPath(baseTexPath) as TextureImporter;

            if (importer != null)
            {
                importer.textureType         = TextureImporterType.Default;
                importer.maxTextureSize      = AtlasResolution;
                importer.alphaSource         = TextureImporterAlphaSource.FromInput;
                importer.alphaIsTransparency = false;
                importer.sRGBTexture         = false;
                importer.SaveAndReimport();
                BaseTexture = AssetDatabase.LoadAssetAtPath <Texture2D>(baseTexPath);
            }

            importer = AssetImporter.GetAtPath(normTexPath) as TextureImporter;
            if (importer != null)
            {
                importer.textureType         = TextureImporterType.Default;
                importer.maxTextureSize      = AtlasResolution;
                importer.alphaSource         = TextureImporterAlphaSource.FromInput;
                importer.alphaIsTransparency = false;
                importer.sRGBTexture         = false;
                importer.SaveAndReimport();
                PackTexture = AssetDatabase.LoadAssetAtPath <Texture2D>(normTexPath);
            }

            var shader = Shader.Find("G2Studios/Imposter/Standard");

            Material = new Material(shader);
            Material.SetTexture("_ImposterBaseTex", BaseTexture);
            Material.SetTexture("_ImposterWorldNormalDepthTex", PackTexture);
            Material.SetFloat("_ImposterFrames", Frames);
            Material.SetFloat("_ImposterSize", Radius);
            Material.SetVector("_ImposterOffset", Offset);
            Material.SetFloat("_ImposterFullSphere", IsHalf ? 0f : 1f);
            Material.name = assetName;
            EditorUtility.SetDirty(Material);

            //create material
            AssetDatabase.CreateAsset(Material, folder + "/" + assetName + "_Imposter_Mat.mat");

            //mesh (not for billboardAsset)
            Mesh      = MeshSetup();
            Mesh.name = "ImposterQuad_" + Radius.ToString("F1");
            AssetDatabase.AddObjectToAsset(Mesh, assetPath);

            if (createBillboardAsset)
            {
                BillboardAsset = CreateUnityBillboardAsset(folder, assetName, assetPath);
            }

            AssetDatabase.SaveAssets();
        }
Esempio n. 24
0
        private void SaveAssets()
        {
            string folder = EditorUtility.OpenFolderPanel("Select Folder", "Assets/", "");

            if (string.IsNullOrEmpty(folder))
            {
                return;
            }
            try
            {
                GAnalytics.Record(GAnalytics.BILLBOARD_SAVE);
                EditorUtility.DisplayProgressBar("Saving", "Saving assets...", 1f);
                GBillboardCreatorArgs args      = ConstructArgs();
                BillboardAsset        billboard = GBillboardCreator.CreateBillboardAsset(args);
                Texture2D             atlas     = GBillboardCreator.RenderAtlas(args);
                Texture2D             normal    = GBillboardCreator.RenderNormal(args);

                string         billboardPath  = Path.Combine(FileUtil.GetProjectRelativePath(folder), billboard.name + ".asset");
                BillboardAsset billboardAsset = AssetDatabase.LoadAssetAtPath <BillboardAsset>(billboardPath);
                if (billboardAsset == null)
                {
                    AssetDatabase.CreateAsset(billboard, billboardPath);
                    billboardAsset = billboard;
                }
                else
                {
                    billboardAsset.SetVertices(billboard.GetVertices());
                    billboardAsset.SetIndices(billboard.GetIndices());
                    billboardAsset.SetImageTexCoords(billboard.GetImageTexCoords());
                    billboardAsset.width  = billboard.width;
                    billboardAsset.height = billboard.height;
                    billboardAsset.bottom = billboard.bottom;
                    billboardAsset.name   = billboard.name;
                }

                string atlasPath = Path.Combine(FileUtil.GetProjectRelativePath(folder), atlas.name + ".png");
                byte[] atlasData = atlas.EncodeToPNG();
                File.WriteAllBytes(atlasPath, atlasData);
                GUtilities.DestroyObject(atlas);

                string normalPath = Path.Combine(FileUtil.GetProjectRelativePath(folder), normal.name + ".png");
                byte[] normalData = normal.EncodeToPNG();
                File.WriteAllBytes(normalPath, normalData);
                GUtilities.DestroyObject(normal);

                AssetDatabase.Refresh();

                TextureImporter atlasImporter = AssetImporter.GetAtPath(atlasPath) as TextureImporter;
                atlasImporter.wrapMode            = TextureWrapMode.Clamp;
                atlasImporter.alphaIsTransparency = true;
                atlasImporter.SaveAndReimport();
                atlas = AssetDatabase.LoadAssetAtPath <Texture2D>(atlasPath);

                TextureImporter normalImporter = AssetImporter.GetAtPath(normalPath) as TextureImporter;
                normalImporter.textureType = TextureImporterType.NormalMap;
                normalImporter.wrapMode    = TextureWrapMode.Clamp;
                normalImporter.SaveAndReimport();
                normal = AssetDatabase.LoadAssetAtPath <Texture2D>(normalPath);


                Material mat = null;
                if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Universal)
                {
                    mat = Object.Instantiate(GGriffinSettings.Instance.TerrainDataDefault.Foliage.TreeBillboardMaterialURP);
                }
                else if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Lightweight)
                {
                    mat = Object.Instantiate(GGriffinSettings.Instance.TerrainDataDefault.Foliage.TreeBillboardMaterialLWRP);
                }
                else
                {
                    mat = Object.Instantiate(GGriffinSettings.Instance.TerrainDataDefault.Foliage.TreeBillboardMaterial);
                }
                if (mat != null)
                {
                    if (mat.HasProperty("_MainTex"))
                    {
                        mat.SetTexture("_MainTex", atlas);
                    }
                    if (mat.HasProperty("_BumpMap"))
                    {
                        mat.SetTexture("_BumpMap", normal);
                    }
                    mat.name = args.Target.name + "_BillboardMaterial";
                    string matPath = Path.Combine(FileUtil.GetProjectRelativePath(folder), mat.name + ".mat");
                    AssetDatabase.CreateAsset(mat, matPath);
                    billboardAsset.material = mat;
                }
                AssetDatabase.Refresh();
            }
            catch (System.Exception e)
            {
                Debug.LogError(e.ToString());
            }

            EditorUtility.ClearProgressBar();
        }
Esempio n. 25
0
    void OnWizardCreate()
    {
        //function to execute on submit

        BillboardAsset billboard = new BillboardAsset();

        billboard.material = m_material;
        Vector4[] texCoords = new Vector4[totalImageCount];

        ushort[]  indices  = new ushort[12];
        Vector2[] vertices = new Vector2[6];

        //make texture to save at end
        var texture = new Texture2D(atlasPixelWidth, atlasPixelHeight, TextureFormat.ARGB32, false);

        //make render texture to copy to texture and assign it to camera
        //renderCamera.targetTexture = RenderTexture.GetTemporary(atlasPixelWidth / atlasColumnImageCount, atlasPixelHeight / atlasRowImageCount, 16);
        renderCamera.targetTexture = RenderTexture.GetTemporary(atlasPixelWidth, atlasPixelHeight, 16);
        var renderTex = renderCamera.targetTexture;

        renderCamera.targetTexture = renderTex;

        //reset rotation, but camera should be on local +x axis from rotating object
        toRotateCamera.transform.eulerAngles = Vector3.zero;
        int imageAt = 0;

        for (int j = 0; j < atlasRowImageCount; j++)
        {
            for (int i = 0; i < atlasColumnImageCount; i++)
            {
                //i is x, j is y
                if (imageAt < totalImageCount)
                {
                    //atla them left-right, top-bottom, 0,0 is bottom left
                    float xRatio = (float)i / atlasColumnImageCount;
                    float yRatio = (float)(atlasRowImageCount - j - 1) / atlasRowImageCount;

                    //starts at viewing from +x, and rotates camera clockwise around object, uses amount of vertices set (later down) to tell how many angles to view from
                    texCoords[imageAt].Set(xRatio, yRatio, 1f / atlasColumnImageCount, 1f / atlasRowImageCount);
                    imageAt++;

                    //set rect of where to render texture to
                    renderCamera.rect = new Rect(xRatio, yRatio, 1f / atlasColumnImageCount, 1f / atlasRowImageCount);
                    renderCamera.Render();

                    //read pixels on rec
                    //Rect rec = new Rect(xRatio * atlasPixelWidth, yRatio * atlasPixelHeight, (float)1 / atlasColumnImageCount * atlasPixelWidth, (float)1 / atlasRowImageCount * atlasPixelHeight);
                    //texture.ReadPixels(rec, i / atlasColumnImageCount * atlasPixelWidth, (atlasRowImageCount - j - 1) / atlasRowImageCount * atlasPixelHeight);

                    toRotateCamera.transform.eulerAngles += Vector3.up * (360 / totalImageCount);
                }
            }
        }
        toRotateCamera.transform.eulerAngles = Vector3.zero;
        renderCamera.rect = new Rect(0, 0, 1, 1);

        RenderTexture pastActive = RenderTexture.active;

        RenderTexture.active = renderTex;
        texture.ReadPixels(new Rect(0, 0, atlasPixelWidth, atlasPixelHeight), 0, 0);
        RenderTexture.active = pastActive;
        texture.Apply();

        //make basic box out of four trinagles, to be able to pinch the top/bottom/middle to cut extra transparent pixels
        //still not sure how this works but it connects vertices to make the mesh
        indices[0]  = 4;
        indices[1]  = 3;
        indices[2]  = 0;
        indices[3]  = 1;
        indices[4]  = 4;
        indices[5]  = 0;
        indices[6]  = 5;
        indices[7]  = 4;
        indices[8]  = 1;
        indices[9]  = 2;
        indices[10] = 5;
        indices[11] = 1;

        //set vertices positions on mesh
        vertices[0].Set(-botWidth / 2 + 0.5f, 0);
        vertices[1].Set(-midWidth / 2 + 0.5f, 0.5f);
        vertices[2].Set(-topWidth / 2 + 0.5f, 1);
        vertices[3].Set(botWidth / 2 + 0.5f, 0);
        vertices[4].Set(midWidth / 2 + 0.5f, 0.5f);
        vertices[5].Set(topWidth / 2 + 0.5f, 1);

        //assign data
        billboard.SetImageTexCoords(texCoords);
        billboard.SetIndices(indices);
        billboard.SetVertices(vertices);

        billboard.width  = objectWidth;
        billboard.height = objectHeight;
        billboard.bottom = bottomOffset;

        //save assets
        string path;
        int    nameLength = AssetDatabase.GetAssetPath(m_material).Length;

        //take out ".mat" prefix
        path = AssetDatabase.GetAssetPath(m_material).Substring(0, nameLength - 4) + ".asset";
        AssetDatabase.CreateAsset(billboard, path);
        path = AssetDatabase.GetAssetPath(m_material).Substring(0, nameLength - 4) + ".png";
        byte[] byteArray = texture.EncodeToPNG();
        System.IO.File.WriteAllBytes(path, byteArray);
        Debug.Log("BILLBOARD ASSET COMPLETED: File saved to " + path + ",\n if pressing save in editor breaks billboard, manually assign texture to material");

        if (optionalBillboardRenderer != null)
        {
            optionalBillboardRenderer.billboard = billboard;
        }

        //cleanup / qol things
        RenderTexture.ReleaseTemporary(renderTex);
        renderCamera.targetTexture = null;
        m_material.SetTexture("_MainTex", texture);

        AssetDatabase.Refresh();
    }
Esempio n. 26
0
    public void ExtractXMLTreePrototypeData()
    {
        TreeSystemPrototypeData[] data = m_ManagedPrototypes;

        for (int i = 0; i < data.Length; i++)
        {
            TreeSystemPrototypeData d = data[i];

            if (d.m_TreePrototype == null)
            {
                Log.e("Nothing set for data at index: " + i);
                continue;
            }

            // Get the protorype's billboard asset
            BillboardRenderer bill      = d.m_TreePrototype.GetComponentInChildren <BillboardRenderer>();
            BillboardAsset    billAsset = bill.billboard;

            // Set sizes
            d.m_Size = new Vector3(billAsset.width, billAsset.height, billAsset.bottom);

            // Parse the XML
            if (!d.m_TreeBillboardData && m_UseXMLData)
            {
                Debug.LogError("We are using XML data and we don't have any custom XML data! Switch 'UseXMLData' off!");
                continue;
            }

            if (m_UseXMLData)
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(d.m_TreeBillboardData.text);

                if (doc["SpeedTreeRaw"]["Billboards"]["Vertical"] == null || doc["SpeedTreeRaw"]["Billboards"]["Horizontal"] == null)
                {
                    Debug.Log("Missing tree XML data for: " + d.m_TreePrototype.name);
                }
                else
                {
                    // Should be multiple of 4
                    d.m_VertBillboardUVs = ExtractBillboards(doc["SpeedTreeRaw"]["Billboards"]["Vertical"], true).ToArray();
                    d.m_HorzBillboardUVs = ExtractBillboards(doc["SpeedTreeRaw"]["Billboards"]["Horizontal"], false).ToArray();
                }
            }
            else
            {
                // TODO: support for non-XML
                Vector4[] uvs = billAsset.GetImageTexCoords();

                // Ussualy 16
                d.m_VertBillboardUVs = new Vector2[uvs.Length * 4];
                // Just set the first UV's just to have something
                d.m_HorzBillboardUVs = new Vector2[4];

                for (int uvIdx = 0, billUv = 0; uvIdx < uvs.Length; uvIdx++, billUv += 4)
                {
                    Vector4 extract = uvs[uvIdx];

                    if (uvIdx == 0)
                    {
                        d.m_HorzBillboardUVs[0] = new Vector2(extract.x, extract.y);
                        d.m_HorzBillboardUVs[1] = new Vector2(extract.x, extract.y) + new Vector2(0, Mathf.Abs(extract.w));
                        d.m_HorzBillboardUVs[2] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, Mathf.Abs(extract.w));
                        d.m_HorzBillboardUVs[3] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, 0);
                    }

                    // We are rotated
                    if (extract.w < 0)
                    {
                        d.m_VertBillboardUVs[billUv + 0] = new Vector2(extract.x, extract.y);
                        d.m_VertBillboardUVs[billUv + 1] = new Vector2(extract.x, extract.y) + new Vector2(0, Mathf.Abs(extract.w));
                        d.m_VertBillboardUVs[billUv + 2] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, Mathf.Abs(extract.w));
                        d.m_VertBillboardUVs[billUv + 3] = new Vector2(extract.x, extract.y) + new Vector2(-extract.z, 0);
                    }
                    else
                    {
                        d.m_VertBillboardUVs[billUv + 0] = new Vector2(extract.x, extract.y);
                        d.m_VertBillboardUVs[billUv + 1] = new Vector2(extract.x, extract.y) + new Vector2(extract.z, 0);
                        d.m_VertBillboardUVs[billUv + 2] = new Vector2(extract.x, extract.y) + new Vector2(extract.z, extract.w);
                        d.m_VertBillboardUVs[billUv + 3] = new Vector2(extract.x, extract.y) + new Vector2(0, extract.w);
                    }
                }
            }

            Vector4 size = d.m_Size;
            size.w = 1;

            // Create the material with the texture references
            Material billboardMaterialBatch = new Material(m_BillboardShaderBatch);
            billboardMaterialBatch.SetTexture("_MainTex", bill.billboard.material.GetTexture("_MainTex"));
            billboardMaterialBatch.SetTexture("_BumpMap", bill.billboard.material.GetTexture("_BumpMap"));
            billboardMaterialBatch.SetVector("_Size", size);
            Material billboardMaterialMaster = new Material(m_BillboardShaderMaster);
            billboardMaterialMaster.SetTexture("_MainTex", bill.billboard.material.GetTexture("_MainTex"));
            billboardMaterialMaster.SetTexture("_BumpMap", bill.billboard.material.GetTexture("_BumpMap"));
            billboardMaterialMaster.SetVector("_Size", size);

            // Replace, don't delete
            // AssetDatabase.DeleteAsset(m_DataStorePath + "/" + d.m_TreePrototype.name + "_Mat.mat");
            AssetDatabase.CreateAsset(billboardMaterialBatch,
                                      m_DataStorePath + "/" + d.m_TreePrototype.name + "_Bill_Batch_Mat.mat");
            AssetDatabase.CreateAsset(billboardMaterialMaster,
                                      m_DataStorePath + "/" + d.m_TreePrototype.name + "_Bill_Master_Mat.mat");

            // Set the material
            d.m_BillboardBatchMaterial  = billboardMaterialBatch;
            d.m_BillboardMasterMaterial = billboardMaterialMaster;

            // Set billboard data
            TreeSystem.SetMaterialBillProps(d, d.m_BillboardBatchMaterial);
            TreeSystem.SetMaterialBillProps(d, d.m_BillboardMasterMaterial);
        }

        AssetDatabase.Refresh();
    }
Esempio n. 27
0
        private void DrawInstanced(int prototypeIndex)
        {
            GTreePrototype proto = prototypes[prototypeIndex];
            Mesh           mesh  = proto.sharedMesh;

            Material[] materials    = proto.sharedMaterials;
            int        submeshCount = prototypeCache[prototypeIndex].subMeshCount;
            int        drawCount    = Mathf.Min(submeshCount, materials.Length);

            Mesh           billboardMesh     = null;
            Material       billboardMaterial = null;
            BillboardAsset billboard         = proto.billboard;

            if (billboard != null)
            {
                billboardMesh     = GBillboardUtilities.GetMesh(billboard);
                billboardMaterial = billboard.material;
            }

            bool canDrawInstanced          = prototypeCache[prototypeIndex].canDrawInstanced;
            bool canDrawBillboardInstanced = prototypeCache[prototypeIndex].canDrawBillboardInstanced;

            batchInstanceCount          = 0;
            billboardBatchInstanceCount = 0;
            int count = instancePrototypeIndices.Length;

            for (int i = 0; i <= count; ++i)
            {
                if (i == count || batchInstanceCount == BATCH_MAX_INSTANCE_COUNT)
                {
                    if (canDrawInstanced)
                    {
                        for (int d = 0; d < drawCount; ++d)
                        {
                            Graphics.DrawMeshInstanced(
                                mesh, d, materials[d],
                                batchContainer, batchInstanceCount, null,
                                proto.shadowCastingMode, proto.receiveShadow, proto.layer,
                                camera, LightProbeUsage.BlendProbes);
                        }
                        batchInstanceCount = 0;
                    }
                }

                if (i == count || billboardBatchInstanceCount == BATCH_MAX_INSTANCE_COUNT)
                {
                    if (billboard != null && canDrawBillboardInstanced)
                    {
                        Graphics.DrawMeshInstanced(
                            billboardMesh, 0, billboardMaterial,
                            billboardBatchContainer, billboardBatchInstanceCount, null,
                            proto.billboardShadowCastingMode, proto.BillboardReceiveShadow, proto.layer,
                            camera, LightProbeUsage.BlendProbes);
                        billboardBatchInstanceCount = 0;
                    }
                }

                if (i == count)
                {
                    break;
                }

                if (instanceCullResults[i] == CULLED)
                {
                    continue;
                }
                if (instancePrototypeIndices[i] != prototypeIndex)
                {
                    continue;
                }

                if (instanceCullResults[i] == VISIBLE)
                {
                    if (canDrawInstanced)
                    {
                        batchContainer[batchInstanceCount] = instanceTransforms[i];
                        batchInstanceCount += 1;
                    }
                    else
                    {
                        for (int d = 0; d < drawCount; ++d)
                        {
                            Graphics.DrawMesh(
                                mesh, instanceTransforms[i], materials[d],
                                proto.layer, camera, d, null,
                                proto.shadowCastingMode, proto.receiveShadow,
                                null, LightProbeUsage.BlendProbes, null);
                        }
                    }
                }
                else if (instanceCullResults[i] == BILLBOARD && billboard != null)
                {
                    if (canDrawBillboardInstanced)
                    {
                        billboardBatchContainer[billboardBatchInstanceCount] = instanceTransforms[i];
                        billboardBatchInstanceCount += 1;
                    }
                    else
                    {
                        Graphics.DrawMesh(
                            billboardMesh, instanceTransforms[i], billboardMaterial,
                            proto.layer, camera, 0, null,
                            proto.billboardShadowCastingMode, proto.BillboardReceiveShadow,
                            null, LightProbeUsage.BlendProbes, null);
                    }
                }
            }
        }
 private void MakePreviewMesh(Mesh mesh, BillboardAsset billboard)
 {