private void GenerateCortanaRMT2Tag(List <int> options, Stream cacheStream, Dictionary <ResourceLocation, Stream> resourceStreams, out CachedTagInstance rmt2Instance, out RenderMethodTemplate rmt2) { string template_name = $@"shaders\cortana_templates\_{string.Join("_", options)}"; rmt2 = new RenderMethodTemplate(); var rmt2_group = TagGroup.Instances[new TagStructureInfo(typeof(RenderMethodTemplate)).GroupTag]; rmt2Instance = CacheContext.TagCache.AllocateTag(rmt2_group); var pixl = new PixelShader(); var pixlGroup = TagGroup.Instances[new TagStructureInfo(typeof(PixelShader)).GroupTag]; CachedTagInstance newPIXLInstance = CacheContext.TagCache.AllocateTag(pixlGroup); var vtsh = new VertexShader(); var vtshGroup = TagGroup.Instances[new TagStructureInfo(typeof(VertexShader)).GroupTag]; CachedTagInstance newVTSHInstance = CacheContext.TagCache.AllocateTag(vtshGroup); rmt2.PixelShader = newPIXLInstance; rmt2.VertexShader = newVTSHInstance; rmt2.DrawModeBitmask |= RenderMethodTemplate.ShaderModeBitmask.Active_Camo; rmt2.VectorArguments = new List <RenderMethodTemplate.ShaderArgument>(); rmt2.IntegerArguments = new List <RenderMethodTemplate.ShaderArgument>(); rmt2.BooleanArguments = new List <RenderMethodTemplate.ShaderArgument>(); rmt2.SamplerArguments = new List <RenderMethodTemplate.ShaderArgument>(); rmt2.ArgumentMappings = new List <RenderMethodTemplate.ArgumentMapping>(); rmt2.RegisterOffsets = new List <RenderMethodTemplate.DrawModeRegisterOffsetBlock>(); pixl.Shaders = new List <PixelShaderBlock>(); pixl.DrawModes = new List <ShaderDrawMode>(); rmt2.DrawModes = new List <RenderMethodTemplate.DrawMode>(); foreach (RenderMethodTemplate.ShaderMode mode in Enum.GetValues(typeof(RenderMethodTemplate.ShaderMode))) { var pixelShaderDrawmode = new ShaderDrawMode(); pixl.DrawModes.Add(pixelShaderDrawmode); var rmt2Drawmode = new RenderMethodTemplate.DrawMode(); rmt2.DrawModes.Add(rmt2Drawmode); if (!HaloShaderGenerator.HaloShaderGenerator.IsShaderSuppored( HaloShaderGenerator.Enums.ShaderType.Cortana, (HaloShaderGenerator.Enums.ShaderStage)(int) mode )) { continue; } rmt2Drawmode.Offset = (ushort)rmt2.RegisterOffsets.Count(); rmt2Drawmode.Count = 1; var shader_gen_result = HaloShaderGenerator.HaloShaderGenerator.GenerateShaderCortana(HaloShaderGenerator.Enums.ShaderStage.Active_Camo); var pixelShaderBlock = GeneratePixelShaderBlock(CacheContext, shader_gen_result); pixelShaderDrawmode.Count = 1; pixelShaderDrawmode.Offset = (byte)pixl.Shaders.Count; pixl.Shaders.Add(pixelShaderBlock); var registerOffsets = new RenderMethodTemplate.DrawModeRegisterOffsetBlock(); rmt2.RegisterOffsets.Add(registerOffsets); registerOffsets.RenderMethodExternArguments_Offset = (ushort)rmt2.ArgumentMappings.Count; var srcRenderMethodExternArguments = shader_gen_result.Registers.Where(r => r.Scope == HaloShaderGenerator.ShaderGeneratorResult.ShaderRegister.ShaderRegisterScope.RenderMethodExtern_Arguments); foreach (var src_arg in srcRenderMethodExternArguments) { var argument_mapping = new RenderMethodTemplate.ArgumentMapping { RegisterIndex = (ushort)src_arg.Register }; foreach (var _enum in Enum.GetValues(typeof(RenderMethodTemplate.RenderMethodExtern))) { if (_enum.ToString().ToLower() == src_arg.Name) { argument_mapping.ArgumentIndex = (byte)_enum; break; } } rmt2.ArgumentMappings.Add(argument_mapping); registerOffsets.RenderMethodExternArguments_Count++; } registerOffsets.SamplerArguments_Offset = (ushort)rmt2.ArgumentMappings.Count; var srcSamplerArguments = shader_gen_result.Registers.Where(r => r.Scope == HaloShaderGenerator.ShaderGeneratorResult.ShaderRegister.ShaderRegisterScope.TextureSampler_Arguments); foreach (var samplerRegister in srcSamplerArguments) { var argumentMapping = new RenderMethodTemplate.ArgumentMapping { RegisterIndex = (ushort)samplerRegister.Register, ArgumentIndex = (byte)registerOffsets.SamplerArguments_Count++ }; rmt2.ArgumentMappings.Add(argumentMapping); var shaderArgument = new RenderMethodTemplate.ShaderArgument { Name = CacheContext.GetStringId(samplerRegister.Name) }; rmt2.SamplerArguments.Add(shaderArgument); } registerOffsets.VectorArguments_Offset = (ushort)rmt2.ArgumentMappings.Count; // add xform args foreach (var samplerRegister in srcSamplerArguments) { int index = GetArgumentIndex(samplerRegister.Name, rmt2.VectorArguments); HaloShaderGenerator.ShaderGeneratorResult.ShaderRegister xformRegister = null; foreach (var register in shader_gen_result.Registers) { if (register.Name == $"{samplerRegister.Name}_xform") { xformRegister = register; break; } } if (xformRegister == null) { continue; } var argumentMapping = new RenderMethodTemplate.ArgumentMapping { RegisterIndex = (ushort)xformRegister.Register, ArgumentIndex = (byte)(index != -1 ? index : rmt2.VectorArguments.Count) }; rmt2.ArgumentMappings.Add(argumentMapping); var shaderArgument = new RenderMethodTemplate.ShaderArgument { Name = CacheContext.GetStringId(samplerRegister.Name) }; rmt2.VectorArguments.Add(shaderArgument); registerOffsets.VectorArguments_Count++; } var srcVectorArguments = shader_gen_result.Registers.Where(r => r.Scope == HaloShaderGenerator.ShaderGeneratorResult.ShaderRegister.ShaderRegisterScope.Vector_Arguments); foreach (var vectorRegister in srcVectorArguments) { if (vectorRegister.IsXFormArgument) { continue; // we've already added these } var argumentMapping = new RenderMethodTemplate.ArgumentMapping { RegisterIndex = (ushort)vectorRegister.Register, ArgumentIndex = (byte)rmt2.VectorArguments.Count }; rmt2.ArgumentMappings.Add(argumentMapping); var shaderArgument = new RenderMethodTemplate.ShaderArgument { Name = CacheContext.GetStringId(vectorRegister.Name) }; rmt2.VectorArguments.Add(shaderArgument); registerOffsets.VectorArguments_Count++; } } newPIXLInstance.Name = template_name; CacheContext.Serialize(new TagSerializationContext(cacheStream, CacheContext, newPIXLInstance), pixl); newVTSHInstance.Name = template_name; CacheContext.Serialize(new TagSerializationContext(cacheStream, CacheContext, newVTSHInstance), vtsh); rmt2Instance.Name = template_name; CacheContext.Serialize(new TagSerializationContext(cacheStream, CacheContext, rmt2Instance), rmt2); CacheContext.SaveTagNames(); }
private RenderMethod.ShaderProperty.Argument ProcessArgument( RenderMethodTemplate.ShaderArgument vectorArgument, List <RenderMethod.AnimationPropertiesBlock> shaderFunctions, List <RenderMethodOption.OptionBlock> templateOptions, ShaderCortana shaderCortana) { RenderMethod.ShaderProperty.Argument shaderArgument = new RenderMethod.ShaderProperty.Argument(); var name = vectorArgument.Name; var nameStr = CacheContext.GetString(name); foreach (var importData in shaderCortana.ImportData) { if (importData.Name.Index != name.Index) { continue; } var argument_data = importData.AnimationProperties.Count > 0 ? importData.AnimationProperties[0].Function.Data : null; if (argument_data != null) { var unknown0A = BitConverter.ToUInt16(argument_data, 0); var unknown0B = BitConverter.ToUInt16(argument_data, 2); var unknown1 = BitConverter.ToUInt32(argument_data, 20); var unknown2 = BitConverter.ToUInt32(argument_data, 24); var unknown3 = BitConverter.ToUInt32(argument_data, 28); switch (importData.Type) { case RenderMethodOption.OptionBlock.OptionDataType.Sampler: shaderArgument.Arg0 = BitConverter.ToSingle(argument_data, 4); shaderArgument.Arg1 = BitConverter.ToSingle(argument_data, 8); shaderArgument.Arg2 = BitConverter.ToSingle(argument_data, 12); shaderArgument.Arg3 = BitConverter.ToSingle(argument_data, 16); break; case RenderMethodOption.OptionBlock.OptionDataType.Float4: shaderArgument.Arg0 = BitConverter.ToSingle(argument_data, 4); shaderArgument.Arg1 = BitConverter.ToSingle(argument_data, 8); shaderArgument.Arg2 = BitConverter.ToSingle(argument_data, 12); shaderArgument.Arg3 = BitConverter.ToSingle(argument_data, 16); break; case RenderMethodOption.OptionBlock.OptionDataType.Float: shaderArgument.Arg0 = BitConverter.ToSingle(argument_data, 4); shaderArgument.Arg1 = BitConverter.ToSingle(argument_data, 4); shaderArgument.Arg2 = BitConverter.ToSingle(argument_data, 4); shaderArgument.Arg3 = BitConverter.ToSingle(argument_data, 4); break; case RenderMethodOption.OptionBlock.OptionDataType.IntegerColor: { var iblue = argument_data[4]; var igreen = argument_data[5]; var ired = argument_data[6]; var iunusedAlpha = argument_data[7]; var blue = (float)iblue / 255.0f; var green = (float)igreen / 255.0f; var red = (float)ired / 255.0f; var unusedAlpha = (float)iunusedAlpha / 255.0f; var ialpha = argument_data[16]; var alpha = (float)ialpha / 255.0f; shaderArgument.Arg0 = red; shaderArgument.Arg1 = green; shaderArgument.Arg2 = blue; shaderArgument.Arg3 = alpha; } break; default: throw new NotImplementedException(); } } else { // default arguments switch (importData.Type) { case RenderMethodOption.OptionBlock.OptionDataType.Sampler: shaderArgument.Arg0 = 1.0f; shaderArgument.Arg1 = 1.0f; shaderArgument.Arg2 = 0.0f; shaderArgument.Arg3 = 0.0f; break; } } for (int functionIndex = 1; functionIndex < importData.AnimationProperties.Count; functionIndex++) { shaderFunctions.Add(importData.AnimationProperties[functionIndex]); } goto datafound; } foreach (var deafult_option in templateOptions) { if (deafult_option.Name.Index != name.Index) { continue; } //TODO: Figure these bad boys out, I think its all just defaults but we should just // throw a warning if they're not part of the RMDF // (Don't throw warnings if we're using a custom shader RMDF goto datafound; } //TODO: Maybe we can do better than this, ie. custom shaders Console.WriteLine($"WARNING: RMCT Conversion couldn't find a argument for {nameStr}"); datafound: return(shaderArgument); }