Improve lighting view in pbr shader. Start on SEModel support.
This commit is contained in:
parent
acc7dcd9c9
commit
ad1c4aed4e
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
Binary file not shown.
Binary file not shown.
238
Switch_Toolbox_Library/FileFormats/SEModel.cs
Normal file
238
Switch_Toolbox_Library/FileFormats/SEModel.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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" />
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user