1
0
mirror of synced 2024-11-30 18:24:39 +01:00

Improve lighting view in pbr shader. Start on SEModel support.

This commit is contained in:
KillzXGaming 2019-06-20 15:29:04 -04:00
parent acc7dcd9c9
commit ad1c4aed4e
12 changed files with 394 additions and 36 deletions

Binary file not shown.

View File

@ -84,7 +84,7 @@ namespace FirstPlugin
for (int i = 0; i < FileCount; i++)
{
var file = new FileEntry();
var file = new FileEntry(FilePath);
file.FileName = FileNames[i];
file.Read(reader);
files.Add(file);
@ -114,6 +114,9 @@ namespace FirstPlugin
public class FileEntry : ArchiveFileInfo
{
//The archive file used to open the file
public string SourceFile { get; set; }
public CompressionType FileCompressionType;
public enum CompressionType : int
@ -123,28 +126,45 @@ namespace FirstPlugin
Deflate,
}
public void Read(FileReader reader)
public FileEntry(string ArchivePath)
{
uint FileOffset = reader.ReadUInt32();
byte[] Unknown = reader.ReadBytes(4);
uint DecompressedFileSize = reader.ReadUInt32();
FileCompressionType = reader.ReadEnum<CompressionType>(false);
SourceFile = ArchivePath;
}
using (reader.TemporarySeek(FileOffset, System.IO.SeekOrigin.Begin))
private uint FileOffset;
private uint DecompressedFileSize;
public override byte[] FileData
{
get
{
if (FileCompressionType == CompressionType.None)
using (var reader = new FileReader(SourceFile))
{
FileData = reader.ReadBytes((int)DecompressedFileSize);
}
else
{
uint FileSize = reader.ReadUInt32();
reader.Position = FileOffset;
FileData = reader.ReadBytes((int)FileSize + 0x10);
if (FileCompressionType == CompressionType.None)
{
return reader.ReadBytes((int)DecompressedFileSize);
}
else
{
uint FileSize = reader.ReadUInt32();
reader.Position = FileOffset;
return reader.ReadBytes((int)FileSize + 0x10);
}
}
}
}
public void Read(FileReader reader)
{
FileOffset = reader.ReadUInt32();
byte[] Unknown = reader.ReadBytes(4);
DecompressedFileSize = reader.ReadUInt32();
FileCompressionType = reader.ReadEnum<CompressionType>(false);
}
}
}
}

View File

@ -739,10 +739,17 @@ namespace Bfres.Structs
default:
List<STGenericObject> ImportedObjects = new List<STGenericObject>();
List<STGenericMaterial> ImportedMaterials = new List<STGenericMaterial>();
List<string> ImportedBoneNames = new List<string>();
STSkeleton ImportedSkeleton = new STSkeleton();
if (Runtime.DEVELOPER_DEBUG_MODE)
if (ext == ".semodel")
{
SEModel seModel = new SEModel();
seModel.CreateGenericModel(FileName);
ImportedObjects = seModel.objects;
ImportedMaterials = seModel.materials;
ImportedSkeleton = seModel.skeleton;
}
else if (Runtime.DEVELOPER_DEBUG_MODE)
{
DAE daeFile = new DAE();
bool IsLoaded = daeFile.LoadFile(FileName);
@ -753,7 +760,6 @@ namespace Bfres.Structs
ImportedObjects = daeFile.objects;
ImportedMaterials = daeFile.materials;
ImportedSkeleton = daeFile.skeleton;
ImportedBoneNames = daeFile.BoneNames;
}
else
{
@ -766,7 +772,6 @@ namespace Bfres.Structs
ImportedObjects = assimp.objects;
ImportedMaterials = assimp.materials;
ImportedSkeleton = assimp.skeleton;
ImportedBoneNames = assimp.BoneNames;
}
@ -1092,8 +1097,8 @@ namespace Bfres.Structs
if (obj.ObjectName == "")
obj.ObjectName = $"Mesh {curShp}";
progressBar.Task = $"Generating shape {obj.ObjectName} { curShp} / { ImportedMaterials.Count}";
progressBar.Value = ((curShp++ * 100) / ImportedMaterials.Count);
progressBar.Task = $"Generating shape {obj.ObjectName} { curShp} / { ImportedObjects.Count}";
progressBar.Value = ((curShp++ * 100) / ImportedObjects.Count);
progressBar.Refresh();
@ -1114,7 +1119,7 @@ namespace Bfres.Structs
shape.BoneIndex = obj.BoneIndex;
if (obj.MaterialIndex + MatStartIndex < materials.Count)
if (obj.MaterialIndex + MatStartIndex < materials.Count && obj.MaterialIndex > 0)
shape.MaterialIndex = obj.MaterialIndex + MatStartIndex;
else
shape.MaterialIndex = 0;

View File

@ -77,6 +77,12 @@ namespace FirstPlugin
return editor;
}
public override void OnAfterAdded()
{
if (textures.Count > 0)
this.TreeView.SelectedNode = textures[0];
}
public override void FillEditor(UserControl control)
{
((STPropertyGrid)control).LoadProperty(header);
@ -263,6 +269,13 @@ namespace FirstPlugin
uint surfBlockType;
uint dataBlockType;
uint mipBlockType;
uint vertexShaderHeader = 0x03;
uint vertexShaderProgram = 0x05;
uint pixelShaderHeader = 0x06;
uint pixelShaderProgram = 0x07;
uint geometryShaderHeader = 0x08;
uint geometryShaderProgram = 0x09;
uint userDataBlock = 0x10;
if (header.MajorVersion == 6 && header.MinorVersion == 0)
{
@ -297,6 +310,9 @@ namespace FirstPlugin
block.Read(reader);
blocks.Add(block);
bool BlockIsEmpty = block.BlockType == BlockType.AlignData ||
block.BlockType == BlockType.EndOfFile;
//Here we use "if" instead of "case" statements as types vary between versions
if ((uint)block.BlockType == surfBlockType)
{
@ -331,6 +347,20 @@ namespace FirstPlugin
{
mipMaps.Add(block.data);
}
else if ((uint)block.BlockType == vertexShaderHeader)
Nodes.Add(new BlockDisplay(block.data) { Text = "Vertex Shader Header" });
else if ((uint)block.BlockType == vertexShaderProgram)
Nodes.Add(new BlockDisplay(block.data) { Text = "Vertex Shader Program" });
else if ((uint)block.BlockType == pixelShaderHeader)
Nodes.Add(new BlockDisplay(block.data) { Text = "Pixel Shader Header" });
else if ((uint)block.BlockType == pixelShaderProgram)
Nodes.Add(new BlockDisplay(block.data) { Text = "Pixel Shader Program" });
else if ((uint)block.BlockType == geometryShaderHeader)
Nodes.Add(new BlockDisplay(block.data) { Text = "Geometry Shader Header" });
else if ((uint)block.BlockType == geometryShaderProgram)
Nodes.Add(new BlockDisplay(block.data) { Text = "Geometry Shader Program" });
else if (!BlockIsEmpty)
Nodes.Add(new BlockDisplay(block.data) { Text = $"Block Type {block.BlockType.ToString("X")}" });
}
if (textures.Count != data.Count)
throw new Exception($"Bad size! {textures.Count} {data.Count}");
@ -339,27 +369,54 @@ namespace FirstPlugin
int curMip = 0;
foreach (var node in Nodes)
{
TextureData tex = (TextureData)node;
if (node is TextureData)
{
TextureData tex = (TextureData)node;
tex.surface.data = data[curTex];
tex.surface.bpp = GX2.surfaceGetBitsPerPixel(tex.surface.format) >> 3;
tex.Format = FTEX.ConvertFromGx2Format((Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)tex.surface.format);
tex.Width = tex.surface.width;
tex.Height = tex.surface.height;
tex.surface.data = data[curTex];
tex.surface.bpp = GX2.surfaceGetBitsPerPixel(tex.surface.format) >> 3;
tex.Format = FTEX.ConvertFromGx2Format((Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)tex.surface.format);
tex.Width = tex.surface.width;
tex.Height = tex.surface.height;
if (tex.surface.numMips > 1)
tex.surface.mipData = mipMaps[curMip++];
else
tex.surface.mipData = new byte[0];
if (tex.surface.numMips > 1)
tex.surface.mipData = mipMaps[curMip++];
else
tex.surface.mipData = new byte[0];
if (tex.surface.mipData == null)
tex.surface.numMips = 1;
if (tex.surface.mipData == null)
tex.surface.numMips = 1;
curTex++;
curTex++;
}
}
reader.Close();
reader.Dispose();
}
public class BlockDisplay : TreeNodeCustom
{
public byte[] BlockData;
public BlockDisplay(byte[] data)
{
BlockData = data;
}
public override void OnClick(TreeView treeview)
{
HexEditor editor = (HexEditor)LibraryGUI.Instance.GetActiveContent(typeof(HexEditor));
if (editor == null)
{
editor = new HexEditor();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
editor.LoadData(BlockData);
}
}
public class GTXHeader
{
readonly string Magic = "Gfx2";

View File

@ -352,6 +352,10 @@ namespace FirstPlugin
Gx2HeaderData.Read(reader);
Gx2HeaderData.data = Data;
Gx2HeaderData.mipData = MipData;
RedChannel = GX2ChanneToGeneric((GX2CompSel)Gx2HeaderData.compSel[0]);
GreenChannel = GX2ChanneToGeneric((GX2CompSel)Gx2HeaderData.compSel[1]);
BlueChannel = GX2ChanneToGeneric((GX2CompSel)Gx2HeaderData.compSel[2]);
AlphaChannel = GX2ChanneToGeneric((GX2CompSel)Gx2HeaderData.compSel[3]);
Format = Bfres.Structs.FTEX.ConvertFromGx2Format((GX2SurfaceFormat)Gx2HeaderData.format);
}
@ -361,6 +365,16 @@ namespace FirstPlugin
reader.Seek(pos + HeaderSize, System.IO.SeekOrigin.Begin);
}
private STChannelType GX2ChanneToGeneric(GX2CompSel comp)
{
if (comp == GX2CompSel.ChannelR) return STChannelType.Red;
else if (comp == GX2CompSel.ChannelG) return STChannelType.Green;
else if (comp == GX2CompSel.ChannelB) return STChannelType.Blue;
else if (comp == GX2CompSel.ChannelA) return STChannelType.Alpha;
else if (comp == GX2CompSel.Always0) return STChannelType.Zero;
else return STChannelType.One;
}
public void Write(FileWriter writer, bool IsNTP3)
{
@ -451,6 +465,11 @@ namespace FirstPlugin
public class NutGX2Surface : GX2.GX2Surface
{
public NutGX2Surface()
{
compSel = new byte[4] { 0,1,2,3,};
}
public void Read(FileReader reader)
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;

View File

@ -0,0 +1,238 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SELib;
using Switch_Toolbox.Library.Rendering;
using OpenTK;
namespace Switch_Toolbox.Library
{
public class SEModel
{
public List<STGenericObject> objects = new List<STGenericObject>();
public List<STGenericMaterial> materials = new List<STGenericMaterial>();
public STSkeleton skeleton;
public static void Save(string FileName, List<STGenericObject> Meshes, List<STGenericMaterial> Materials, List<STBone> bones)
{
SELib.SEModel seModel = new SELib.SEModel();
for (int i = 0; i < Meshes.Count; i++)
seModel.AddMesh(SaveMesh(Meshes[i]));
for (int i = 0; i < Materials.Count; i++)
seModel.AddMaterial(SaveMaterial(Materials[i]));
// for (int i = 0; i < bones.Count; i++)
// seModel.AddBone(SaveBone(bones[i]));
}
private static SELib.SEModelMesh SaveMesh(STGenericObject mesh)
{
var seMesh = new SELib.SEModelMesh();
var MeshLevel = mesh.lodMeshes[mesh.DisplayLODIndex];
for (int i = 0; i < MeshLevel.faces.Count; i++)
{
seMesh.AddFace((uint)MeshLevel.faces[i], (uint)MeshLevel.faces[i++], (uint)MeshLevel.faces[i++]);
}
return seMesh;
}
private static SELib.SEModelMaterial SaveMaterial(STGenericMaterial material)
{
var seMaterial = new SELib.SEModelMaterial();
return seMaterial;
}
private static SELib.SEModelBone SaveBone(STBone bone)
{
var seBone = new SELib.SEModelBone();
return seBone;
}
public void CreateGenericModel(string FileName)
{
skeleton = new STSkeleton();
var seModel = SELib.SEModel.Read(FileName);
for (int i = 0; i < seModel.MeshCount; i++)
objects.Add(CreateGenericObject(seModel, seModel.Meshes[i]));
for (int i = 0; i < seModel.MaterialCount; i++)
materials.Add(CreateGenericMaterial(seModel, seModel.Materials[i]));
for (int i = 0; i < seModel.BoneCount; i++)
skeleton.bones.Add(CreateGenericBone(seModel, seModel.Bones[i]));
}
public STBone CreateGenericBone(SELib.SEModel seModel, SELib.SEModelBone seBone)
{
STBone bone = new STBone(skeleton);
bone.Text = seBone.BoneName;
bone.parentIndex = seBone.BoneParent;
bone.RotationType = STBone.BoneRotationType.Euler;
Vector3 rotEular = ToEular(seBone.LocalRotation);
bone.position = new float[] { (float)seBone.LocalPosition.X, (float)seBone.LocalPosition.Y, (float)seBone.LocalPosition.Z };
bone.scale = new float[] { (float)seBone.Scale.X, (float)seBone.Scale.Y, (float)seBone.Scale.Z };
bone.rotation = new float[] { rotEular.X, rotEular.Y, rotEular.Z, 0 };
return bone;
}
public STGenericMaterial CreateGenericMaterial(SELib.SEModel seModel, SELib.SEModelMaterial seMaterial)
{
STGenericMaterial material = new STGenericMaterial();
material.Text = seMaterial.Name;
if (seMaterial.MaterialData is SEModelSimpleMaterial)
{
if (((SEModelSimpleMaterial)seMaterial.MaterialData).DiffuseMap != string.Empty)
{
string TextureName = ((SEModelSimpleMaterial)seMaterial.MaterialData).DiffuseMap;
material.TextureMaps.Add(new STGenericMatTexture()
{
Name = TextureName,
Type = STGenericMatTexture.TextureType.Diffuse
});
}
if (((SEModelSimpleMaterial)seMaterial.MaterialData).NormalMap != string.Empty)
{
string TextureName = ((SEModelSimpleMaterial)seMaterial.MaterialData).NormalMap;
material.TextureMaps.Add(new STGenericMatTexture()
{
Name = TextureName,
Type = STGenericMatTexture.TextureType.Normal
});
}
if (((SEModelSimpleMaterial)seMaterial.MaterialData).SpecularMap != string.Empty)
{
string TextureName = ((SEModelSimpleMaterial)seMaterial.MaterialData).SpecularMap;
material.TextureMaps.Add(new STGenericMatTexture()
{
Name = TextureName,
Type = STGenericMatTexture.TextureType.Specular
});
}
}
return material;
}
public STGenericObject CreateGenericObject(SELib.SEModel seModel, SELib.SEModelMesh seMesh)
{
int Index = seModel.Meshes.IndexOf(seMesh);
STGenericObject mesh = new STGenericObject();
mesh.ObjectName = $"Mesh_{Index}";
if (seMesh.MaterialReferenceIndicies.Count > 0)
mesh.MaterialIndex = seMesh.MaterialReferenceIndicies[0];
mesh.HasPos = true;
for (int v = 0; v < seMesh.VertexCount; v++)
{
if (seMesh.Verticies[v].UVSets.Count > 0)
mesh.HasUv0 = true;
if (seMesh.Verticies[v].Weights.Count > 0)
{
mesh.HasIndices = true;
for (int w = 0; w < seMesh.Verticies[v].WeightCount; w++)
{
if (seMesh.Verticies[v].Weights[w].BoneWeight != 0)
mesh.HasWeights = true;
}
}
if (seMesh.Verticies[v].VertexColor != SELib.Utilities.Color.White)
mesh.HasVertColors = true;
if (seMesh.Verticies[v].VertexNormal != SELib.Utilities.Vector3.Zero)
mesh.HasNrm = true;
Vertex vertex = new Vertex();
mesh.vertices.Add(vertex);
vertex.pos = ToTKVector3(seMesh.Verticies[v].Position);
vertex.nrm = ToTKVector3(seMesh.Verticies[v].VertexNormal);
vertex.col = ToTKVector4(seMesh.Verticies[v].VertexColor);
for (int u = 0; u < seMesh.Verticies[v].UVSetCount; u++)
{
if (u == 0)
vertex.uv0 = ToTKVector2(seMesh.Verticies[v].UVSets[u]);
if (u == 1)
vertex.uv1 = ToTKVector2(seMesh.Verticies[v].UVSets[u]);
if (u == 2)
vertex.uv2 = ToTKVector2(seMesh.Verticies[v].UVSets[u]);
}
for (int w = 0; w < seMesh.Verticies[v].WeightCount; w++)
{
//Get the bone name from the index. Indices for formats get set after the importer
string BoneName = seModel.Bones[(int)seMesh.Verticies[v].Weights[w].BoneIndex].BoneName;
float BoneWeight = seMesh.Verticies[v].Weights[w].BoneWeight;
vertex.boneNames.Add(BoneName);
vertex.boneWeights.Add(BoneWeight);
}
}
mesh.lodMeshes = new List<STGenericObject.LOD_Mesh>();
var lodMesh = new STGenericObject.LOD_Mesh();
lodMesh.PrimitiveType = STPolygonType.Triangle;
mesh.lodMeshes.Add(lodMesh);
for (int f = 0; f < seMesh.FaceCount; f++)
{
lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex1);
lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex2);
lodMesh.faces.Add((int)seMesh.Faces[f].FaceIndex3);
}
return mesh;
}
private Vector2 ToTKVector2(SELib.Utilities.Vector2 value) {
return new Vector2((float)value.X, (float)value.Y);
}
private Vector3 ToTKVector3(SELib.Utilities.Vector3 value) {
return new Vector3((float)value.X, (float)value.Y, (float)value.Z);
}
private Vector4 ToTKVector4(SELib.Utilities.Color value) {
return new Vector4((float)(value.R / 255),
(float)(value.G / 255),
(float)(value.B / 255),
(float)(value.A / 255));
}
private static Vector3 ToEular(SELib.Utilities.Quaternion selibQuat)
{
OpenTK.Quaternion q = new Quaternion((float)selibQuat.X, (float)selibQuat.Y, (float)selibQuat.Z, (float)selibQuat.W);
Matrix4 mat = Matrix4.CreateFromQuaternion(q);
float x, y, z;
y = (float)Math.Asin(Clamp(mat.M13, -1, 1));
if (Math.Abs(mat.M13) < 0.99999)
{
x = (float)Math.Atan2(-mat.M23, mat.M33);
z = (float)Math.Atan2(-mat.M12, mat.M11);
}
else
{
x = (float)Math.Atan2(mat.M32, mat.M22);
z = 0;
}
return new Vector3(x, y, z) * -1;
}
private static float Clamp(float v, float min, float max)
{
if (v < min) return min;
if (v > max) return max;
return v;
}
}
}

View File

@ -226,6 +226,7 @@
<Compile Include="FileFormats\DAE\DAE.cs" />
<Compile Include="FileFormats\OBJ.cs" />
<Compile Include="FileFormats\R4G4.cs" />
<Compile Include="FileFormats\SEModel.cs" />
<Compile Include="FileFormats\SizeTables\RSTB.cs" />
<Compile Include="FileFormats\SizeTables\TPFileSizeTable.cs" />
<Compile Include="FileFormats\TGA.cs" />

View File

@ -383,9 +383,27 @@ void main()
if (RenderAsLighting)
{
fragColor.rgb = specularTerm;
diffuseIblColor = texture(irradianceMap, N).rgb;
diffuseTerm = diffuseIblColor * vec3(0.5);
diffuseTerm *= kD;
diffuseTerm *= cavity;
diffuseTerm *= ao;
diffuseTerm *= shadow;
diffuseTerm += LightingDiffuse;
// Adjust for metalness.
diffuseTerm *= clamp(1 - metallic, 0, 1);
diffuseTerm *= vec3(1) - kS.xxx;
fragColor.rgb = vec3(0);
fragColor.rgb += diffuseTerm;
fragColor.rgb += specularTerm;
fragColor.rgb += emissionTerm;
// Global brightness adjustment.
fragColor.rgb *= 1.5;
// HDR tonemapping
fragColor.rgb = fragColor.rgb / (fragColor.rgb + vec3(1.0));
// Convert back to sRGB.
fragColor.rgb = pow(fragColor.rgb, vec3(1 / gamma));
}