/// <summary> /// Called once when the renderer can be loaded from a given shader model and mesh. /// </summary> public void OnLoad(BfshaLibrary.ShaderModel shaderModel, FMDL model, FSHP mesh, BfresMeshAsset meshAsset) { var shapeBlock = shaderModel.UniformBlocks.Values.FirstOrDefault(x => x.Type == BfshaLibrary.UniformBlock.BlockType.Shape); //Models may update the shape block outside the shader if the shape block is unused so update mesh matrix manually if (shapeBlock.Size == 0 && mesh.VertexSkinCount == 0) { mesh.UpdateVertexBuffer(true); meshAsset.UpdateVertexBuffer(); } //Assign some necessary data meshAsset.MaterialAsset = this; //Force reload from material editing mesh.ShaderReload += delegate { Console.WriteLine($"Reloading shader program {meshAsset.Name}"); this.ReloadRenderState(meshAsset); this.ReloadProgram(meshAsset); mesh.HasValidShader = this.HasValidProgram; Console.WriteLine($"Program Validation: {this.HasValidProgram}"); this.UpdateShader = true; }; ShaderModel = shaderModel; MaterialData = mesh.Material; ParentModel = model; //Load mesh function for loading the custom shader for the first time LoadMesh(meshAsset); ReloadRenderState(meshAsset); ReloadProgram(meshAsset); var bfresMaterial = (FMAT)this.MaterialData; //Remap the vertex layouts from shader model attributes if (!IsSwitch) { //GX2 shaders can be directly mapped via string and location searches Dictionary <string, string> attributeLocations = new Dictionary <string, string>(); for (int i = 0; i < shaderModel.Attributes.Count; i++) { string key = shaderModel.Attributes.GetKey(i); attributeLocations.Add(key, $"{key}_0_0"); } meshAsset.UpdateVaoAttributes(attributeLocations); } else { Dictionary <string, int> attributeLocations = new Dictionary <string, int>(); for (int i = 0; i < shaderModel.Attributes.Count; i++) { string key = shaderModel.Attributes.GetKey(i); int location = shaderModel.Attributes[i].Location; attributeLocations.Add(key, location); } meshAsset.UpdateVaoAttributes(attributeLocations); } }
/// <summary> /// Called once when the renderer can be loaded from a given shader model and mesh. /// </summary> public void OnLoad(SHARCFB sharcfb, FMDL model, FSHP mesh, BfresMeshAsset meshAsset) { ShaderModel = sharcfb.Programs.FirstOrDefault(x => x.Name == mesh.Material.ShaderModel); if (ShaderModel == null) { Console.WriteLine($"Failed to find program! {mesh.Material.ShaderModel}"); return; } //Assign some necessary data meshAsset.MaterialAsset = this; //Force reload from material editing mesh.ShaderReload += delegate { Console.WriteLine($"Reloading shader program {meshAsset.Name}"); this.ReloadRenderState(meshAsset); this.ReloadProgram(meshAsset); mesh.HasValidShader = this.HasValidProgram; Console.WriteLine($"Program Validation: {this.HasValidProgram}"); this.UpdateShader = true; }; MaterialData = mesh.Material; ParentModel = model; //Load mesh function for loading the custom shader for the first time LoadMesh(meshAsset); ReloadRenderState(meshAsset); ReloadProgram(meshAsset); var gx2ShaderVertex = (GX2VertexShader)ShaderModel.GetGX2VertexShader(BinaryIndex); var bfresMaterial = (FMAT)this.MaterialData; //Remap the vertex layouts from shader model attributes Dictionary <string, string> attributeLocations = new Dictionary <string, string>(); for (int i = 0; i < gx2ShaderVertex.Attributes.Count; i++) { var symbol = ShaderModel.AttributeVariables.symbols.FirstOrDefault( x => x.Name == gx2ShaderVertex.Attributes[i].Name); if (symbol == null) { continue; } var attribVar = gx2ShaderVertex.Attributes[i]; var arrayCount = Math.Max(1, attribVar.Count); var streamCount = attribVar.GetStreamCount(); if (arrayCount > 1 || streamCount > 1) { throw new Exception("Multiple attribute streams and variable counts not supported!"); } attributeLocations.Add(symbol.SymbolName, $"{symbol.Name}_0_0"); } meshAsset.UpdateVaoAttributes(attributeLocations); }