Example #1
0
        private static void SetMaterialPopups(Material material, LW_VertexBuffer buffer)
        {
            LW_Canvas canvas = buffer.canvas;

            material.SetFloat("_BlendMode", (int)canvas.blendMode);
            material.SetFloat("_FeatureMode", (int)canvas.featureMode);
            material.SetFloat("_StrokeDrawMode", (int)canvas.strokeDrawMode);
            material.SetFloat("_StrokeScaleMode", (int)canvas.strokeScaleMode);
            material.SetFloat("_JoinsAndCapsMode", (int)canvas.joinsAndCapsMode);
            material.SetFloat("_GradientsMode", (int)canvas.gradientsMode);
            material.SetFloat("_AntiAliasingMode", (int)canvas.antiAliasingMode);
        }
Example #2
0
 private static void RemoveBufferFromDict(LW_VertexBuffer buffer)
 {
     foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict)
     {
         LW_MaterialBuffer materialBuffer = kvp.Value;
         if (materialBuffer.vertexBuffers.Contains(buffer))
         {
             int index = materialBuffer.vertexBuffers.IndexOf(buffer);
             if (!materialBuffer.emptyIndices.Contains(index))
             {
                 materialBuffer.emptyIndices.Push(index);
             }
         }
     }
 }
Example #3
0
 private static void RemoveGraphicFromDict(LW_Graphic graphic)
 {
     foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict)
     {
         LW_MaterialBuffer materialBuffer = kvp.Value;
         for (int i = 0; i < materialBuffer.vertexBuffers.Count; i++)
         {
             LW_VertexBuffer buffer = materialBuffer.vertexBuffers[i];
             if (buffer.graphic == graphic)
             {
                 if (!materialBuffer.emptyIndices.Contains(i))
                 {
                     materialBuffer.emptyIndices.Push(i);
                 }
             }
         }
     }
 }
Example #4
0
        private static int  GetRenderQueue(LW_VertexBuffer buffer)
        {
            switch (buffer.canvas.blendMode)
            {
            case BlendMode.Opaque:
                return(2000);

            case BlendMode.AlphaTest:
                return(2450);

            case BlendMode.AlphaBlend:
                return(3000);

            case BlendMode.UI:
                return(3000);
            }
            return(2000);
        }
Example #5
0
        public static void Clean()
        {
            s_LastMaterial = null;

            if (s_DirtyTextures.Count > 0)
            {
                while (s_DirtyTextures.Count > 0)
                {
                    s_DirtyTextures.Pop().Apply();
                }
            }

            if (s_MaterialPoolDirty)
            {
                                #if UNITY_EDITOR || DEVELOPMENT
                if (s_DebugMaterialPool)
                {
                    Debug.Log("Clean MaterialPool");
                }
                                #endif

                s_ToRemoveFromDict.Clear();

                foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict)
                {
                    Material               poolMat        = kvp.Key;
                    LW_MaterialBuffer      materialBuffer = kvp.Value;
                    List <LW_VertexBuffer> vertexBuffers  = materialBuffer.vertexBuffers;
                    Stack <int>            emptyIndices   = materialBuffer.emptyIndices;

                    if (poolMat == null || vertexBuffers.Count == 0 || emptyIndices.Count == vertexBuffers.Count)
                    {
                        s_ToRemoveFromDict.Add(poolMat);
                    }
                    else
                    {
                        bool removeMaterialFromDict = true;

                        for (int i = 0; i < vertexBuffers.Count; i++)
                        {
                            if (emptyIndices.Contains(i))
                            {
                                continue;
                            }

                            LW_VertexBuffer buffer = vertexBuffers[i];
                            if (buffer.isValid && MaterialMatchesBuffer(poolMat, buffer) && poolMat.renderQueue == buffer.renderQueue)
                            {
                                removeMaterialFromDict = false;
                            }
                            else
                            {
                                                                #if UNITY_EDITOR || DEVELOPMENT
                                if (s_DebugMaterialPool)
                                {
                                    Debug.Log("Cleaning MaterialPool: vBuffer: " + i);
                                }
                                                                #endif

                                emptyIndices.Push(i);
                            }
                        }

                        if (removeMaterialFromDict)
                        {
                            s_ToRemoveFromDict.Add(poolMat);
                        }
                    }
                }

                for (int i = 0; i < s_ToRemoveFromDict.Count; i++)
                {
                    if (s_MaterialDict.ContainsKey(s_ToRemoveFromDict[i]))
                    {
                        s_MaterialDict.Remove(s_ToRemoveFromDict[i]);
                    }
                }

                s_MaterialPoolDirty = false;
            }
        }
Example #6
0
        private static bool MaterialMatchesBuffer(Material material, LW_VertexBuffer buffer)
        {
            LW_PaintStyle style  = buffer.style as LW_PaintStyle;
            LW_Canvas     canvas = buffer.canvas;

            // Get Custom Material
            Material customMaterial    = style.material != null ? style.material : (canvas.material != null ? canvas.material : null);
            bool     isLineWorksShader = customMaterial == null || customMaterial.shader.name.StartsWith("LineWorks");

            // Get Buffer Textures
            Texture bufferTexture  = style.mainTexture != null ? style.mainTexture : canvas.mainTexture != null ? canvas.mainTexture : null;
            Vector2 bufferUvOffset = style.mainTexture != null ? style.uvOffset : Vector2.zero;
            Vector2 bufferUvTiling = style.mainTexture != null ? style.uvTiling : Vector2.one;

            // Get Material Textures
            Texture materialTexture  = isLineWorksShader ? material.GetTexture("_MainTex") : null;
            Vector2 materialUvOffset = isLineWorksShader ? material.GetTextureOffset("_MainTex") : Vector2.zero;
            Vector2 materialUvTiling = isLineWorksShader ? material.GetTextureScale("_MainTex") : Vector2.one;

            Texture bufferCapTexture  = null;
            Texture bufferJoinTexture = null;

            if (style is LW_Stroke)
            {
                LW_Stroke stroke = style as LW_Stroke;
                bufferCapTexture  = stroke.linecap == Linecap.Texture ? stroke.capTexture : null;
                bufferJoinTexture = stroke.linejoin == Linejoin.Texture ? stroke.joinTexture : null;
            }
            Texture materialCapTexture  = isLineWorksShader && material.HasProperty("_CapTex") ? material.GetTexture("_CapTex") : null;
            Texture materialJoinTexture = isLineWorksShader && material.HasProperty("_JoinTex") ? material.GetTexture("_JoinTex") : null;
            // Check for Match

            bool isMatch =
                customMaterial != null && customMaterial == material ||
                (
                    customMaterial == null &&
                    bufferCapTexture == materialCapTexture &&
                    bufferJoinTexture == materialJoinTexture &&
                    bufferTexture == materialTexture &&
                    bufferUvOffset == materialUvOffset &&
                    bufferUvTiling == materialUvTiling &&
                    (
                        (canvas.blendMode == BlendMode.Opaque && !material.IsKeywordEnabled("_BLEND_ALPHATEST") && !material.IsKeywordEnabled("_BLEND_ALPHABLEND") && !material.IsKeywordEnabled("_BLEND_UI") && !material.IsKeywordEnabled("_BLEND_ADDITIVESOFT")) ||
                        (canvas.blendMode == BlendMode.AlphaTest && material.IsKeywordEnabled("_BLEND_ALPHATEST")) ||
                        (canvas.blendMode == BlendMode.AlphaBlend && material.IsKeywordEnabled("_BLEND_ALPHABLEND")) ||
                        (canvas.blendMode == BlendMode.UI && material.IsKeywordEnabled("_BLEND_UI")) ||
                        (canvas.blendMode == BlendMode.AdditiveSoft && material.IsKeywordEnabled("_BLEND_ADDITIVESOFT"))
                    ) &&
                    (
                        (
                            (canvas.featureMode == FeatureMode.Advanced && material.IsKeywordEnabled("_ADVANCED_ON")) ||
                            (canvas.featureMode == FeatureMode.Simple && !material.IsKeywordEnabled("_ADVANCED_ON"))
                        ) && (
                            (canvas.strokeDrawMode == StrokeDrawMode.Draw3D && material.IsKeywordEnabled("_STROKE_3D")) ||
                            ((canvas.featureMode == FeatureMode.Simple || canvas.strokeDrawMode == StrokeDrawMode.Draw2D) && !material.IsKeywordEnabled("_STROKE_3D"))
                            ) && (
                            ((canvas.featureMode == FeatureMode.Simple || canvas.strokeScaleMode == StrokeScaleMode.Scaled) && !material.IsKeywordEnabled("_STROKE_UNSCALED") && !material.IsKeywordEnabled("_STROKE_SCREENSPACE")) ||
                            (canvas.strokeScaleMode == StrokeScaleMode.Unscaled && material.IsKeywordEnabled("_STROKE_UNSCALED")) ||
                            (canvas.strokeScaleMode == StrokeScaleMode.ScreenSpace && material.IsKeywordEnabled("_STROKE_SCREENSPACE"))
                            ) && (
                            (canvas.joinsAndCapsMode == JoinsAndCapsMode.Shader && material.IsKeywordEnabled("_JOINSCAPS_ON")) ||
                            ((canvas.featureMode == FeatureMode.Simple || canvas.joinsAndCapsMode != JoinsAndCapsMode.Shader) && !material.IsKeywordEnabled("_JOINSCAPS_ON"))
                            ) && (
                            (canvas.gradientsMode == GradientsMode.Shader && material.IsKeywordEnabled("_GRADIENTS_ON")) ||
                            ((canvas.featureMode == FeatureMode.Simple || canvas.gradientsMode != GradientsMode.Shader) && !material.IsKeywordEnabled("_GRADIENTS_ON"))
                            ) && (
                            (canvas.antiAliasingMode == AntiAliasingMode.On && material.IsKeywordEnabled("_ANTIALIAS_ON")) ||
                            ((canvas.featureMode == FeatureMode.Simple || canvas.antiAliasingMode != AntiAliasingMode.On) && !material.IsKeywordEnabled("_ANTIALIAS_ON"))
                            )
                    )
                );

            /*
             * Debug.Log(material.name + " == " + buffer.style.name +
             *      "("
             + (customMaterial != null)
             + " && " + (customMaterial == material)
             + ")"
             + " || ("
             + (customMaterial == null)
             + " && " + (bufferTexture == materialTexture)
             + " && " + (bufferUvOffset == materialUvOffset)
             + " && " + (bufferUvTiling == materialUvTiling)
             + " && ("
             + (canvas.blendMode == BlendMode.Opaque && !material.IsKeywordEnabled("_BLEND_ALPHATEST") && !material.IsKeywordEnabled("_BLEND_ALPHABLEND") && !material.IsKeywordEnabled("_BLEND_UI") && !material.IsKeywordEnabled("_BLEND_ADDITIVESOFT"))
             + " || " + (canvas.blendMode == BlendMode.AlphaTest && material.IsKeywordEnabled("_BLEND_ALPHATEST"))
             + " || " + (canvas.blendMode == BlendMode.AlphaBlend && material.IsKeywordEnabled("_BLEND_ALPHABLEND"))
             + " || " + (canvas.blendMode == BlendMode.UI && material.IsKeywordEnabled("_BLEND_UI"))
             + " || " + (canvas.blendMode == BlendMode.AdditiveSoft && material.IsKeywordEnabled("_BLEND_ADDITIVESOFT"))
             + ") && ("
             +      //+ !isAdvancedShader
             +      //+ " || (("
             + (canvas.featureMode == FeatureMode.Advanced && material.IsKeywordEnabled("_ADVANCED_ON"))
             + " || " + (canvas.featureMode == FeatureMode.Simple && !material.IsKeywordEnabled("_ADVANCED_ON"))
             + ") && ("
             + (canvas.strokeDrawMode == StrokeDrawMode.Draw3D && material.IsKeywordEnabled("_STROKE_3D"))
             + " || " + ((canvas.featureMode == FeatureMode.Simple || canvas.strokeDrawMode == StrokeDrawMode.Draw2D) && !material.IsKeywordEnabled("_STROKE_3D"))
             + ") && ("
             + ((canvas.featureMode == FeatureMode.Simple || canvas.strokeScaleMode == StrokeScaleMode.Scaled) && !material.IsKeywordEnabled("_STROKE_UNSCALED") && !material.IsKeywordEnabled("_STROKE_SCREENSPACE"))
             + " || " + (canvas.strokeScaleMode == StrokeScaleMode.Unscaled && material.IsKeywordEnabled("_STROKE_UNSCALED"))
             + " || " + (canvas.strokeScaleMode == StrokeScaleMode.ScreenSpace && material.IsKeywordEnabled("_STROKE_SCREENSPACE"))
             + ") && ("
             + (canvas.joinsAndCapsMode == JoinsAndCapsMode.Shader && material.IsKeywordEnabled("_JOINSCAPS_ON"))
             + " || " + ((canvas.featureMode == FeatureMode.Simple || canvas.joinsAndCapsMode != JoinsAndCapsMode.Shader) && !material.IsKeywordEnabled("_JOINSCAPS_ON"))
             + ") && ("
             + (canvas.gradientsMode == GradientsMode.Shader && material.IsKeywordEnabled("_GRADIENTS_ON"))
             + " || " + ((canvas.featureMode == FeatureMode.Simple || canvas.gradientsMode != GradientsMode.Shader) &&  !material.IsKeywordEnabled("_GRADIENTS_ON"))
             + ") && ("
             + (canvas.antiAliasingMode == AntiAliasingMode.On && material.IsKeywordEnabled("_ANTIALIAS_ON"))
             + " || " + ((canvas.featureMode == FeatureMode.Simple || canvas.antiAliasingMode != AntiAliasingMode.On) && !material.IsKeywordEnabled("_ANTIALIAS_ON"))
             + ")))"
             + );
             */
            return(isMatch);
        }
Example #7
0
        private static void RebuildStyleData(Material material, LW_MaterialBuffer materialBuffer, bool forceRebuild = false)
        {
            //Debug.Log("RebuildStyleData material: " + material.name);

            if (!(material != null && materialBuffer != null && materialBuffer.vertexBuffers != null && materialBuffer.isAdvancedShader && (forceRebuild || materialBuffer.isDirty)))
            {
                return;
            }

            List <LW_VertexBuffer> vertexBuffers = materialBuffer.vertexBuffers;
            Stack <int>            emptyIndices  = materialBuffer.emptyIndices;

            // Setup
            int       width          = s_GradientDataLength + s_GradientPrecision;
            int       height         = vertexBuffers.Count;
            bool      hasChanged     = false;
            bool      rebuildAllRows = forceRebuild;
            Texture2D styleData      = material.GetTexture("_StyleData") as Texture2D;

            // Resizing StyleData
            if (styleData != null)
            {
                if (styleData.height < height)
                {
                    int     oldHeight = styleData.height;
                    int     oldWidth  = styleData.width;
                    Color[] pixels    = styleData.GetPixels();
                    styleData.Resize(width, height, TextureFormat.RGBAFloat, false);
                    styleData.SetPixels(0, 0, oldWidth, oldHeight, pixels, 0);
                    material.SetVector("_StyleDataSize", new Vector4(width, height, s_GradientDataLength, s_GradientPrecision));
                    hasChanged = true;
                }
                else if (styleData.height > height)
                {
                    styleData = null;
                }
            }

            // Creating StyleData
            if (styleData == null)
            {
                styleData            = new Texture2D(width, height, TextureFormat.RGBAFloat, false);
                styleData.hideFlags  = HideFlags.DontSave;
                styleData.filterMode = FilterMode.Bilinear;
                styleData.wrapMode   = TextureWrapMode.Clamp;
                styleData.anisoLevel = 0;
                material.SetTexture("_StyleData", styleData);
                material.SetVector("_StyleDataSize", new Vector4(width, height, s_GradientDataLength, s_GradientPrecision));
                hasChanged     = true;
                rebuildAllRows = true;
            }

            // Updating StyleData
            for (int i = 0; i < vertexBuffers.Count; i++)
            {
                int index = i;

                LW_VertexBuffer buffer = vertexBuffers[i];


                if (buffer.isEmpty || emptyIndices.Contains(i) || (buffer.styleDataIndex == index && !buffer.style.isDirty && !rebuildAllRows))
                {
                    continue;
                }

                //Debug.Log("buffer.styleDataIndex = " + index);

                hasChanged            = true;
                buffer.styleDataIndex = index;

                //LW_Graphic graphic = buffer.graphic;
                //LW_Canvas canvas = buffer.canvas;
                LW_PaintStyle style = buffer.style as LW_PaintStyle;

                float boundsMin = Mathf.Min(buffer.bounds.min.x, buffer.bounds.min.y);
                float boundsMax = Mathf.Max(buffer.bounds.max.x, buffer.bounds.max.y);

                float strokeJustification   = -1;
                float strokeWidth           = 0;
                float strokeLength          = 0;
                float screenSpaceMiterLimit = 0;
                float caps  = -1;
                float joins = -1;

                // Vertex Data
                if (style is LW_Stroke)
                {
                    LW_Stroke stroke = style as LW_Stroke;
                    strokeJustification   = ((int)stroke.justification - 1);
                    strokeWidth           = stroke.MaxWidth();
                    strokeLength          = buffer.totalLength;
                    screenSpaceMiterLimit = stroke.screenSpace ? stroke.miterLimit : -stroke.miterLimit;
                    caps  = (int)stroke.linecap;
                    joins = (int)stroke.linejoin;
                }

                if (style is LW_Fill)
                {
                    strokeWidth  = buffer.bounds.size.y;
                    strokeLength = buffer.bounds.size.x;
                    caps         = (int)Linecap.Round;
                    joins        = (int)Linejoin.Round;
                }

                // Fragment Data
                Matrix4x4 gradTransform = style.gradientUnits == GradientUnits.objectBoundingBox ?
                                          style.BoundsToLocalMatrix(buffer.bounds) * style.gradientTransform * style.LocalToBoundsMatrix(buffer.bounds) :
                                          style.gradientTransform;
                Vector2 start             = gradTransform.MultiplyPoint(style.gradientStart);
                Vector2 end               = gradTransform.MultiplyPoint(style.gradientEnd);
                Vector2 gradientDirection = end - start;
                float   gradAngle         = Mathf.Atan2(gradientDirection.x, gradientDirection.y);
                float   gradScale         = gradientDirection.magnitude;

                styleData.SetPixel(0, index, new Color(screenSpaceMiterLimit, strokeJustification, strokeWidth, strokeLength));
                styleData.SetPixel(1, index, new Color((int)style.uvMode, (int)style.gradientUnits, boundsMin, boundsMax));
                styleData.SetPixel(2, index, new Color(start.x, start.y, (int)style.gradientSpreadMethod, (int)style.paintMode));
                styleData.SetPixel(3, index, new Color(gradAngle, gradScale, caps, joins));

                for (int p = 0; p < s_GradientPrecision + 1; p++)
                {
                    float percentage = (float)p / (float)s_GradientPrecision;
                    Color color      = style.ColorAtPercentage(percentage);
                    styleData.SetPixel(s_GradientDataLength + p, i, color);
                }
            }

            if (hasChanged)
            {
                if (!s_DirtyTextures.Contains(styleData))
                {
                    s_DirtyTextures.Push(styleData);
                }
            }

            materialBuffer.isDirty = false;
        }
Example #8
0
        private static void MatchMaterialToBuffer(Material material, LW_VertexBuffer buffer)
        {
            // Setup
            LW_PaintStyle style  = buffer.style as LW_PaintStyle;
            LW_Canvas     canvas = buffer.canvas;

            Material customMaterial    = style.material != null ? style.material : (canvas.material != null ? canvas.material : null);
            bool     isLineWorksShader = customMaterial == null || customMaterial.shader.name.StartsWith("LineWorks");
            bool     isCustomMaterial  = customMaterial != null;

            // Update LineWorks Material to Match Buffer
            if (isLineWorksShader && !isCustomMaterial)
            {
                Shader shader = defaultShader;
                if (material.shader != shader)
                {
                    material.shader = shader;
                }

                // this was from a previous version where the width and color property were directly applied to the material.
                //if (style is LW_Stroke) {
                //	LW_Stroke stroke = style as LW_Stroke;
                //	if (material.GetFloat("_Width") != stroke.widthMultiplier) material.SetFloat("_Width", stroke.widthMultiplier);
                //}
                //if (material.GetColor("_Color") != style.color) material.SetColor("_Color", style.color);

                Texture2D texture  = style.mainTexture != null ? style.mainTexture : canvas.mainTexture != null ? canvas.mainTexture : null;
                Vector2   uvOffset = style.mainTexture != null ? style.uvOffset : Vector2.zero;
                Vector2   uvTiling = style.mainTexture != null ? style.uvTiling : Vector2.one;

                if (material.GetTexture("_MainTex") != texture)
                {
                    material.SetTexture("_MainTex", texture);
                }
                if (material.GetTextureOffset("_MainTex") != uvOffset)
                {
                    material.SetTextureOffset("_MainTex", uvOffset);
                }
                if (material.GetTextureScale("_MainTex") != uvTiling)
                {
                    material.SetTextureScale("_MainTex", uvTiling);
                }

                if (style is LW_Stroke)
                {
                    LW_Stroke stroke = style as LW_Stroke;
                    if (stroke.linecap == Linecap.Texture && stroke.capTexture != null && material.GetTexture("_CapTex") != stroke.capTexture)
                    {
                        material.SetTexture("_CapTex", stroke.capTexture);
                    }
                    if (stroke.linejoin == Linejoin.Texture && stroke.joinTexture != null && material.GetTexture("_JoinTex") != stroke.joinTexture)
                    {
                        material.SetTexture("_JoinTex", stroke.joinTexture);
                    }
                }

                SetMaterialPopups(material, buffer);
                SetMaterialKeywords(material);
            }

            material.renderQueue = buffer.renderQueue;

            //if (isAdvancedShader) RebuildStyleData(material, s_MaterialDict[material]);
        }
Example #9
0
        public static Material Get(LW_VertexBuffer buffer)
        {
            if (!buffer.isValid)
            {
                return(null);
            }

            // Setup
            Material material = null;

            // Check for Custom Materials
            LW_PaintStyle style = buffer.style as LW_PaintStyle;

            if (style.material != null)
            {
                material           = style.material;
                buffer.renderQueue = material.renderQueue;
            }
            else if (buffer.canvas.material != null)
            {
                material           = buffer.canvas.material;
                buffer.renderQueue = material.renderQueue;
            }

            // Check Last Material and Update RenderQue If needed.
            if (material == null)
            {
                buffer.renderQueue = GetRenderQueue(buffer);

                if (s_LastMaterial != null && buffer.renderQueue < s_LastMaterial.renderQueue)
                {
                    buffer.renderQueue = s_LastMaterial.renderQueue + 1;
                }

                if (s_LastMaterial != null && MaterialMatchesBuffer(s_LastMaterial, buffer))
                {
                    material = s_LastMaterial;
                }
            }

            // Check Material Dictionary for Match
            if (material == null)
            {
                foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict)
                {
                    if (kvp.Key == null)
                    {
                        continue;
                    }

                    Material poolMat = kvp.Key;

                    if (MaterialMatchesBuffer(poolMat, buffer) && poolMat.renderQueue == buffer.renderQueue)
                    {
                        material = kvp.Key;
                        break;
                    }
                }
            }

            // Check Material Dictionary for Unused Material
            if (material == null)
            {
                foreach (KeyValuePair <Material, LW_MaterialBuffer> kvp in s_MaterialDict)
                {
                    if (kvp.Key == null)
                    {
                        continue;
                    }

                    Material poolMat = kvp.Key;
                    List <LW_VertexBuffer> bufferList = kvp.Value.vertexBuffers;

                    if (bufferList == null || bufferList.Count == 0 || (bufferList.Count == 1 && bufferList[0] == buffer))
                    {
                        material = poolMat;
                        MatchMaterialToBuffer(material, buffer);
                        break;
                    }
                }
            }

            // Create New Material
            if (material == null)
            {
                Shader shader = defaultShader;
                if (shader == null)
                {
                    Debug.Log("LineWorks Shader: \"LineWorks/Default\" is Missing. Make sure required LineWorks Shader is included in the scene or in a Resources Folder. Using UI/Default shader but Vector Graphics may not display correctly.");
                    shader = Shader.Find("UI/Default");
                }
                material           = new Material(shader);
                material.hideFlags = HideFlags.DontSave;
                material.name      = string.Format("LineWorks Material {0}", s_MaterialNameCount++);
                MatchMaterialToBuffer(material, buffer);
            }

            //MatchMaterialToBuffer(material, buffer);

            // Add Material to Dictionary if needed.
            LW_MaterialBuffer materialBuffer = null;

            if (s_MaterialDict.ContainsKey(material))
            {
                materialBuffer = s_MaterialDict[material];
                List <LW_VertexBuffer> vertexBuffers = materialBuffer.vertexBuffers;
                Stack <int>            emptyIndices  = materialBuffer.emptyIndices;

                if (!vertexBuffers.Contains(buffer))
                {
                    if (emptyIndices.Count > 0)
                    {
                        vertexBuffers[emptyIndices.Pop()] = buffer;
                    }
                    else
                    {
                        vertexBuffers.Add(buffer);
                    }
                    buffer.styleDataIndex = -1;
                }
            }
            else
            {
                materialBuffer = new LW_MaterialBuffer();
                materialBuffer.vertexBuffers.Add(buffer);
                s_MaterialDict.Add(material, materialBuffer);
                buffer.styleDataIndex = -1;
            }

            materialBuffer.isDirty           = !buffer.isValid || buffer.style.isDirty || buffer.styleDataIndex == -1;
            materialBuffer.isLineWorksShader = material.shader.name.StartsWith("LineWorks");
            materialBuffer.isAdvancedShader  = materialBuffer.isLineWorksShader && material.IsKeywordEnabled("_ADVANCED_ON");

            // Finish
            s_LastMaterial = material;

            return(material);
        }