From bdf2b625e9b8130f6f3e99c9f823d898002638a3 Mon Sep 17 00:00:00 2001 From: KillzXGaming Date: Tue, 14 Jan 2020 21:15:37 -0500 Subject: [PATCH] Start to impliment a base for custom bfres renderers --- .../FileFormats/BFRES/BFRES.cs | 18 +- .../BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs | 2 +- .../BFRES/Bfres Structs/SubFiles/FMDL/FSKL.cs | 3 +- .../File_Format_Library.csproj | 5 +- .../GL/BFRES/BFRESRenderBase.cs | 255 ++++++ .../GL/{ => BFRES}/BFRES_Render.cs | 378 +-------- .../GL/BFRES/RedPro/RedPro_Renderer.cs | 795 ++++++++++++++++++ .../GL/BFRES/RedPro/ShaderProgram.cs | 37 + File_Format_Library/GUI/BFRES/BfresEditor.cs | 2 +- File_Format_Library/Main.cs | 4 +- .../OpenGL/GLShaderGeneric.cs | 59 ++ Toolbox/Shader/Bfres/BFRES_utility.frag | 7 +- 12 files changed, 1178 insertions(+), 387 deletions(-) create mode 100644 File_Format_Library/GL/BFRES/BFRESRenderBase.cs rename File_Format_Library/GL/{ => BFRES}/BFRES_Render.cs (76%) create mode 100644 File_Format_Library/GL/BFRES/RedPro/RedPro_Renderer.cs create mode 100644 File_Format_Library/GL/BFRES/RedPro/ShaderProgram.cs diff --git a/File_Format_Library/FileFormats/BFRES/BFRES.cs b/File_Format_Library/FileFormats/BFRES/BFRES.cs index 75799503..61f06e93 100644 --- a/File_Format_Library/FileFormats/BFRES/BFRES.cs +++ b/File_Format_Library/FileFormats/BFRES/BFRES.cs @@ -758,7 +758,8 @@ namespace FirstPlugin return editor; } - public BFRESRender BFRESRender; + + public BFRESRenderBase BFRESRender; public void Load(System.IO.Stream stream) { CanSave = true; @@ -781,7 +782,6 @@ namespace FirstPlugin BFRESRender = new BFRESRender(); - DrawableContainer.Drawables.Add(BFRESRender); DrawableContainer.Name = FileName; BFRESRender.ModelTransform = MarioCostumeEditor.SetTransform(FileName); @@ -796,6 +796,20 @@ namespace FirstPlugin LoadFile(new Syroot.NintenTools.NSW.Bfres.ResFile(stream)); } + if (resFileU != null) { + if (resFileU.VersioFull == "3,0,0,1") + { + //Todo check for valid sharc files to parse as programs via materials to map + + // Console.WriteLine("RedPro_Renderer!"); + /* BFRESRender = new RedPro_Renderer(); + BFRESRender.ModelTransform = Matrix4.Identity; + BFRESRender.ResFileNode = this;*/ + } + } + + DrawableContainer.Drawables.Add(BFRESRender); + var Models = GetModels(); if (Models != null) { diff --git a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs index 751c47f3..a6e4a269 100644 --- a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs +++ b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FMAT.cs @@ -203,7 +203,7 @@ namespace Bfres.Structs ((BFRES)Parent.Parent.Parent.Parent).BFRESRender.UpdateSingleMaterialTextureMaps(this); } - public BFRESRender GetRenderer() + public BFRESRenderBase GetRenderer() { return ((BFRES)Parent.Parent.Parent.Parent).BFRESRender; } diff --git a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSKL.cs b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSKL.cs index a75879db..6e433599 100644 --- a/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSKL.cs +++ b/File_Format_Library/FileFormats/BFRES/Bfres Structs/SubFiles/FMDL/FSKL.cs @@ -186,10 +186,11 @@ namespace Bfres.Structs public override string ImportFilter => FileFilters.GetFilter(typeof(BfresBone)); public override string ReplaceFilter => FileFilters.GetFilter(typeof(FSKL)); - public BFRESRender GetRenderer() + public BFRESRenderBase GetRenderer() { return ((FMDL)Parent.Parent).GetRenderer(); } + public fsklNode() { Text = "Skeleton"; diff --git a/File_Format_Library/File_Format_Library.csproj b/File_Format_Library/File_Format_Library.csproj index 2d92a466..ba62b6d0 100644 --- a/File_Format_Library/File_Format_Library.csproj +++ b/File_Format_Library/File_Format_Library.csproj @@ -396,7 +396,7 @@ - + @@ -406,6 +406,8 @@ + + UserControl @@ -1392,6 +1394,7 @@ + UserControl diff --git a/File_Format_Library/GL/BFRES/BFRESRenderBase.cs b/File_Format_Library/GL/BFRES/BFRESRenderBase.cs new file mode 100644 index 00000000..6438e4b8 --- /dev/null +++ b/File_Format_Library/GL/BFRES/BFRESRenderBase.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library; +using Toolbox.Library.Rendering; +using GL_EditorFramework.GL_Core; +using GL_EditorFramework.Interfaces; +using Bfres.Structs; +using OpenTK.Graphics.OpenGL; +using OpenTK; + +namespace FirstPlugin +{ + public class BFRESRenderBase : AbstractGlDrawable, IMeshContainer + { + public Matrix4 ModelTransform = Matrix4.Identity; + + // gl buffer objects + internal int vbo_position; + internal int ibo_elements; + + public BFRES ResFileNode; + + public List Meshes + { + get + { + List meshes = new List(); + for (int m = 0; m < models.Count; m++) + { + for (int s = 0; s < models[m].shapes.Count; s++) + meshes.Add(models[m].shapes[s]); + } + return meshes; + } + } + + private List _models = new List(); + public List models + { + get + { + return _models; + } + } + + internal bool Disposing = false; + + public void UpdateModelList() + { + _models.Clear(); + foreach (var node in ResFileNode.Nodes) + { + if (node is BFRESGroupNode && + ((BFRESGroupNode)node).Type == BRESGroupType.Models) + { + foreach (FMDL mdl in ((BFRESGroupNode)node).Nodes) + _models.Add(mdl); + } + } + } + + private void TransformBones() + { + for (int mdl = 0; mdl < models.Count; mdl++) + { + for (int b = 0; b < models[mdl].Skeleton.bones.Count; b++) + { + models[mdl].Skeleton.bones[b].ModelMatrix = ModelTransform; + } + } + } + + internal void GenerateBuffers() + { + GL.GenBuffers(1, out vbo_position); + GL.GenBuffers(1, out ibo_elements); + + TransformBones(); + + UpdateVertexData(); + UpdateTextureMaps(); + } + + public void Destroy() + { + bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; + + if (!buffersWereInitialized) + return; + + GL.DeleteBuffer(vbo_position); + GL.DeleteBuffer(ibo_elements); + + Disposing = true; + } + + public virtual void UpdateVertexData() + { + + } + + public virtual void UpdateTextureMaps() + { + if (!Runtime.OpenTKInitialized) + return; + + foreach (BNTX bntx in PluginRuntime.bntxContainers) + { + if (!bntx.AllGLInitialized) + { + foreach (var tex in bntx.Textures) + { + if (tex.Value.RenderableTex != null && !tex.Value.RenderableTex.GLInitialized) + tex.Value.LoadOpenGLTexture(); + } + } + } + foreach (BFRESGroupNode ftexCont in PluginRuntime.ftexContainers) + { + foreach (var tex in ftexCont.ResourceNodes) + { + if (!((FTEX)tex.Value).RenderableTex.GLInitialized) + ((FTEX)tex.Value).LoadOpenGLTexture(); + } + } + } + + + public void UpdateSingleMaterialTextureMaps(FMAT mat) + { + if (!Runtime.OpenTKInitialized) + return; + + foreach (BNTX bntx in PluginRuntime.bntxContainers) + { + foreach (var t in mat.TextureMaps) + { + if (bntx.Textures.ContainsKey(t.Name)) + { + if (!bntx.Textures[t.Name].RenderableTex.GLInitialized) + bntx.Textures[t.Name].LoadOpenGLTexture(); + } + } + } + + LibraryGUI.UpdateViewport(); + } + + public override void Prepare(GL_ControlModern control) + { + } + + public override void Prepare(GL_ControlLegacy control) + { + } + + public override void Draw(GL_ControlLegacy control, Pass pass) + { + if (Disposing || pass == Pass.TRANSPARENT) return; + + bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; + if (!buffersWereInitialized) + GenerateBuffers(); + + if (!Runtime.OpenTKInitialized) + return; + + Matrix4 mvpMat = control.ModelMatrix * control.CameraMatrix * control.ProjectionMatrix; + + Matrix4 invertedCamera = Matrix4.Identity; + if (invertedCamera.Determinant != 0) + invertedCamera = mvpMat.Inverted(); + + Vector3 lightDirection = new Vector3(0f, 0f, -1f); + Vector3 difLightDirection = Vector3.TransformNormal(lightDirection, invertedCamera).Normalized(); + + GL.Enable(EnableCap.Texture2D); + GL.Enable(EnableCap.DepthTest); + + foreach (var model in models) + { + foreach (var shape in model.shapes) + { + if (Runtime.RenderModels && model.Checked && shape.Checked) + { + var mat = shape.GetMaterial(); + + List faces = shape.lodMeshes[shape.DisplayLODIndex].getDisplayFace(); + + GL.Begin(PrimitiveType.Triangles); + foreach (var index in faces) + { + Vertex vert = shape.vertices[index]; + float normal = Vector3.Dot(difLightDirection, vert.nrm) * 0.5f + 0.5f; + GL.Color3(new Vector3(normal)); + GL.TexCoord2(vert.uv0); + GL.Vertex3(vert.pos); + } + GL.End(); + } + } + } + + GL.Enable(EnableCap.Texture2D); + } + + public void CenterCamera(GL_ControlBase control) + { + if (!Runtime.FrameCamera) + return; + + var spheres = new List(); + for (int mdl = 0; mdl < models.Count; mdl++) + { + for (int shp = 0; shp < models[mdl].shapes.Count; shp++) + { + var vertexPositions = models[mdl].shapes[shp].vertices.Select(x => x.pos).Distinct(); + spheres.Add(control.GenerateBoundingSphere(vertexPositions)); + } + } + + control.FrameSelect(spheres); + } + + public static Vector4 GenerateBoundingSphere(IEnumerable boundingSpheres) + { + // The initial max/min should be the first point. + Vector3 min = boundingSpheres.FirstOrDefault().Xyz - new Vector3(boundingSpheres.FirstOrDefault().W); + Vector3 max = boundingSpheres.FirstOrDefault().Xyz + new Vector3(boundingSpheres.FirstOrDefault().W); + + // Calculate the end points using the center and radius + foreach (var sphere in boundingSpheres) + { + min = Vector3.ComponentMin(min, sphere.Xyz - new Vector3(sphere.W)); + max = Vector3.ComponentMax(max, sphere.Xyz + new Vector3(sphere.W)); + } + + return GetBoundingSphereFromSpheres(min, max); + } + private static Vector4 GetBoundingSphereFromSpheres(Vector3 min, Vector3 max) + { + Vector3 lengths = max - min; + float maxLength = Math.Max(lengths.X, Math.Max(lengths.Y, lengths.Z)); + Vector3 center = (max + min) / 2.0f; + float radius = maxLength / 2.0f; + return new Vector4(center, radius); + } + + public override void Draw(GL_ControlModern control, Pass pass) { + } + } +} diff --git a/File_Format_Library/GL/BFRES_Render.cs b/File_Format_Library/GL/BFRES/BFRES_Render.cs similarity index 76% rename from File_Format_Library/GL/BFRES_Render.cs rename to File_Format_Library/GL/BFRES/BFRES_Render.cs index 22ddf68a..19f3a841 100644 --- a/File_Format_Library/GL/BFRES_Render.cs +++ b/File_Format_Library/GL/BFRES/BFRES_Render.cs @@ -19,11 +19,8 @@ using SF = SFGraphics.GLObjects.Shaders; namespace FirstPlugin { - public class BFRESRender : AbstractGlDrawable, IMeshContainer + public class BFRESRender : BFRESRenderBase { - private bool Disposing = false; - - public Matrix4 ModelTransform = Matrix4.Identity; Vector3 position = new Vector3(0); public static Vector4 hoverColor = new Vector4(1); @@ -34,179 +31,19 @@ namespace FirstPlugin public bool IsSelected() => Selected; - // gl buffer objects - int vbo_position; - int ibo_elements; - - public List Meshes - { - get - { - List meshes = new List(); - for (int m =0; m < models.Count; m++) - { - for (int s = 0; s < models[m].shapes.Count; s++) - meshes.Add(models[m].shapes[s]); - } - return meshes; - } - } - - private List _models = new List(); - public List models - { - get - { - return _models; - } - } - - public void UpdateModelList() - { - _models.Clear(); - foreach (var node in ResFileNode.Nodes) - { - if (node is BFRESGroupNode && - ((BFRESGroupNode)node).Type == BRESGroupType.Models) - { - foreach (FMDL mdl in ((BFRESGroupNode)node).Nodes) - _models.Add(mdl); - } - } - } - - public BFRES ResFileNode; - public BFRESRender() { } - private void GenerateBuffers() - { - GL.GenBuffers(1, out vbo_position); - GL.GenBuffers(1, out ibo_elements); - - TransformBones(); - - UpdateVertexData(); - UpdateTextureMaps(); - } - - public void Destroy() - { - bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; - - if (!buffersWereInitialized) - return; - - GL.DeleteBuffer(vbo_position); - GL.DeleteBuffer(ibo_elements); - - Disposing = true; - } - - private void TransformBones() - { - for (int mdl = 0; mdl < models.Count; mdl++) - { - for (int b = 0; b < models[mdl].Skeleton.bones.Count; b++) - { - models[mdl].Skeleton.bones[b].ModelMatrix = ModelTransform; - } - } - } #region Rendering - - // public ShaderProgram BotwShaderProgram; - // public ShaderProgram normalsShaderProgram; - // public ShaderProgram debugShaderProgram; - // public ShaderProgram pbrShaderProgram; - // public ShaderProgram defaultShaderProgram; - // public ShaderProgram solidColorShaderProgram; - public override void Prepare(GL_ControlModern control) { - /* string pathFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRES.frag"; - string pathVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRES.vert"; - - - string pathBotwFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRES_Botw.frag"; - - string pathPbrFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRES_PBR.frag"; - - string pathBfresUtiltyFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRES_utility.frag"; - string pathBfresTurboShadow = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRESTurboShadow.frag"; - - string pathUtiltyFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Utility") + "\\Utility.frag"; - - - - string pathDebugFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\BFRES_Debug.frag"; - string pathNormalsFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\Normals.frag"; - string pathNormalsVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\Normals.vert"; - string pathNormalGeom = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Bfres") + "\\Normals.geom"; - - var defaultFrag = new FragmentShader(System.IO.File.ReadAllText(pathFrag)); - var defaultVert = new VertexShader(System.IO.File.ReadAllText(pathVert)); - - var BotwtFrag = new FragmentShader(System.IO.File.ReadAllText(pathBotwFrag)); - - var shadowMapAGL = new FragmentShader(System.IO.File.ReadAllText(pathBfresTurboShadow)); - - var PbrFrag = new FragmentShader(System.IO.File.ReadAllText(pathPbrFrag)); - - var debugFrag = new FragmentShader(System.IO.File.ReadAllText(pathDebugFrag)); - var normalsVert = new VertexShader(System.IO.File.ReadAllText(pathNormalsVert)); - var normalsFrag = new FragmentShader(System.IO.File.ReadAllText(pathNormalsFrag)); - var normalsGeom = new GeomertyShader(System.IO.File.ReadAllText(pathNormalGeom)); - - var bfresUtiltyFrag = new FragmentShader(System.IO.File.ReadAllText(pathBfresUtiltyFrag)); - var utiltyFrag = new FragmentShader(System.IO.File.ReadAllText(pathUtiltyFrag)); - - var solidColorFrag = new FragmentShader( - @"#version 330 - uniform vec4 color; - out vec4 fragColor; - - void main(){ - fragColor = color; - }"); - - var solidColorVert = new VertexShader( - @"#version 330 - in vec3 vPosition; - in vec3 vNormal; - in vec3 vColor; - - uniform mat4 mtxMdl; - uniform mat4 mtxCam; - - out vec3 normal; - out vec3 color; - out vec3 position; - - void main(){ - normal = vNormal; - color = vColor; - position = vPosition; - - gl_Position = mtxMdl * mtxCam * vec4(vPosition.xyz, 1.0); - }"); - - defaultShaderProgram = new ShaderProgram(new Shader[] { bfresUtiltyFrag, utiltyFrag, defaultFrag, defaultVert, utiltyFrag, shadowMapAGL }); - BotwShaderProgram = new ShaderProgram(new Shader[] { bfresUtiltyFrag, utiltyFrag, BotwtFrag, defaultVert, utiltyFrag, shadowMapAGL }); - - normalsShaderProgram = new ShaderProgram(new Shader[] { normalsFrag, normalsVert, normalsGeom }); - debugShaderProgram = new ShaderProgram(new Shader[] { bfresUtiltyFrag, utiltyFrag, debugFrag, defaultVert, utiltyFrag, shadowMapAGL }); - pbrShaderProgram = new ShaderProgram(new Shader[] { bfresUtiltyFrag, utiltyFrag, PbrFrag, defaultVert, shadowMapAGL }); - solidColorShaderProgram = new ShaderProgram(solidColorFrag, solidColorVert);*/ } public override void Prepare(GL_ControlLegacy control) { - } public override void Draw(GL_ControlLegacy control, Pass pass) @@ -259,56 +96,10 @@ namespace FirstPlugin GL.Enable(EnableCap.Texture2D); } - public void CenterCamera(GL_ControlBase control) - { - if (!Runtime.FrameCamera) - return; - - var spheres = new List(); - for (int mdl = 0; mdl < models.Count; mdl++) - { - for (int shp = 0; shp < models[mdl].shapes.Count; shp++) - { - var vertexPositions = models[mdl].shapes[shp].vertices.Select(x => x.pos).Distinct(); - spheres.Add(control.GenerateBoundingSphere(vertexPositions)); - } - } - - control.FrameSelect(spheres); - } - - public static Vector4 GenerateBoundingSphere(IEnumerable boundingSpheres) - { - // The initial max/min should be the first point. - Vector3 min = boundingSpheres.FirstOrDefault().Xyz - new Vector3(boundingSpheres.FirstOrDefault().W); - Vector3 max = boundingSpheres.FirstOrDefault().Xyz + new Vector3(boundingSpheres.FirstOrDefault().W); - - // Calculate the end points using the center and radius - foreach (var sphere in boundingSpheres) - { - min = Vector3.ComponentMin(min, sphere.Xyz - new Vector3(sphere.W)); - max = Vector3.ComponentMax(max, sphere.Xyz + new Vector3(sphere.W)); - } - - return GetBoundingSphereFromSpheres(min, max); - } - private static Vector4 GetBoundingSphereFromSpheres(Vector3 min, Vector3 max) - { - Vector3 lengths = max - min; - float maxLength = Math.Max(lengths.X, Math.Max(lengths.Y, lengths.Z)); - Vector3 center = (max + min) / 2.0f; - float radius = maxLength / 2.0f; - return new Vector4(center, radius); - } - public override void Draw(GL_ControlModern control, Pass pass) { DrawBfres(control, pass); } - /* public override void Draw(GL_ControlModern control, Pass pass, EditorSceneBase editorScene) { - DrawBfres(control, pass); - }*/ - private void DrawBfres(GL_ControlModern control, Pass pass) { if (!Runtime.OpenTKInitialized || pass == Pass.TRANSPARENT || Disposing) @@ -445,26 +236,6 @@ namespace FirstPlugin shader.DisableVertexAttributes(); } - public void DepthSortMeshes(Vector3 cameraPosition) - { - foreach (FMDL fmdl in models) - { - List unsortedMeshes = new List(); - - foreach (FSHP m in fmdl.shapes) - { - m.sortingDistance = m.CalculateSortingDistance(cameraPosition); - unsortedMeshes.Add(m); - } - - fmdl.depthSortedMeshes = unsortedMeshes.OrderBy(o => (o.sortingDistance)).ToList(); - } - - - // Order by the distance from the camera to the closest point on the bounding sphere. - // Positive values are usually closer to camera. Negative values are usually farther away. - } - private void SetRenderSettings(SF.Shader shader) { shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor); @@ -813,7 +584,7 @@ namespace FirstPlugin } static bool Loaded = false; - public void UpdateVertexData() + public override void UpdateVertexData() { if (!Runtime.OpenTKInitialized) return; @@ -872,50 +643,6 @@ namespace FirstPlugin Loaded = true; } - public void UpdateSingleMaterialTextureMaps(FMAT mat) - { - if (!Runtime.OpenTKInitialized) - return; - - foreach (BNTX bntx in PluginRuntime.bntxContainers) - { - foreach (var t in mat.TextureMaps) - { - if (bntx.Textures.ContainsKey(t.Name)) - { - if (!bntx.Textures[t.Name].RenderableTex.GLInitialized) - bntx.Textures[t.Name].LoadOpenGLTexture(); - } - } - } - - LibraryGUI.UpdateViewport(); - } - public void UpdateTextureMaps() - { - if (!Runtime.OpenTKInitialized) - return; - - foreach (BNTX bntx in PluginRuntime.bntxContainers) - { - if (!bntx.AllGLInitialized) - { - foreach (var tex in bntx.Textures) - { - if (tex.Value.RenderableTex != null && !tex.Value.RenderableTex.GLInitialized) - tex.Value.LoadOpenGLTexture(); - } - } - } - foreach (BFRESGroupNode ftexCont in PluginRuntime.ftexContainers) - { - foreach (var tex in ftexCont.ResourceNodes) - { - if (!((FTEX)tex.Value).RenderableTex.GLInitialized) - ((FTEX)tex.Value).LoadOpenGLTexture(); - } - } - } private static void SetRenderPass(FMAT mat) { @@ -1300,107 +1027,6 @@ namespace FirstPlugin GL.DrawElements(PrimitiveType.Triangles, p.lodMeshes[p.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, p.Offset); } - /* public override BoundingBox GetSelectionBox() - { - Vector3 Min = new Vector3(0); - Vector3 Max = new Vector3(0); - - foreach (var model in models) - { - foreach (var shape in model.shapes) - { - foreach (var vertex in shape.vertices) - { - Min.X = Math.Min(Min.X, vertex.pos.X); - Min.Y = Math.Min(Min.Y, vertex.pos.Y); - Min.Z = Math.Min(Min.Z, vertex.pos.Z); - Max.X = Math.Max(Max.X, vertex.pos.X); - Max.Y = Math.Max(Max.Y, vertex.pos.Y); - Max.Z = Math.Max(Max.Z, vertex.pos.Z); - } - } - } - - return new BoundingBox() - { - minX = Min.X, - minY = Min.Y, - minZ = Min.Z, - maxX = Max.X, - maxY = Max.Y, - maxZ = Max.Z, - }; - } - - - public override uint SelectAll(GL_ControlBase control) - { - Selected = true; - return REDRAW; - } - - public override uint SelectDefault(GL_ControlBase control) - { - Selected = true; - return REDRAW; - } - - public override uint Select(int partIndex, GL_ControlBase control) - { - Selected = true; - return REDRAW; - } - - public override uint Deselect(int partIndex, GL_ControlBase control) - { - Selected = false; - return REDRAW; - } - - public override LocalOrientation GetLocalOrientation(int partIndex) - { - return new LocalOrientation(position); - } - - public override bool TryStartDragging(DragActionType actionType, int hoveredPart, out LocalOrientation localOrientation, out bool dragExclusively) - { - localOrientation = new LocalOrientation(position); - dragExclusively = false; - return Selected; - } - - public override bool IsInRange(float range, float rangeSquared, Vector3 pos) - { - range = 20000; //Make the range large for now. Todo go back to this - - BoundingBox box = GetSelectionBox(); - - if (pos.X < box.maxX + range && pos.X > box.minX - range && - pos.Y < box.maxY + range && pos.Y > box.minY - range && - pos.Z < box.maxZ + range && pos.Z > box.minZ - range) - return true; - - return false; - } - - public override uint DeselectAll(GL_ControlBase control) - { - Selected = false; - return REDRAW; - } - - public override Vector3 Position - { - get - { - return position; - } - set - { - position = value; - } - }*/ - #endregion } } diff --git a/File_Format_Library/GL/BFRES/RedPro/RedPro_Renderer.cs b/File_Format_Library/GL/BFRES/RedPro/RedPro_Renderer.cs new file mode 100644 index 00000000..7f145c94 --- /dev/null +++ b/File_Format_Library/GL/BFRES/RedPro/RedPro_Renderer.cs @@ -0,0 +1,795 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Drawing; +using Syroot.NintenTools.NSW.Bfres; +using Syroot.NintenTools.NSW.Bfres.Helpers; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using System.Windows.Forms; +using GL_EditorFramework.GL_Core; +using GL_EditorFramework.Interfaces; +using Toolbox.Library; +using Toolbox.Library.Rendering; +using Toolbox.Library.IO; +using Toolbox.Library.Forms; +using ResU = Syroot.NintenTools.Bfres; +using Bfres.Structs; +using FirstPlugin.RedPro; + +namespace FirstPlugin +{ + public class RedPro_Renderer : BFRESRenderBase + { + public List ShaderPrograms = new List(); + + Vector3 position = new Vector3(0); + + public static Vector4 hoverColor = new Vector4(1); + public static Vector4 selectColor = new Vector4(1); + + protected bool Selected = false; + public bool Hovered = false; + + public bool IsSelected() => Selected; + + public struct DisplayVertex + { + // Used for rendering. + public Vector3 Position; + public Vector3 Normal; + public Vector4 BlendWeight; + public Vector4 BlendIndex; + public Vector2 TexCoord0; + public Vector2 TexCoord1; + public Vector2 TexCoord2; + public Vector2 TexCoord3; + public Vector2 TexCoord4; + public Vector2 TexCoord5; + public Vector2 TexCoord6; + public Vector2 TexCoord7; + public Vector4 Color0; + public Vector4 Color1; + + public static int Size = 4 * (3 + 3 + 4 + 4 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4 + 4); + } + + public RedPro_Renderer() + { + + } + + #region Rendering + + public override void Prepare(GL_ControlModern control) + { + + } + + public override void Prepare(GL_ControlLegacy control) + { + + } + + public override void Draw(GL_ControlLegacy control, Pass pass) + { + if (Disposing || pass == Pass.TRANSPARENT) return; + + bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; + if (!buffersWereInitialized) + GenerateBuffers(); + + if (!Runtime.OpenTKInitialized) + return; + + Matrix4 mvpMat = control.ModelMatrix * control.CameraMatrix * control.ProjectionMatrix; + + Matrix4 invertedCamera = Matrix4.Identity; + if (invertedCamera.Determinant != 0) + invertedCamera = mvpMat.Inverted(); + + Vector3 lightDirection = new Vector3(0f, 0f, -1f); + Vector3 difLightDirection = Vector3.TransformNormal(lightDirection, invertedCamera).Normalized(); + + GL.Enable(EnableCap.Texture2D); + GL.Enable(EnableCap.DepthTest); + + foreach (var model in models) + { + foreach (var shape in model.shapes) + { + if (Runtime.RenderModels && model.Checked && shape.Checked) + { + var mat = shape.GetMaterial(); + + List faces = shape.lodMeshes[shape.DisplayLODIndex].getDisplayFace(); + + GL.Begin(PrimitiveType.Triangles); + foreach (var index in faces) + { + Vertex vert = shape.vertices[index]; + float normal = Vector3.Dot(difLightDirection, vert.nrm) * 0.5f + 0.5f; + GL.Color3(new Vector3(normal)); + GL.TexCoord2(vert.uv0); + GL.Vertex3(vert.pos); + } + GL.End(); + } + } + } + + GL.Enable(EnableCap.Texture2D); + } + + public override void Draw(GL_ControlModern control, Pass pass) + { + DrawBfres(control, pass); + } + + private void DrawBfres(GL_ControlModern control, Pass pass) + { + if (!Runtime.OpenTKInitialized || pass == Pass.TRANSPARENT || Disposing) + return; + + bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0; + if (!buffersWereInitialized) + GenerateBuffers(); + + if (Hovered == true) + throw new Exception("model selected"); + + control.UpdateModelMatrix(ModelTransform * Matrix4.CreateScale(Runtime.previewScale)); + + for (int m = 0; m < models.Count; m++) + { + if (models[m].Checked) + { + List opaque = new List(); + List transparent = new List(); + + for (int shp = 0; shp < models[m].shapes.Count; shp++) + { + if (models[m].shapes[shp].GetFMAT().isTransparent) + transparent.Add(models[m].shapes[shp]); + else + opaque.Add(models[m].shapes[shp]); + } + + for (int shp = 0; shp < transparent.Count; shp++) + { + DrawModel(control, transparent[shp], models[m], models[m].IsSelected); + } + + for (int shp = 0; shp < opaque.Count; shp++) + { + DrawModel(control, opaque[shp], models[m], models[m].IsSelected); + } + } + } + + GL.Disable(EnableCap.DepthTest); + GL.Enable(EnableCap.DepthTest); + GL.Enable(EnableCap.CullFace); + } + + public void DepthSortMeshes(Vector3 cameraPosition) + { + foreach (FMDL fmdl in models) + { + List unsortedMeshes = new List(); + + foreach (FSHP m in fmdl.shapes) + { + m.sortingDistance = m.CalculateSortingDistance(cameraPosition); + unsortedMeshes.Add(m); + } + + fmdl.depthSortedMeshes = unsortedMeshes.OrderBy(o => (o.sortingDistance)).ToList(); + } + + + // Order by the distance from the camera to the closest point on the bounding sphere. + // Positive values are usually closer to camera. Negative values are usually farther away. + } + + private static void SetTextureUniforms(FMAT mat, FSHP m, SHShaderProgram shader) + { + for (int t = 0; t < mat.TextureMaps.Count; t++) { + MatTexture matex = (MatTexture)mat.TextureMaps[t]; + mat.HasDiffuseMap = TextureUniform(shader, mat, $"tex_map{t}", matex); + } + } + + private static bool TextureUniform(SHShaderProgram shader, FMAT mat, string name, MatTexture mattex) + { + if (mattex.textureState == STGenericMatTexture.TextureState.Binded) + return true; + + // Bind the texture and create the uniform if the material has the right textures. + BindTexture(mattex, mat, shader, mat.GetResFileU() != null); + + return true; + } + public static bool BindTexture(MatTexture tex, FMAT material, SHShaderProgram shader, bool IsWiiU) + { + BFRES bfres = (BFRES)material.Parent.Parent.Parent.Parent; + + GL.ActiveTexture(TextureUnit.Texture0 + tex.textureUnit + 1); + GL.BindTexture(TextureTarget.Texture2D, RenderTools.defaultTex.RenderableTex.TexID); + + string activeTex = tex.Name; + if (tex.animatedTexName != "") + activeTex = tex.animatedTexName; + + if (IsWiiU) + { + if (bfres.HasTextures) + { + var ftexCont = bfres.GetFTEXContainer; + if (ftexCont != null) + { + if (ftexCont.ResourceNodes.ContainsKey(activeTex)) + { + return BindFTEX(ftexCont, tex, shader, activeTex); + } + } + } + + foreach (var ftexContainer in PluginRuntime.ftexContainers) + { + if (ftexContainer.ResourceNodes.ContainsKey(activeTex)) + { + return BindFTEX(ftexContainer, tex, shader, activeTex); + } + } + } + else + { + if (bfres.HasTextures) + { + var bntx = bfres.GetBNTX; + if (bntx != null) + { + if (bntx.Textures.ContainsKey(activeTex)) + { + return BindBNTX(bntx, tex, shader, activeTex); + } + } + } + + foreach (var bntx in PluginRuntime.bntxContainers) + { + if (bntx.Textures.ContainsKey(activeTex)) + { + return BindBNTX(bntx, tex, shader, activeTex); + } + } + } + + return true; + } + + private static bool BindFTEX(BFRESGroupNode ftexContainer, MatTexture tex, SHShaderProgram shader, string activeTex) + { + FTEX ftex = (FTEX)ftexContainer.ResourceNodes[activeTex]; + + if (ftex.RenderableTex == null || !ftex.RenderableTex.GLInitialized) + ftex.LoadOpenGLTexture(); + + BindGLTexture(tex, shader, ftex); + + return ftex.RenderableTex.GLInitialized; + } + + private static bool BindBNTX(BNTX bntx, MatTexture tex, SHShaderProgram shader, string activeTex) + { + if (bntx.Textures[activeTex].RenderableTex == null || + !bntx.Textures[activeTex].RenderableTex.GLInitialized) + { + bntx.Textures[activeTex].LoadOpenGLTexture(); + } + + BindGLTexture(tex, shader, bntx.Textures[activeTex]); + + return bntx.Textures[activeTex].RenderableTex.GLInitialized; + } + + private static void BindGLTexture(MatTexture tex, SHShaderProgram shader, STGenericTexture texture) + { + //If the texture is still not initialized then return + if (!texture.RenderableTex.GLInitialized) + return; + + // GL.ActiveTexture(TextureUnit.Texture0 + texid); + GL.BindTexture(TextureTarget.Texture2D, texture.RenderableTex.TexID); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)MatTexture.wrapmode[tex.WrapModeS]); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)MatTexture.wrapmode[tex.WrapModeT]); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)MatTexture.minfilter[tex.MinFilter]); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)MatTexture.magfilter[tex.MagFilter]); + GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)ExtTextureFilterAnisotropic.TextureMaxAnisotropyExt, 0.0f); + } + + private SHShaderProgram SearchProgram(string shaderArchive, string shaderProgram) + { + for (int i = 0; i < ShaderPrograms.Count; i++) + if (ShaderPrograms[i].IsLinked(shaderArchive, shaderProgram)) + return ShaderPrograms[i]; + return null; + } + + private void DrawModel(GL_ControlBase control, FSHP m, FMDL mdl, bool ModelSelected) + { + if (m.lodMeshes[m.DisplayLODIndex].faces.Count <= 3) + return; + + var mat = m.GetFMAT(); + + SHShaderProgram shader = SearchProgram( + mat.shaderassign.ShaderArchive, + mat.shaderassign.ShaderModel); + + if (shader == null) return; + + shader.Enable(); + shader.EnableVertexAttributes(); + + GL.Enable(EnableCap.AlphaTest); + GL.AlphaFunc(AlphaFunction.Gequal, 0.1f); + + // SetRenderPass(mat); + // SetUniforms(mat, shader, m, m.DisplayId); + // SetTextureUniforms(mat, m, shader); + + shader.LoadUniforms(mdl, m, mdl.Skeleton, control); + + SetVertexAttributes(m, shader); + + if (m.Checked && mdl.Skeleton.bones.Count > 0 && mdl.Skeleton.bones[m.BoneIndex].Visible && mat.Enabled) + { + PrimitiveType primitiveType = PrimitiveType.Triangles; + + switch (m.lodMeshes[m.DisplayLODIndex].PrimativeType) + { + case STPrimitiveType.Lines: + primitiveType = PrimitiveType.Lines; + break; + case STPrimitiveType.LineStrips: + primitiveType = PrimitiveType.LineStrip; + break; + case STPrimitiveType.Points: + primitiveType = PrimitiveType.Points; + break; + case STPrimitiveType.Triangles: + primitiveType = PrimitiveType.Triangles; + break; + } + + GL.DrawElements(primitiveType, m.lodMeshes[m.DisplayLODIndex].displayFaceSize, DrawElementsType.UnsignedInt, m.Offset); + } + + shader.DisableVertexAttributes(); + shader.Disable(); + } + + public void UpdateShaders() + { + if (ShaderPrograms.Count > 0) return; + + foreach (var file in ResFileNode.IFileInfo.ArchiveParent.Files) { + if (Utils.GetExtension(file.FileName) == ".sharc") + { + var fileFormat = file.OpenFile(); + if (fileFormat != null && fileFormat is SHARC) { + ShaderPrograms.AddRange(LoadProgram((SHARC)fileFormat)); + } + } + } + } + + private List LoadProgram(SHARC sharc) + { + List programs = new List(); + foreach (var program in sharc.header.ShaderPrograms) + programs.Add(new SHShaderProgram(sharc.header, program)); + + return programs; + } + + static bool Loaded = false; + public override void UpdateVertexData() + { + if (!Runtime.OpenTKInitialized) + return; + + UpdateShaders(); + UpdateModelList(); + Loaded = false; + + DisplayVertex[] Vertices; + int[] Faces; + + int poffset = 0; + int voffset = 0; + List Vs = new List(); + List Ds = new List(); + + int TotalShapeCount = models.Sum(b => b.shapes.Count); + + int value = 0; + + for (int m = 0; m < models.Count; m++) + { + //Reset min/max + models[m].MaxPosition = new Vector3(0); + models[m].MinPosition = new Vector3(0); + + for (int shp = 0; shp < models[m].shapes.Count; shp++) + { + //Update render pass aswell + //CheckRenderPass(models[m].shapes[shp].GetFMAT()); + + models[m].shapes[shp].Offset = poffset * 4; + List pv = CreateDisplayVertices(models[m], models[m].shapes[shp]); + Vs.AddRange(pv); + + for (int i = 0; i < models[m].shapes[shp].lodMeshes[models[m].shapes[shp].DisplayLODIndex].displayFaceSize; i++) + { + Ds.Add(models[m].shapes[shp].display[i] + voffset); + } + poffset += models[m].shapes[shp].lodMeshes[models[m].shapes[shp].DisplayLODIndex].displayFaceSize; + voffset += pv.Count; + } + } + + // Binds + Vertices = Vs.ToArray(); + Faces = Ds.ToArray(); + + // Bind only once! + GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position); + GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * DisplayVertex.Size), Vertices, BufferUsageHint.StaticDraw); + + GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements); + GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(Faces.Length * sizeof(int)), Faces, BufferUsageHint.StaticDraw); + + LibraryGUI.UpdateViewport(); + + Loaded = true; + } + + static List CreateDisplayVertices(FMDL model, FSHP mesh) + { + // rearrange faces + mesh.display = mesh.lodMeshes[mesh.DisplayLODIndex].getDisplayFace().ToArray(); + + List displayVertList = new List(); + + if (mesh.lodMeshes[mesh.DisplayLODIndex].faces.Count <= 3) + return displayVertList; + + foreach (Vertex v in mesh.vertices) + { + model.MaxPosition = OpenGLUtils.GetMax(model.MaxPosition, v.pos); + model.MinPosition = OpenGLUtils.GetMin(model.MinPosition, v.pos); + + DisplayVertex displayVert = new DisplayVertex() + { + Position = v.pos, + Normal = v.nrm, + Color0 = v.col, + Color1 = v.col2, + TexCoord0 = v.uv0, + TexCoord1 = v.uv1, + TexCoord2 = v.uv2, + BlendIndex = new Vector4( + v.boneIds.Count > 0 ? v.boneIds[0] : -1, + v.boneIds.Count > 1 ? v.boneIds[1] : -1, + v.boneIds.Count > 2 ? v.boneIds[2] : -1, + v.boneIds.Count > 3 ? v.boneIds[3] : -1), + BlendWeight = new Vector4( + v.boneWeights.Count > 0 ? v.boneWeights[0] : 0, + v.boneWeights.Count > 1 ? v.boneWeights[1] : 0, + v.boneWeights.Count > 2 ? v.boneWeights[2] : 0, + v.boneWeights.Count > 3 ? v.boneWeights[3] : 0), + }; + + displayVertList.Add(displayVert); + } + + return displayVertList; + } + + public void UpdateSingleMaterialTextureMaps(FMAT mat) + { + if (!Runtime.OpenTKInitialized) + return; + + foreach (BNTX bntx in PluginRuntime.bntxContainers) + { + foreach (var t in mat.TextureMaps) + { + if (bntx.Textures.ContainsKey(t.Name)) + { + if (!bntx.Textures[t.Name].RenderableTex.GLInitialized) + bntx.Textures[t.Name].LoadOpenGLTexture(); + } + } + } + + LibraryGUI.UpdateViewport(); + } + public void UpdateTextureMaps() + { + if (!Runtime.OpenTKInitialized) + return; + + foreach (BNTX bntx in PluginRuntime.bntxContainers) + { + if (!bntx.AllGLInitialized) + { + foreach (var tex in bntx.Textures) + { + if (tex.Value.RenderableTex != null && !tex.Value.RenderableTex.GLInitialized) + tex.Value.LoadOpenGLTexture(); + } + } + } + foreach (BFRESGroupNode ftexCont in PluginRuntime.ftexContainers) + { + foreach (var tex in ftexCont.ResourceNodes) + { + if (!((FTEX)tex.Value).RenderableTex.GLInitialized) + ((FTEX)tex.Value).LoadOpenGLTexture(); + } + } + } + + private static void SetRenderPass(FMAT mat) + { + bool NoCull = false; + bool CullBack = false; + bool CullFront = false; + + for (int i = 0; i < mat.renderinfo.Count; i++) + { + if (mat.renderinfo[i].Name == "display_face") + { + NoCull = mat.renderinfo[i].ValueString.Contains("both"); + CullFront = mat.renderinfo[i].ValueString.Contains("back"); + CullBack = mat.renderinfo[i].ValueString.Contains("front"); + } + + if (mat.shaderassign.ShaderArchive == "Turbo_UBER") + { + AglShaderTurbo aglShader = new AglShaderTurbo(); + aglShader.LoadRenderInfo(mat.renderinfo[i]); + } + } + + if (NoCull) + { + GL.Disable(EnableCap.CullFace); + } + else if (CullFront) + { + GL.Enable(EnableCap.CullFace); + GL.CullFace(CullFaceMode.Front); + } + else if (CullBack) + { + GL.Enable(EnableCap.CullFace); + GL.CullFace(CullFaceMode.Back); + } + } + + private static void CheckRenderPass(FMAT mat) + { + if (mat.ImageKey != "material") + { + mat.ImageKey = "material"; + mat.SelectedImageKey = "material"; + } + + bool IsTranslucent = false; + bool IsTransparentMask = false; + + + for (int i = 0; i < mat.renderinfo.Count; i++) + { + if (mat.renderinfo[i].Name == "gsys_render_state_mode") + { + IsTranslucent = mat.renderinfo[i].ValueString.Contains("translucent"); + IsTransparentMask = mat.renderinfo[i].ValueString.Contains("mask"); + } + if (mat.renderinfo[i].Name == "renderPass") + { + IsTransparentMask = mat.renderinfo[i].ValueString.Contains("xlu"); + } + } + + if (mat.shaderassign.options.ContainsKey("enable_translucent")) + IsTranslucent = mat.shaderassign.options["enable_translucent"] == "1"; + if (mat.shaderassign.options.ContainsKey("enable_translucent")) + IsTransparentMask = mat.shaderassign.options["enable_transparent"] == "1"; + + if (mat.MaterialU != null) + { + IsTranslucent = mat.MaterialU.RenderState.FlagsMode == ResU.RenderStateFlagsMode.Translucent; + IsTransparentMask = mat.MaterialU.RenderState.FlagsMode == ResU.RenderStateFlagsMode.AlphaMask; + } + + mat.isTransparent = IsTransparentMask || IsTranslucent; + + SetMaterialIcon(mat, IsTranslucent, "MaterialTranslucent"); + SetMaterialIcon(mat, IsTransparentMask, "MaterialTransparent"); + } + + private static void SetMaterialIcon(FMAT mat, bool IsEffect, string Key) + { + if (IsEffect) + { + mat.ImageKey = Key; + mat.SelectedImageKey = Key; + } + } + + private static void SetUniforms(FMAT mat, SHShaderProgram shader, FSHP m, int id) + { + + } + + private static void SetUniformData(FMAT mat, SHShaderProgram shader, string propertyName) + { + if (mat.shaderassign.options.ContainsKey(propertyName)) + { + float value = float.Parse(mat.shaderassign.options[propertyName]); + shader.SetFloat(propertyName, value); + } + if (mat.matparam.ContainsKey(propertyName)) + { + if (mat.matparam[propertyName].Type == ShaderParamType.Float) + { + if (mat.anims.ContainsKey(propertyName)) + mat.matparam[propertyName].ValueFloat[0] = mat.anims[propertyName][0]; + shader.SetFloat(propertyName, mat.matparam[propertyName].ValueFloat[0]); + } + + if (mat.matparam[propertyName].Type == ShaderParamType.Float2) + { + if (mat.anims.ContainsKey(propertyName)) + { + mat.matparam[propertyName].ValueFloat = new float[2] { + mat.anims[propertyName][0], mat.anims[propertyName][1]}; + } + + shader.SetVec2(propertyName, Utils.ToVec2(mat.matparam[propertyName].ValueFloat)); + } + + if (mat.matparam[propertyName].Type == ShaderParamType.Float3) + { + if (mat.anims.ContainsKey(propertyName)) + { + mat.matparam[propertyName].ValueFloat = new float[3] { + mat.anims[propertyName][0], + mat.anims[propertyName][1], + mat.anims[propertyName][2]}; + } + + shader.SetVec3(propertyName, Utils.ToVec3(mat.matparam[propertyName].ValueFloat)); + } + if (mat.matparam[propertyName].Type == ShaderParamType.Float4) + { + if (mat.anims.ContainsKey(propertyName)) + { + mat.matparam[propertyName].ValueFloat = new float[4] { + mat.anims[propertyName][0], mat.anims[propertyName][1], + mat.anims[propertyName][2], mat.anims[propertyName][3]}; + } + + shader.SetVec4(propertyName, Utils.ToVec4(mat.matparam[propertyName].ValueFloat)); + } + if (mat.matparam[propertyName].Type == ShaderParamType.TexSrt) + { + // Vector 2 Scale + // 1 roation float + // Vector2 translate + TexSrt texSRT = mat.matparam[propertyName].ValueTexSrt; + + shader.SetVec2("SRT_Scale", Utils.ToVec2(texSRT.Scaling)); + shader.SetFloat("SRT_Rotate", texSRT.Rotation); + shader.SetVec2("SRT_Translate", Utils.ToVec2(texSRT.Translation)); + } + + //MTA SRT + if (propertyName == "texsrt0" && mat.shaderassign.ShaderArchive == "ssg") + { + TexSrt texSRT = mat.matparam[propertyName].ValueTexSrt; + + shader.SetVec2("SRT_Scale", Utils.ToVec2(texSRT.Scaling)); + shader.SetFloat("SRT_Rotate", texSRT.Rotation); + shader.SetVec2("SRT_Translate", Utils.ToVec2(texSRT.Translation)); + } + } + + if (mat.animatedMatParams.ContainsKey(propertyName)) + { + if (mat.animatedMatParams[propertyName].Type == ShaderParamType.Float) + { + if (mat.anims.ContainsKey(propertyName)) + mat.animatedMatParams[propertyName].ValueFloat[0] = mat.anims[propertyName][0]; + shader.SetFloat(propertyName, mat.animatedMatParams[propertyName].ValueFloat[0]); + } + + if (mat.animatedMatParams[propertyName].Type == ShaderParamType.Float2) + { + if (mat.anims.ContainsKey(propertyName)) + { + mat.animatedMatParams[propertyName].ValueFloat = new float[2] { + mat.anims[propertyName][0], mat.anims[propertyName][1]}; + } + + shader.SetVec2(propertyName, Utils.ToVec2(mat.animatedMatParams[propertyName].ValueFloat)); + } + + if (mat.animatedMatParams[propertyName].Type == ShaderParamType.Float3) + { + Console.WriteLine(propertyName + " " + mat.animatedMatParams[propertyName].ValueFloat); + + if (mat.anims.ContainsKey(propertyName)) + { + mat.animatedMatParams[propertyName].ValueFloat = new float[3] { + mat.anims[propertyName][0], + mat.anims[propertyName][1], + mat.anims[propertyName][2]}; + } + + shader.SetVec3(propertyName, Utils.ToVec3(mat.animatedMatParams[propertyName].ValueFloat)); + } + if (mat.animatedMatParams[propertyName].Type == ShaderParamType.Float4) + { + if (mat.anims.ContainsKey(propertyName)) + { + mat.animatedMatParams[propertyName].ValueFloat = new float[4] { + mat.anims[propertyName][0], mat.anims[propertyName][1], + mat.anims[propertyName][2], mat.anims[propertyName][3]}; + } + + shader.SetVec4(propertyName, Utils.ToVec4(mat.animatedMatParams[propertyName].ValueFloat)); + } + + if (mat.animatedMatParams[propertyName].Type == ShaderParamType.TexSrt) + { + // Vector 2 Scale + // 1 roation float + // Vector2 translate + TexSrt texSRT = mat.animatedMatParams[propertyName].ValueTexSrt; + + shader.SetVec2("SRT_Scale", Utils.ToVec2(texSRT.Scaling)); + shader.SetFloat("SRT_Rotate", texSRT.Rotation); + shader.SetVec2("SRT_Translate", Utils.ToVec2(texSRT.Translation)); + } + } + } + private void SetVertexAttributes(FSHP m, SHShaderProgram shader) + { + GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position); + GL.VertexAttribPointer(shader.GetAttribute("aPosition"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 0); + GL.VertexAttribPointer(shader.GetAttribute("aNormal"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 12); + GL.VertexAttribPointer(shader.GetAttribute("aBlendWeight"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 24); + GL.VertexAttribIPointer(shader.GetAttribute("aBlendIndex"), 4, VertexAttribIntegerType.Int, DisplayVertex.Size, new IntPtr(40)); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord0"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 56); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord1"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 64); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord2"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 72); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord3"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 80); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord4"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 88); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord5"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 96); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord6"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 104); + GL.VertexAttribPointer(shader.GetAttribute("aTexCoord7"), 2, VertexAttribPointerType.Float, false, DisplayVertex.Size, 112); + GL.VertexAttribPointer(shader.GetAttribute("aColor0"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 120); + GL.VertexAttribPointer(shader.GetAttribute("aColor1"), 4, VertexAttribPointerType.Float, false, DisplayVertex.Size, 136); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements); + } + + #endregion + } +} diff --git a/File_Format_Library/GL/BFRES/RedPro/ShaderProgram.cs b/File_Format_Library/GL/BFRES/RedPro/ShaderProgram.cs new file mode 100644 index 00000000..c2d1f3df --- /dev/null +++ b/File_Format_Library/GL/BFRES/RedPro/ShaderProgram.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Toolbox.Library; +using OpenTK.Graphics.OpenGL; +using OpenTK; +using Bfres.Structs; +using Toolbox.Library.IO; + +namespace FirstPlugin.RedPro +{ + public class SHShaderProgram : GLShaderGeneric + { + public SHARC.Header ShaderArchive { get; set; } + public SHARC.ShaderProgram Program { get; set; } + + public SHShaderProgram(SHARC.Header shader, SHARC.ShaderProgram program) + { + ShaderArchive = shader; + Program = program; + + this.Compile(); + } + + public bool IsLinked(string shaderArchive, string shaderProgram) + { + return (ShaderArchive.Name == shaderArchive.Replace(" ", string.Empty) && Program.Text.Replace(" ", string.Empty) == shaderProgram); + } + + public void LoadUniforms(FMDL fmdl, FSHP shp, STSkeleton skeleton, GL_EditorFramework.GL_Core.GL_ControlBase control) + { + + } + } +} diff --git a/File_Format_Library/GUI/BFRES/BfresEditor.cs b/File_Format_Library/GUI/BFRES/BfresEditor.cs index 5609a586..b01e61a0 100644 --- a/File_Format_Library/GUI/BFRES/BfresEditor.cs +++ b/File_Format_Library/GUI/BFRES/BfresEditor.cs @@ -136,7 +136,7 @@ namespace FirstPlugin.Forms return null; } - public void FrameCamera(BFRESRender Renderer) + public void FrameCamera(BFRESRenderBase Renderer) { if (!Runtime.UseOpenGL || !DisplayViewport) return; diff --git a/File_Format_Library/Main.cs b/File_Format_Library/Main.cs index c9498b83..6f32083f 100644 --- a/File_Format_Library/Main.cs +++ b/File_Format_Library/Main.cs @@ -345,7 +345,6 @@ namespace FirstPlugin Formats.Add(typeof(BTI)); Formats.Add(typeof(TXE)); Formats.Add(typeof(SARC)); - Formats.Add(typeof(BCRES)); Formats.Add(typeof(BNTX)); Formats.Add(typeof(BEA)); Formats.Add(typeof(BYAML)); @@ -392,7 +391,7 @@ namespace FirstPlugin Formats.Add(typeof(IGA_PAK)); Formats.Add(typeof(MKAGPDX_Model)); Formats.Add(typeof(GFBMDL)); - // Formats.Add(typeof(GFBANM)); + // Formats.Add(typeof(GFBANM)); Formats.Add(typeof(GFBANMCFG)); Formats.Add(typeof(Turbo.Course_MapCamera_bin)); Formats.Add(typeof(SDF)); @@ -445,6 +444,7 @@ namespace FirstPlugin Formats.Add(typeof(NLG_NLOC)); Formats.Add(typeof(PCK)); Formats.Add(typeof(NLG.StrikersSAnim)); + Formats.Add(typeof(CtrLibrary.BCH)); diff --git a/Switch_Toolbox_Library/OpenGL/GLShaderGeneric.cs b/Switch_Toolbox_Library/OpenGL/GLShaderGeneric.cs index 28d3cf3d..e8cde6ea 100644 --- a/Switch_Toolbox_Library/OpenGL/GLShaderGeneric.cs +++ b/Switch_Toolbox_Library/OpenGL/GLShaderGeneric.cs @@ -16,6 +16,7 @@ namespace Toolbox.Library private int vertexShaderID; private int fragmentShaderID; + private Dictionary uniformBlocks = new Dictionary(); private Dictionary attributes = new Dictionary(); private Dictionary uniforms = new Dictionary(); private int activeAttributeCount; @@ -66,18 +67,32 @@ namespace Toolbox.Library { if (uniforms.ContainsKey(name)) GL.Uniform4(uniforms[name], value); + else + Console.WriteLine("Could not find vec4 " + name); + } + + public void SetVec3(string name, Vector3 value) + { + if (uniforms.ContainsKey(name)) + GL.Uniform3(uniforms[name], value); + else + Console.WriteLine("Could not find vec3 " + name); } public void SetVec2(string name, Vector2 value) { if (uniforms.ContainsKey(name)) GL.Uniform2(uniforms[name], value); + else + Console.WriteLine("Could not find vec2 " + name); } public void SetFloat(string name, float value) { if (uniforms.ContainsKey(name)) GL.Uniform1(uniforms[name], value); + else + Console.WriteLine("Could not find float " + name); } public void SetInt(string name, int value) @@ -106,6 +121,50 @@ namespace Toolbox.Library GL.UniformMatrix4(uniforms[name], false, ref value); } + public void LoadLayout(string name) + { + if (!uniformBlocks.ContainsKey(name)) { + //Get block indices + var uniformID = GL.GetUniformBlockIndex(program, name); + + //Link them + GL.UniformBlockBinding(program, uniformID, 0); + + int buffer; + GL.GenBuffers(1, out buffer); + uniformBlocks.Add(name, buffer); + + var dataValues = new Vector4[3] + { + new Vector4(1, 0, 0, 0), + new Vector4(0, 1, 0, 0), + new Vector4(0, 0, 1, 0) + }; + + var totalSize = (Vector3.SizeInBytes + 4) * dataValues.Length; //Add 4 for alignment + + GL.BindBuffer(BufferTarget.UniformBuffer, buffer); + GL.BufferData(BufferTarget.UniformBuffer, + totalSize, + IntPtr.Zero, + BufferUsageHint.StaticDraw); + GL.BindBuffer(BufferTarget.UniformBuffer, 0); + + // define the range of the buffer that links to a uniform binding point + GL.BindBufferRange(BufferRangeTarget.UniformBuffer, 0, buffer, + IntPtr.Zero, totalSize); + + GL.BindBuffer(BufferTarget.UniformBuffer, buffer); + GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, (Vector3.SizeInBytes + 4) * dataValues.Length, dataValues); //Add 4 for alignment + GL.BindBuffer(BufferTarget.UniformBuffer, 0); + } + } + + public void GetAttribLocation() + { + + } + public int this[string name] { get { return uniforms[name]; } diff --git a/Toolbox/Shader/Bfres/BFRES_utility.frag b/Toolbox/Shader/Bfres/BFRES_utility.frag index baf254fa..a09348da 100644 --- a/Toolbox/Shader/Bfres/BFRES_utility.frag +++ b/Toolbox/Shader/Bfres/BFRES_utility.frag @@ -28,8 +28,9 @@ vec3 SpecularPass(vec3 I, vec3 normal, int HasSpecularMap, sampler2D SpecularMap float specBrdf = max(dot(I, normal), 0); float exponent = 8; - if (SpecColor == vec3(0)) //Color shouldn't be black unless it's not set - SpecColor = vec3(1); + vec3 specularColor = SpecColor; + if (specularColor == vec3(0)) //Color shouldn't be black unless it's not set + specularColor = vec3(1); if (HasSpecularMap == 0) { @@ -51,7 +52,7 @@ vec3 SpecularPass(vec3 I, vec3 normal, int HasSpecularMap, sampler2D SpecularMap result *= SpecColor.rgb; float intensity = 0.3; - return result * intensity; + return result * vec3(intensity); } vec3 EmissionPass(sampler2D EmissionMap, float emission_intensity, VertexAttributes vert, float texCoordIndex, vec3 emission_color)