public override void LoadMesh(BfresMeshAsset mesh) { base.LoadMesh(mesh); if (ShaderFileState == ShaderState.Global) { mesh.Shape.UpdateVertexBuffer(true); mesh.UpdateVertexBuffer(); } }
public override void LoadMesh(BfresMeshAsset mesh) { int offset = mesh.Attributes.Sum(x => x.Stride); for (int i = 0; i < 3; i++) { if (mesh.Attributes.Any(x => x.name == $"inst{i}")) { continue; } VaoAttribute vaoAtt = new VaoAttribute(); vaoAtt.vertexAttributeName = $"inst{i}"; vaoAtt.name = $"inst{i}"; vaoAtt.ElementCount = 4; vaoAtt.Offset = offset; vaoAtt.Type = VertexAttribPointerType.Float; mesh.Attributes.Add(vaoAtt); offset += vaoAtt.Stride; } var tangentAttribute = mesh.Attributes.FirstOrDefault(x => x.name == "_t0"); if (tangentAttribute != null) { tangentAttribute.name = "tangent"; } //Tangents need to be assigned manually for some reason. if (!mesh.Attributes.Any(x => x.name == "tangent")) { VaoAttribute vaoAtt = new VaoAttribute(); vaoAtt.vertexAttributeName = $"_t0"; vaoAtt.name = $"tangent"; vaoAtt.ElementCount = 4; vaoAtt.Offset = offset; vaoAtt.Type = VertexAttribPointerType.Float; mesh.Attributes.Add(vaoAtt); offset += vaoAtt.Stride; } mesh.UpdateVertexBuffer(); }
public void RenderMesh(GLContext control, BfresMeshAsset mesh, int stage = 0) { if (!mesh.InFrustum) { return; } if (mesh.UpdateVertexData) { mesh.UpdateVertexBuffer(); } if (Runtime.DebugRendering != Runtime.DebugRender.Default) { DrawDebug(control, mesh); return; } else if (mesh.MaterialAsset is ShaderRenderBase) { DrawCustomShaderRender(control, mesh, stage); return; } else //Draw default if not using game shader rendering. { if (!control.IsShaderActive(BfresRender.DefaultShader)) { control.CurrentShader = BfresRender.DefaultShader; } var mtxMdl = this.ParentRender.Transform.TransformMatrix; var mtxCam = control.Camera.ViewProjectionMatrix; control.CurrentShader.SetMatrix4x4("mtxMdl", ref mtxMdl); control.CurrentShader.SetMatrix4x4("mtxCam", ref mtxCam); mesh.MaterialAsset.Render(control, control.CurrentShader, mesh); DrawSolidColorMesh(control.CurrentShader, mesh); } }
/// <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); } }