Beispiel #1
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 1 || args.Count > 2)
            {
                return(false);
            }

            if (args[0] == "new")
            {
                return(MatchShaderNew(args[1]));
            }
            else if (args.Count == 2)
            {
                return(false);
            }

            RenderMethodTemplate bmRmt2 = new RenderMethodTemplate();
            CachedTag            bmRmt2Instance;

            using (var blamStream = BlamCache.OpenCacheRead())
            {
                if (BlamCache.TryGetCachedTag(args[0], out bmRmt2Instance))
                {
                    bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance);
                }
                else
                {
                    return(false);
                }
            }

            List <string> bmMaps = new List <string>();
            List <string> bmArgs = new List <string>();

            // Get a simple list of H3 bitmaps and arguments names
            foreach (var a in bmRmt2.TextureParameterNames)
            {
                bmMaps.Add(BlamCache.StringTable.GetString(a.Name));
            }
            foreach (var a in bmRmt2.RealParameterNames)
            {
                bmArgs.Add(BlamCache.StringTable.GetString(a.Name));
            }

            string result = null;

            using (var cacheStream = Cache.OpenCacheRead())
            {
                ShaderMatcher Matcher = new ShaderMatcher();
                Matcher.Init(cacheStream, Cache, BlamCache);

                // Find a HO equivalent rmt2
                var edRmt2Instance = Matcher.FixRmt2Reference(cacheStream, bmRmt2Instance.Name, bmRmt2Instance, bmRmt2, bmMaps, bmArgs);
                result = edRmt2Instance.Name;
            }

            Console.WriteLine($"Blam template \"{bmRmt2Instance.Name}.rmt2\"\n matched with \"{result}.rmt2\".");
            return(true);
        }
        private RenderMethod ConvertRenderMethod(Stream cacheStream, Dictionary <ResourceLocation, Stream> resourceStreams, RenderMethod finalRm, string blamTagName)
        {
            // Verify that the ShaderMatcher is ready to use
            if (!Matcher.IsInitialized())
            {
                Matcher.Init(cacheStream, CacheContext, BlamCache);
            }

            // Set flags
            Matcher.SetMS30Flag(cacheStream, FlagIsSet(PortingFlags.Ms30));

            // finalRm.ShaderProperties[0].ShaderMaps are all ported bitmaps
            // finalRm.BaseRenderMethod is a H3 tag
            // finalRm.ShaderProperties[0].Template is a H3 tag

            // TODO hardcode shader values such as argument changes for specific shaders
            var bmMaps = new List <string>();
            var bmArgs = new List <string>();
            var edMaps = new List <string>();
            var edArgs = new List <string>();

            // Reset rmt2 preset
            var pRmt2 = 0;

            // Make a template of ShaderProperty, with the correct bitmaps and arguments counts.
            var newShaderProperty = new RenderMethod.ShaderProperty
            {
                ShaderMaps = new List <RenderMethod.ShaderProperty.ShaderMap>(),
                Arguments  = new List <RenderMethod.ShaderProperty.Argument>()
            };

            // Get a simple list of bitmaps and arguments names
            var bmRmt2Instance = BlamCache.IndexItems.Find(x => x.ID == finalRm.ShaderProperties[0].Template.Index);
            var blamContext    = new CacheSerializationContext(ref BlamCache, bmRmt2Instance);
            var bmRmt2         = BlamCache.Deserializer.Deserialize <RenderMethodTemplate>(blamContext);

            // Get a simple list of H3 bitmaps and arguments names
            foreach (var a in bmRmt2.SamplerArguments)
            {
                bmMaps.Add(BlamCache.Strings.GetItemByID(a.Name.Index));
            }
            foreach (var a in bmRmt2.VectorArguments)
            {
                bmArgs.Add(BlamCache.Strings.GetItemByID(a.Name.Index));
            }

            // Find a HO equivalent rmt2
            var edRmt2Instance = Matcher.FixRmt2Reference(cacheStream, blamTagName, bmRmt2Instance, bmRmt2, bmMaps, bmArgs);

            if (edRmt2Instance == null)
            {
                return(CacheContext.Deserialize <Shader>(cacheStream, CacheContext.GetTag <Shader>(@"shaders\invalid")));
            }

            var edRmt2Tagname = edRmt2Instance.Name ?? $"0x{edRmt2Instance.Index:X4}";

            // pRmsh pRmt2 now potentially have a new value
            if (pRmt2 != 0)
            {
                if (CacheContext.TagCache.Index.Contains(pRmt2))
                {
                    var a = CacheContext.GetTag(pRmt2);
                    if (a != null)
                    {
                        edRmt2Instance = a;
                    }
                }
            }

            var edRmt2 = CacheContext.Deserialize <RenderMethodTemplate>(cacheStream, edRmt2Instance);

            foreach (var a in edRmt2.SamplerArguments)
            {
                edMaps.Add(CacheContext.StringIdCache.GetString(a.Name));
            }
            foreach (var a in edRmt2.VectorArguments)
            {
                edArgs.Add(CacheContext.StringIdCache.GetString(a.Name));
            }

            // The bitmaps are default textures.
            // Arguments are probably default values. I took the values that appeared the most frequently, assuming they are the default value.
            foreach (var a in edMaps)
            {
                var newBitmap = Matcher.GetDefaultBitmapTag(a);

                if (!CacheContext.TagCache.Index.Contains(pRmt2))
                {
                    newBitmap = @"shaders\default_bitmaps\bitmaps\default_detail"; // would only happen for removed shaders
                }
                CachedTagInstance bitmap = null;

                try
                {
                    bitmap = CacheContext.GetTag <Bitmap>(newBitmap);
                }
                catch
                {
                    bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag($"{newBitmap}.bitm")[0]);
                }

                newShaderProperty.ShaderMaps.Add(
                    new RenderMethod.ShaderProperty.ShaderMap
                {
                    Bitmap = bitmap
                });
            }

            foreach (var a in edArgs)
            {
                newShaderProperty.Arguments.Add(Matcher.DefaultArgumentsValues(a));
            }

            // Reorder blam bitmaps to match the HO rmt2 order
            // Reorder blam arguments to match the HO rmt2 order
            foreach (var eM in edMaps)
            {
                foreach (var bM in bmMaps)
                {
                    if (eM == bM)
                    {
                        newShaderProperty.ShaderMaps[edMaps.IndexOf(eM)] = finalRm.ShaderProperties[0].ShaderMaps[bmMaps.IndexOf(bM)];
                    }
                }
            }

            foreach (var eA in edArgs)
            {
                foreach (var bA in bmArgs)
                {
                    if (eA == bA)
                    {
                        newShaderProperty.Arguments[edArgs.IndexOf(eA)] = finalRm.ShaderProperties[0].Arguments[bmArgs.IndexOf(bA)];
                    }
                }
            }

            // Remove some tagblocks
            // finalRm.Unknown = new List<RenderMethod.UnknownBlock>(); // hopefully not used; this gives rmt2's name. They correspond to the first tagblocks in rmdf, they tell what the shader does
            finalRm.ImportData = new List <RenderMethod.ImportDatum>(); // most likely not used
            finalRm.ShaderProperties[0].Template   = edRmt2Instance;
            finalRm.ShaderProperties[0].ShaderMaps = newShaderProperty.ShaderMaps;
            finalRm.ShaderProperties[0].Arguments  = newShaderProperty.Arguments;

            Matcher.FixRmdfTagRef(finalRm);

            FixAnimationProperties(cacheStream, resourceStreams, BlamCache, CacheContext, finalRm, edRmt2, bmRmt2, blamTagName);

            // Fix any null bitmaps, caused by bitm port failure
            foreach (var a in finalRm.ShaderProperties[0].ShaderMaps)
            {
                if (a.Bitmap != null)
                {
                    continue;
                }

                var defaultBitmap = Matcher.GetDefaultBitmapTag(edMaps[finalRm.ShaderProperties[0].ShaderMaps.IndexOf(a)]);

                try
                {
                    a.Bitmap = CacheContext.GetTag <Bitmap>(defaultBitmap);
                }
                catch
                {
                    a.Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag($"{defaultBitmap}.bitm")[0]);
                }
            }

            if (Matcher.RmhgUnknownTemplates.Contains(edRmt2Instance.Name))
            {
                if (finalRm.ShaderProperties[0].Unknown.Count == 0)
                {
                    finalRm.ShaderProperties[0].Unknown = new List <RenderMethod.ShaderProperty.UnknownBlock1>
                    {
                        new RenderMethod.ShaderProperty.UnknownBlock1
                        {
                            Unknown = 1
                        }
                    }
                }
            }
            ;

            switch (blamTagName)
            {
            case @"levels\dlc\chillout\shaders\chillout_flood_godrays" when finalRm is ShaderHalogram:
            {
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    if (CacheContext.GetString(edRmt2.SamplerArguments[i].Name) == "overlay_map")
                    {
                        finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\dlc\chillout\bitmaps\chillout_flood_godrays.bitmap")[0]);
                        break;
                    }
                }

                // Fixup arguments
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    switch (CacheContext.GetString(templateArg.Name))
                    {
                    case "overlay_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 0f, 0f };
                        break;

                    case "overlay_tint":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.3764706f, 0.7254902f, 0.9215687f, 1f };
                        break;

                    case "overlay_intensity":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1.25f, 1.25f, 1.25f, 1.25f };
                        break;
                    }
                }
                break;
            }

            case @"levels\dlc\chillout\shaders\chillout_invis_godrays" when finalRm is ShaderHalogram:
            {
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    if (CacheContext.GetString(edRmt2.SamplerArguments[i].Name) == "overlay_map")
                    {
                        finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\dlc\chillout\bitmaps\chillout_invis_godrays.bitmap")[0]);
                        break;
                    }
                }

                // Fixup arguments
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    switch (CacheContext.GetString(templateArg.Name))
                    {
                    case "overlay_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 0f, 0f };
                        break;

                    case "overlay_tint":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.3058824f, 0.7098039f, 0.937255f, 1f };
                        break;

                    case "overlay_intensity":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 1f, 1f };
                        break;
                    }
                }
                break;
            }

            case @"levels\solo\020_base\lights\light_volume_hatlight" when finalRm is ShaderHalogram:
            {
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    if (CacheContext.GetString(edRmt2.SamplerArguments[i].Name) == "overlay_map")
                    {
                        finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\solo\020_base\bitmaps\light_volume_hatlight.bitmap")[0]);
                        break;
                    }
                }

                // Fixup arguments
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    switch (CacheContext.GetString(templateArg.Name))
                    {
                    case "overlay_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 2f, 1f, 0f, 0f };
                        break;

                    case "overlay_tint":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.9960785f, 1f, 0.8039216f, 1f };
                        break;

                    case "overlay_intensity":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 1f, 1f };
                        break;
                    }
                }
                break;
            }

            case @"objects\vehicles\ghost\shaders\ghost_dash_zcam" when finalRm is ShaderHalogram:
            case @"objects\weapons\rifle\sniper_rifle\shaders\scope_alpha" when finalRm is ShaderHalogram:
                finalRm.InputVariable = TagTool.Tags.TagMapping.VariableTypeValue.ParticleRandom1;
                finalRm.RangeVariable = TagTool.Tags.TagMapping.VariableTypeValue.ParticleAge;
                break;

            case @"levels\dlc\armory\shaders\concrete_floor_smooth" when finalRm is Shader:
            {
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    if (CacheContext.GetString(edRmt2.SamplerArguments[i].Name) == "bump_map")
                    {
                        finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\dlc\armory\bitmaps\concrete_floor_bump.bitmap")[0]);
                        break;
                    }
                }
                break;
            }

            case @"levels\dlc\sidewinder\shaders\side_tree_branch_snow" when finalRm is Shader:
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    if (CacheContext.GetString(templateArg.Name) == "env_tint_color")
                    {
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0f, 0f, 0f, 0f };
                        break;
                    }
                }
                break;

            case @"levels\multi\isolation\sky\shaders\skydome" when finalRm is Shader:
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    if (CacheContext.GetString(templateArg.Name) == "albedo_color")
                    {
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.447059f, 0.376471f, 0.898039f, 1.0f };
                        break;
                    }
                }
                break;

            case @"levels\multi\snowbound\shaders\cov_grey_icy" when finalRm is Shader:
            {
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    switch (CacheContext.GetString(edRmt2.SamplerArguments[i].Name))
                    {
                    case "base_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\for_metal_greytech_dif.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "detail_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\for_metal_greytech_icy.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "bump_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\for_metal_greytech_platebump.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "bump_detail_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\for_metal_greytech_bump.bitmap")[0]);
                        }
                        catch { }
                        break;
                    }
                }

                // Fixup arguments
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    switch (CacheContext.GetString(templateArg.Name))
                    {
                    case "base_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 0f, 0f };
                        break;

                    case "detail_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1.5f, 1.5f, 0f, 0f };
                        break;

                    case "albedo_color":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.554902f, 0.5588236f, 0.5921569f, 1f };
                        break;

                    case "bump_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 0f, 0f };
                        break;

                    case "bump_detail_map":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 2f, 2f, 0f, 0f };
                        break;

                    case "diffuse_coefficient":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.4f, 0.4f, 0.4f, 0.4f };
                        break;

                    case "specular_coefficient":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 1f, 1f };
                        break;

                    case "roughness":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.2f, 0.2f, 0.2f, 0.2f };
                        break;

                    case "analytical_specular_contribution":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.2f, 0.2f, 0.2f, 0.2f };
                        break;

                    case "area_specular_contribution":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.1f, 0.1f, 0.1f, 0.1f };
                        break;

                    case "environment_map_specular_contribution":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.15f, 0.15f, 0.15f, 0.15f };
                        break;

                    case "specular_tint":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0.8431373f, 0.8470589f, 0.8117648f, 1f };
                        break;
                    }
                }
                break;
            }

            case @"levels\multi\snowbound\shaders\rock_cliffs" when finalRm is Shader:
            case @"levels\multi\snowbound\shaders\rock_rocky" when finalRm is Shader:
            case @"levels\multi\snowbound\shaders\rock_rocky_icy" when finalRm is Shader:
            {
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    switch (CacheContext.GetString(edRmt2.SamplerArguments[i].Name))
                    {
                    case "base_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_horiz.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "detail_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_granite_detail.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "detail_map2":
                        try
                        {
                            switch (blamTagName)
                            {
                            case @"levels\multi\snowbound\shaders\rock_rocky_icy":
                                finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_icy_blend.bitmap")[0]);
                                break;

                            default:
                                finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_cliff_dif.bitmap")[0]);
                                break;
                            }
                        }
                        catch { }
                        break;

                    case "bump_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_horiz_bump.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "bump_detail_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_granite_bump.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "height_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"levels\multi\snowbound\bitmaps\rock_horiz_parallax.bitmap")[0]);
                        }
                        catch { }
                        break;

                    case "environment_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = ConvertTag(cacheStream, resourceStreams, ParseLegacyTag(@"shaders\default_bitmaps\bitmaps\color_white.bitmap")[0]);
                        }
                        catch { }
                        break;
                    }
                }

                // Fixup arguments
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    switch (CacheContext.GetString(templateArg.Name))
                    {
                    case "base_map":
                        switch (blamTagName)
                        {
                        case @"levels\multi\snowbound\shaders\rock_cliffs":
                            finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 16f, 2f, 0f, 0.5f };
                            break;
                        }
                        break;

                    case "detail_map":
                        switch (blamTagName)
                        {
                        case @"levels\multi\snowbound\shaders\rock_cliffs":
                        case @"levels\multi\snowbound\shaders\rock_rocky":
                            finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 320f, 20f, 0f, 0f };
                            break;
                        }
                        break;

                    case "detail_map2":
                        switch (blamTagName)
                        {
                        case @"levels\multi\snowbound\shaders\rock_cliffs":
                            finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1f, 1f, 0f, 0f };
                            break;
                        }
                        break;

                    case "bump_detail_map":
                        switch (blamTagName)
                        {
                        case @"levels\multi\snowbound\shaders\rock_cliffs":
                        case @"levels\multi\snowbound\shaders\rock_rocky":
                            finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 320f, 20f, 0f, 0f };
                            break;
                        }
                        break;

                    case "diffuse_coefficient":
                        switch (blamTagName)
                        {
                        case @"levels\multi\snowbound\shaders\rock_rocky_icy":
                            finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 1.2f, 1.2f, 1.2f, 1.2f };
                            break;
                        }
                        break;
                    }
                }
                break;
            }

            case @"levels\multi\snowbound\shaders\cov_metalplates_icy" when finalRm is Shader:
                // Fixup bitmaps
                for (var i = 0; i < edRmt2.SamplerArguments.Count; i++)
                {
                    switch (CacheContext.GetString(edRmt2.SamplerArguments[i].Name))
                    {
                    case "detail_map":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = CacheContext.GetTag <Bitmap>(@"levels\multi\snowbound\bitmaps\for_metal_greytech_icy4");
                        }
                        catch { }
                        break;

                    case "detail_map2":
                        try
                        {
                            finalRm.ShaderProperties[0].ShaderMaps[i].Bitmap = CacheContext.GetTag <Bitmap>(@"levels\multi\snowbound\bitmaps\for_metal_greytech_icy3");
                        }
                        catch { }
                        break;
                    }
                }
                break;

            case @"levels\multi\snowbound\shaders\invis_col_glass" when finalRm is Shader:
                // Fixup arguments
                for (var i = 0; i < edRmt2.VectorArguments.Count; i++)
                {
                    var templateArg = edRmt2.VectorArguments[i];

                    switch (CacheContext.GetString(templateArg.Name))
                    {
                    case "albedo_color":
                        finalRm.ShaderProperties[0].Arguments[i].Values = new float[] { 0f, 0f, 0f, 0f };
                        break;
                    }
                }
                break;
            }

            return(finalRm);
        }