public FMAT(BFRES bfres, FMDL fmdl, Model model, Material material) { Init(); ParentFile = bfres; Material = material; ParentModel = model; ParentBfresModel = fmdl; Reload(material); }
/// <summary> /// Loads the material renderer for the first time. /// </summary> /// <returns></returns> public override void TryLoadShader(BFRES bfres, FMDL fmdl, FSHP mesh, BfresMeshAsset meshAsset) { var sharcfb = TryLoadShaderArchive(bfres, mesh.Material.ShaderArchive, mesh.Material.ShaderModel); if (sharcfb == null) { return; } OnLoad(sharcfb, fmdl, mesh, meshAsset); }
public FSHP(ResFile resFile, FSKL skeleton, FMDL model, Shape shape) { ParentFile = resFile; ParentModel = model; Shape = shape; ParentSkeleton = skeleton; BoneIndex = shape.BoneIndex; VertexBuffer = model.Model.VertexBuffers[shape.VertexBufferIndex]; VertexSkinCount = shape.VertexSkinCount; Name = shape.Name; UpdateVertexBuffer(); UpdatePolygonGroups(); }
public ModelFolder(BFRES bfres, ResFile resFile, ResDict <Model> resDict) { foreach (Model model in resDict.Values) { var node = new BfresNodeBase(model.Name); node.Icon = "/Images/Model.png"; AddChild(node); var fmdl = new FMDL(node, bfres, model); node.Tag = fmdl; bfres.Models.Add(fmdl); node.AddChild(new BfresNodeBase("Meshes")); node.AddChild(new MaterialFolder("Materials")); node.AddChild(new BfresNodeBase("Skeleton")); foreach (FSHP mesh in fmdl.Meshes) { var meshNode = new BfresNodeBase(mesh.Name) { Tag = mesh, Icon = "/Images/Mesh.png" }; mesh.ParentNode = meshNode; mesh.MeshSelected = (o, s) => { meshNode.IsSelected = (bool)o; }; node.Children[0].AddChild(meshNode); } foreach (FMAT mat in fmdl.Materials) { var matNode = new BfresNodeBase(mat.Name) { Tag = mat, Icon = ((FMAT)mat).Icon, }; mat.ParentNode = matNode; node.Children[1].AddChild(matNode); } foreach (var bone in ((FSKL)fmdl.Skeleton).CreateBoneHierarchy()) { node.Children[2].AddChild(bone); } } }
/// <summary> /// Loads the material renderer for the first time. /// </summary> /// <returns></returns> public override void TryLoadShader(BFRES bfres, FMDL fmdl, FSHP mesh, BfresMeshAsset meshAsset) { var bfsha = TryLoadShaderArchive(bfres, mesh.Material.ShaderArchive, mesh.Material.ShaderModel); if (bfsha == null) { return; } var shaderModel = bfsha.ShaderModels.Values.FirstOrDefault(x => x.Name == mesh.Material.ShaderModel); if (shaderModel != null) { OnLoad(shaderModel, fmdl, mesh, meshAsset); } }
static void LoadBoneSelector(FMDL model, FSHP shape) { string selecteBone = model.Skeleton.Bones[shape.BoneIndex].Name; if (ImGui.BeginCombo("Bone", selecteBone)) { for (int i = 0; i < model.Skeleton.Bones.Count; i++) { bool isSelected = model.Skeleton.Bones[i].Name == selecteBone; if (ImGui.Selectable(model.Skeleton.Bones[i].Name, isSelected)) { shape.BoneIndex = (ushort)i; } if (isSelected) { ImGui.SetItemDefaultFocus(); } } ImGui.EndCombo(); } }
static void LoadMaterialSelector(FMDL model, FSHP shape) { string selectedMaterial = model.Materials[shape.Shape.MaterialIndex].Name; if (ImGui.BeginCombo("Material", selectedMaterial)) { for (int i = 0; i < model.Materials.Count; i++) { bool isSelected = model.Materials[i].Name == selectedMaterial; if (ImGui.Selectable(model.Materials[i].Name, isSelected)) { shape.Shape.MaterialIndex = (ushort)i; shape.Material = (FMAT)model.Materials[i]; } if (isSelected) { ImGui.SetItemDefaultFocus(); } } ImGui.EndCombo(); } }
/// <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); }
/// <summary> /// Loads the material renderer for the first time. /// </summary> public virtual void TryLoadShader(BFRES bfres, FMDL fmdl, FSHP mesh, BfresMeshAsset meshAsset) { }
public BfresModelAsset(BFRES bfres, BfresRender render, FMDL model) { ParentRender = render; ModelData = model; Name = model.Name; List <Vector3> positons = new List <Vector3>(); foreach (FSHP mesh in model.Meshes) { //Create a mesh asset for rendering onto var meshAsset = new BfresMeshAsset(mesh); Meshes.Add(meshAsset); foreach (var customRender in BfshaRenders) { var materialRender = (ShaderRenderBase)Activator.CreateInstance(customRender); if (materialRender.UseRenderer( mesh.Material, mesh.Material.ShaderArchive, mesh.Material.ShaderModel)) { materialRender.TryLoadShader(bfres, ResModel, mesh, meshAsset); break; } } //Check for the GX2 shader decompiler as needed for Wii U games if (System.IO.File.Exists("GFD\\gx2shader-decompiler.exe")) { foreach (var customRender in SharcfbRenders) { var materialRender = (SharcFBRenderer)Activator.CreateInstance(customRender); if (materialRender.UseRenderer( mesh.Material, mesh.Material.ShaderArchive, mesh.Material.ShaderModel)) { materialRender.TryLoadShader(bfres, ResModel, mesh, meshAsset); break; } } } mesh.Material.MaterialAsset = (BfresMaterialAsset)meshAsset.MaterialAsset; ((BfresMaterialAsset)meshAsset.MaterialAsset).ParentRenderer = render; ((BfresMaterialAsset)meshAsset.MaterialAsset).ParentModel = this.ResModel; //Calculate total boundings for (int i = 0; i < mesh.Vertices.Count; i++) { positons.Add(mesh.Vertices[i].Position); } } SkeletonRenderer = new SkeletonRenderer(model.Skeleton); //Calculate the total bounding sphere BoundingSphere = GLFrameworkEngine.Utils.BoundingSphereGenerator.GenerateBoundingSphere(positons); positons.Clear(); }