diff --git a/.vs/Switch_Toolbox/v15/.suo b/.vs/Switch_Toolbox/v15/.suo
index bf033ec9..ef2dd498 100644
Binary files a/.vs/Switch_Toolbox/v15/.suo and b/.vs/Switch_Toolbox/v15/.suo differ
diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide
index 11aed00e..48160b39 100644
Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide differ
diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm
index c027fd38..04c0b39c 100644
Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-shm differ
diff --git a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal
index 3348179f..c0deabbf 100644
Binary files a/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal and b/.vs/Switch_Toolbox/v15/Server/sqlite3/storage.ide-wal differ
diff --git a/Switch_FileFormatsMain/GL/BFRES_Render.cs b/Switch_FileFormatsMain/GL/BFRES_Render.cs
index 6368bc82..8ecc804c 100644
--- a/Switch_FileFormatsMain/GL/BFRES_Render.cs
+++ b/Switch_FileFormatsMain/GL/BFRES_Render.cs
@@ -67,6 +67,8 @@ namespace FirstPlugin
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out ibo_elements);
+ TransformBones();
+
UpdateVertexData();
UpdateTextureMaps();
}
@@ -82,6 +84,17 @@ namespace FirstPlugin
GL.DeleteBuffer(ibo_elements);
}
+ private void TransformBones()
+ {
+ foreach (var model in models)
+ {
+ foreach (var bone in model.Skeleton.bones)
+ {
+ bone.ModelMatrix = ModelTransform;
+ }
+ }
+ }
+
#region Rendering
diff --git a/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache b/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache
index e71cf8f5..5bda6efb 100644
Binary files a/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache and b/Switch_FileFormatsMain/obj/Release/DesignTimeResolveAssemblyReferences.cache differ
diff --git a/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache b/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache
index 08423834..2450413e 100644
Binary files a/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache and b/Switch_FileFormatsMain/obj/Release/Switch_FileFormatsMain.csprojAssemblyReference.cache differ
diff --git a/Switch_Toolbox_Library/FileFormats/DDS.cs b/Switch_Toolbox_Library/FileFormats/DDS.cs
index 0c036127..d3095399 100644
--- a/Switch_Toolbox_Library/FileFormats/DDS.cs
+++ b/Switch_Toolbox_Library/FileFormats/DDS.cs
@@ -492,11 +492,6 @@ namespace Switch_Toolbox.Library
ArrayCount = 1;
- if (header.caps2 == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
- {
- ArrayCount = 6;
- }
-
int DX10HeaderSize = 0;
if (header.ddspf.fourCC == FOURCC_DX10)
{
@@ -506,6 +501,11 @@ namespace Switch_Toolbox.Library
ReadDX10Header(reader);
}
+ if (header.caps2 == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
+ {
+ ArrayCount = 6;
+ }
+
bool IsCompressed = false;
bool HasLuminance = false;
bool HasAlpha = false;
@@ -678,6 +678,12 @@ namespace Switch_Toolbox.Library
case TEX_FORMAT.BC3_UNORM_SRGB:
pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
break;
+ case TEX_FORMAT.BC6H_UF16:
+ pixelInternalFormat = PixelInternalFormat.CompressedRgbBptcUnsignedFloat;
+ break;
+ case TEX_FORMAT.BC6H_SF16:
+ pixelInternalFormat = PixelInternalFormat.CompressedRgbBptcUnsignedFloat;
+ break;
default:
throw new Exception("Unsupported format! " + dds.Format);
}
@@ -693,8 +699,22 @@ namespace Switch_Toolbox.Library
}
else
{
- texture.LoadImageData((int)dds.header.width, new SFGraphics.GLObjects.Textures.TextureFormats.TextureFormatUncompressed(PixelInternalFormat.Rgba,
- OpenTK.Graphics.OpenGL.PixelFormat.Rgba, OpenTK.Graphics.OpenGL.PixelType.UnsignedByte),
+ PixelInternalFormat pixelInternalFormat = PixelInternalFormat.Rgba;
+ PixelType pixelType = PixelType.UnsignedByte;
+ PixelFormat pixelFormat = PixelFormat.Rgba;
+
+ switch (dds.Format)
+ {
+ case TEX_FORMAT.R32G32B32A32_FLOAT:
+ pixelInternalFormat = PixelInternalFormat.Rgba32f;
+ pixelType = PixelType.Float;
+ break;
+ default:
+ throw new Exception("Unsupported format! " + dds.Format);
+ }
+
+ texture.LoadImageData((int)dds.header.width, new SFGraphics.GLObjects.Textures.TextureFormats.TextureFormatUncompressed(pixelInternalFormat,
+ pixelFormat, pixelType),
cubemap[0].mipmaps[0],
cubemap[1].mipmaps[0],
cubemap[2].mipmaps[0],
diff --git a/Switch_Toolbox_Library/Generics/OpenGLTexture.cs b/Switch_Toolbox_Library/Generics/OpenGLTexture.cs
new file mode 100644
index 00000000..5f55d1c4
--- /dev/null
+++ b/Switch_Toolbox_Library/Generics/OpenGLTexture.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OpenTK.Graphics.OpenGL;
+
+namespace Switch_Toolbox.Library
+{
+ //Class based on https://github.com/ScanMountGoat/SFGraphics/blob/2cba15420b40d42c4254583336dbc3ca6a0d28dc/Projects/SFGraphics/GLObjects/Textures/Texture.cs
+ //This makes managing textures easier
+ public class OpenGLTexture
+ {
+ public int TexID;
+
+ public int Width { get; protected set; }
+
+ public int Height { get; protected set; }
+
+ public TextureTarget TextureTarget { get; }
+
+ private TextureMinFilter minFilter;
+ public TextureMinFilter MinFilter
+ {
+ get { return minFilter; }
+ set
+ {
+ minFilter = value;
+ SetTexParameter(TextureParameterName.TextureMinFilter, (int)value);
+ }
+ }
+
+ private TextureMagFilter magFilter;
+ public TextureMagFilter MagFilter
+ {
+ get { return magFilter; }
+ set
+ {
+ magFilter = value;
+ SetTexParameter(TextureParameterName.TextureMagFilter, (int)value);
+ }
+ }
+
+ private TextureWrapMode textureWrapS;
+ public TextureWrapMode TextureWrapS
+ {
+ get { return textureWrapS; }
+ set
+ {
+ textureWrapS = value;
+ SetTexParameter(TextureParameterName.TextureWrapS, (int)value);
+ }
+ }
+
+ private TextureWrapMode textureWrapT;
+ public TextureWrapMode TextureWrapT
+ {
+ get { return textureWrapT; }
+ set
+ {
+ textureWrapT = value;
+ SetTexParameter(TextureParameterName.TextureWrapT, (int)value);
+ }
+ }
+
+ private TextureWrapMode textureWrapR;
+ public TextureWrapMode TextureWrapR
+ {
+ get { return textureWrapR; }
+ set
+ {
+ textureWrapR = value;
+ SetTexParameter(TextureParameterName.TextureWrapR, (int)value);
+ }
+ }
+
+ public void Bind()
+ {
+ GL.BindTexture(TextureTarget, TexID);
+ }
+
+ private void SetTexParameter(TextureParameterName param, int value)
+ {
+ Bind();
+ GL.TexParameter(TextureTarget, param, value);
+ }
+ }
+}
diff --git a/Switch_Toolbox_Library/Generics/STBone.cs b/Switch_Toolbox_Library/Generics/STBone.cs
index ec11513c..85a1d118 100644
--- a/Switch_Toolbox_Library/Generics/STBone.cs
+++ b/Switch_Toolbox_Library/Generics/STBone.cs
@@ -37,6 +37,9 @@ namespace Switch_Toolbox.Library
public Quaternion rot = Quaternion.FromMatrix(Matrix3.Zero);
public Matrix4 Transform, invert;
+ //Used for shifting models with the bones in the shader
+ public Matrix4 ModelMatrix = Matrix4.Identity;
+
public Vector3 GetPosition()
{
return pos;
diff --git a/Switch_Toolbox_Library/Generics/STSkeleton.cs b/Switch_Toolbox_Library/Generics/STSkeleton.cs
index c3d90b0e..4b5276bc 100644
--- a/Switch_Toolbox_Library/Generics/STSkeleton.cs
+++ b/Switch_Toolbox_Library/Generics/STSkeleton.cs
@@ -51,6 +51,7 @@ namespace Switch_Toolbox.Library
uniform mat4 bone;
uniform mat4 parent;
uniform mat4 rotation;
+ uniform mat4 ModelMatrix;
uniform int hasParent;
uniform float scale;
@@ -63,7 +64,7 @@ namespace Switch_Toolbox.Library
else
position = bone * rotation * vec4((point.xyz - vec3(0, 1, 0)) * scale, 1);
}
- gl_Position = mtxCam * mtxMdl * vec4(position.xyz, 1);
+ gl_Position = mtxCam * ModelMatrix * mtxMdl * vec4(position.xyz, 1);
}");
@@ -236,7 +237,9 @@ namespace Switch_Toolbox.Library
solidColorShaderProgram.SetVector4("boneColor", ColorUtility.ToVector4(boneColor));
solidColorShaderProgram.SetFloat("scale", Runtime.bonePointSize);
+ solidColorShaderProgram.SetMatrix4x4("ModelMatrix", ref bn.ModelMatrix);
+
Matrix4 transform = bn.Transform;
solidColorShaderProgram.SetMatrix4x4("bone", ref transform);
diff --git a/Switch_Toolbox_Library/Rendering/DrawableSkybox.cs b/Switch_Toolbox_Library/Rendering/DrawableSkybox.cs
index 25120071..b528bff2 100644
--- a/Switch_Toolbox_Library/Rendering/DrawableSkybox.cs
+++ b/Switch_Toolbox_Library/Rendering/DrawableSkybox.cs
@@ -43,6 +43,8 @@ namespace Switch_Toolbox.Library.Rendering
if (!Runtime.OpenTKInitialized || !Runtime.PBR.UseSkybox || pass == Pass.TRANSPARENT)
return;
+ GL.Disable(EnableCap.CullFace);
+
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
@@ -56,11 +58,12 @@ namespace Switch_Toolbox.Library.Rendering
// enable seamless cubemap sampling for lower mip levels in the pre-filter map.
GL.Enable(EnableCap.TextureCubeMapSeamless);
- Matrix4 proj = Matrix4.Identity;
- Matrix4 rot = Matrix4.CreateFromQuaternion(control.ModelMatrix.ExtractRotation());
+ Matrix4 proj = control.ProjectionMatrix;
+ // Matrix4 rot = Matrix4.CreateFromQuaternion(control.ModelMatrix.ExtractRotation());
+ Matrix4 rot = new Matrix4(new Matrix3(control.CameraMatrix));
- GL.UniformMatrix4(defaultShaderProgram["projection"], false, ref proj);
- GL.UniformMatrix4(defaultShaderProgram["rotView"], false, ref rot);
+ defaultShaderProgram.SetMatrix4x4("projection", ref proj);
+ defaultShaderProgram.SetMatrix4x4("rotView", ref rot);
if (Runtime.PBR.UseDiffuseSkyTexture)
{
diff --git a/Switch_Toolbox_Library/Rendering/PBRMapGenerator.cs b/Switch_Toolbox_Library/Rendering/PBRMapGenerator.cs
new file mode 100644
index 00000000..b5b8bebe
--- /dev/null
+++ b/Switch_Toolbox_Library/Rendering/PBRMapGenerator.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using GL_EditorFramework.Interfaces;
+using GL_EditorFramework.GL_Core;
+using OpenTK.Graphics.OpenGL;
+using OpenTK;
+
+namespace Switch_Toolbox.Library.Rendering
+{
+ public class PBRMapGenerator
+ {
+ public int BrdfLUTMap = -1;
+
+ private ShaderProgram BrdfShader;
+
+ private int captureFBO = 1;
+ private int captureRBO = 1;
+
+ private bool IsBufferCreated()
+ {
+ return (captureFBO != -1 && captureRBO != -1);
+ }
+
+ private void GenerateFrameBuffer()
+ {
+ // setup framebuffer
+ GL.GenFramebuffers(1, out captureFBO);
+ GL.GenFramebuffers(1, out captureRBO);
+ }
+
+ public void GeneratImageBasedLightingMap()
+ {
+ // enable seamless cubemap sampling for lower mip levels in the pre-filter map.
+ GL.Enable(EnableCap.TextureCubeMapSeamless);
+
+ if (!IsBufferCreated())
+ GenerateFrameBuffer();
+ }
+
+ public void GenerateBrdfMap()
+ {
+ if (!IsBufferCreated())
+ GenerateFrameBuffer();
+
+ GL.UseProgram(BrdfShader.program);
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ RenderQuad();
+
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
+
+ BrdfLUTMap = LoadBrdfLUTTexture();
+
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, captureFBO);
+ GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, captureRBO);
+ GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent24, 512, 512);
+ GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, BrdfLUTMap, 0);
+
+ Matrix4 proj = Matrix4.Identity;
+ }
+
+ public static int LoadBrdfLUTTexture()
+ {
+ int texture;
+ GL.GenTextures(1, out texture);
+ GL.BindTexture(TextureTarget.Texture2D, texture);
+ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rg32f, 512, 512, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rg, PixelType.Float, (IntPtr)0);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
+
+ return texture;
+ }
+
+ private static void RenderQuad()
+ {
+ int quadVAO = 0;
+ int quadVBO;
+ if (quadVAO == 0)
+ {
+ float[] vertices = {
+ // positions // texture Coords
+ -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
+ 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+ };
+
+ GL.GenVertexArrays(1, out quadVAO);
+ GL.GenBuffers(1, out quadVBO);
+ GL.BindVertexArray(quadVAO);
+ GL.BindBuffer(BufferTarget.ArrayBuffer, quadVBO);
+ GL.BufferData(BufferTarget.ArrayBuffer, 4 * vertices.Length, vertices, BufferUsageHint.StaticDraw);
+ GL.EnableVertexAttribArray(0);
+ GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), (IntPtr)0);
+ GL.EnableVertexAttribArray(1);
+ GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), (IntPtr)(3 * sizeof(float)));
+ }
+ GL.BindVertexArray(quadVAO);
+ GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
+ GL.BindVertexArray(0);
+ }
+ }
+}
diff --git a/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj b/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj
index 520bec3f..974d79ea 100644
--- a/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj
+++ b/Switch_Toolbox_Library/Switch_Toolbox_Library.csproj
@@ -497,6 +497,7 @@
+
@@ -622,6 +623,7 @@
+
diff --git a/Toolbox/GUI/Settings.Designer.cs b/Toolbox/GUI/Settings.Designer.cs
index 0a67c54a..175d3327 100644
--- a/Toolbox/GUI/Settings.Designer.cs
+++ b/Toolbox/GUI/Settings.Designer.cs
@@ -93,6 +93,8 @@
this.tabPage3 = new System.Windows.Forms.TabPage();
this.stLabel13 = new Switch_Toolbox.Library.Forms.STLabel();
this.botwGamePathTB = new Switch_Toolbox.Library.Forms.STTextBox();
+ this.stContextMenuStrip1 = new Switch_Toolbox.Library.Forms.STContextMenuStrip(this.components);
+ this.clearSettingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.stLabel14 = new Switch_Toolbox.Library.Forms.STLabel();
this.tpGamePathTB = new Switch_Toolbox.Library.Forms.STTextBox();
this.stLabel12 = new Switch_Toolbox.Library.Forms.STLabel();
@@ -105,8 +107,6 @@
this.chkDiffyseSkybox = new Switch_Toolbox.Library.Forms.STCheckBox();
this.stLabel16 = new Switch_Toolbox.Library.Forms.STLabel();
this.diffuseCubemapPathTB = new Switch_Toolbox.Library.Forms.STTextBox();
- this.stContextMenuStrip1 = new Switch_Toolbox.Library.Forms.STContextMenuStrip(this.components);
- this.clearSettingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.chkUseSkyobx = new Switch_Toolbox.Library.Forms.STCheckBox();
this.stLabel15 = new Switch_Toolbox.Library.Forms.STLabel();
this.specularCubemapPathTB = new Switch_Toolbox.Library.Forms.STTextBox();
@@ -130,8 +130,8 @@
((System.ComponentModel.ISupportInitialize)(this.bgGradientBottom)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.bgGradientTop)).BeginInit();
this.tabPage3.SuspendLayout();
- this.tabPage4.SuspendLayout();
this.stContextMenuStrip1.SuspendLayout();
+ this.tabPage4.SuspendLayout();
this.SuspendLayout();
//
// contentContainer
@@ -988,6 +988,20 @@
this.botwGamePathTB.TabIndex = 8;
this.botwGamePathTB.Click += new System.EventHandler(this.botwGamePathTB_Click);
//
+ // stContextMenuStrip1
+ //
+ this.stContextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.clearSettingToolStripMenuItem});
+ this.stContextMenuStrip1.Name = "stContextMenuStrip1";
+ this.stContextMenuStrip1.Size = new System.Drawing.Size(142, 26);
+ //
+ // clearSettingToolStripMenuItem
+ //
+ this.clearSettingToolStripMenuItem.Name = "clearSettingToolStripMenuItem";
+ this.clearSettingToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
+ this.clearSettingToolStripMenuItem.Text = "Clear Setting";
+ this.clearSettingToolStripMenuItem.Click += new System.EventHandler(this.clearSettingToolStripMenuItem_Click);
+ //
// stLabel14
//
this.stLabel14.AutoSize = true;
@@ -1098,34 +1112,20 @@
this.stLabel16.AutoSize = true;
this.stLabel16.Location = new System.Drawing.Point(16, 73);
this.stLabel16.Name = "stLabel16";
- this.stLabel16.Size = new System.Drawing.Size(129, 13);
+ this.stLabel16.Size = new System.Drawing.Size(150, 13);
this.stLabel16.TabIndex = 4;
- this.stLabel16.Text = "Custom Diffuse Cubemap:";
+ this.stLabel16.Text = "Diffuse Cubemap (Irradiance) :";
//
// diffuseCubemapPathTB
//
this.diffuseCubemapPathTB.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.diffuseCubemapPathTB.ContextMenuStrip = this.stContextMenuStrip1;
- this.diffuseCubemapPathTB.Location = new System.Drawing.Point(160, 71);
+ this.diffuseCubemapPathTB.Location = new System.Drawing.Point(181, 73);
this.diffuseCubemapPathTB.Name = "diffuseCubemapPathTB";
this.diffuseCubemapPathTB.Size = new System.Drawing.Size(197, 20);
this.diffuseCubemapPathTB.TabIndex = 3;
this.diffuseCubemapPathTB.Click += new System.EventHandler(this.diffuseCubemapPathTBB_Click);
//
- // stContextMenuStrip1
- //
- this.stContextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.clearSettingToolStripMenuItem});
- this.stContextMenuStrip1.Name = "stContextMenuStrip1";
- this.stContextMenuStrip1.Size = new System.Drawing.Size(142, 26);
- //
- // clearSettingToolStripMenuItem
- //
- this.clearSettingToolStripMenuItem.Name = "clearSettingToolStripMenuItem";
- this.clearSettingToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
- this.clearSettingToolStripMenuItem.Text = "Clear Setting";
- this.clearSettingToolStripMenuItem.Click += new System.EventHandler(this.clearSettingToolStripMenuItem_Click);
- //
// chkUseSkyobx
//
this.chkUseSkyobx.AutoSize = true;
@@ -1142,15 +1142,15 @@
this.stLabel15.AutoSize = true;
this.stLabel15.Location = new System.Drawing.Point(16, 47);
this.stLabel15.Name = "stLabel15";
- this.stLabel15.Size = new System.Drawing.Size(138, 13);
+ this.stLabel15.Size = new System.Drawing.Size(159, 13);
this.stLabel15.TabIndex = 1;
- this.stLabel15.Text = "Custom Specular Cubemap:";
+ this.stLabel15.Text = "Specular Cubemap {Radiance) :";
//
// specularCubemapPathTB
//
this.specularCubemapPathTB.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.specularCubemapPathTB.ContextMenuStrip = this.stContextMenuStrip1;
- this.specularCubemapPathTB.Location = new System.Drawing.Point(160, 45);
+ this.specularCubemapPathTB.Location = new System.Drawing.Point(181, 45);
this.specularCubemapPathTB.Name = "specularCubemapPathTB";
this.specularCubemapPathTB.Size = new System.Drawing.Size(197, 20);
this.specularCubemapPathTB.TabIndex = 0;
@@ -1192,9 +1192,9 @@
((System.ComponentModel.ISupportInitialize)(this.bgGradientTop)).EndInit();
this.tabPage3.ResumeLayout(false);
this.tabPage3.PerformLayout();
+ this.stContextMenuStrip1.ResumeLayout(false);
this.tabPage4.ResumeLayout(false);
this.tabPage4.PerformLayout();
- this.stContextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
}
diff --git a/Toolbox/Shader/Bfres/BFRES.vert b/Toolbox/Shader/Bfres/BFRES.vert
index 081b1836..eb6dcfef 100644
--- a/Toolbox/Shader/Bfres/BFRES.vert
+++ b/Toolbox/Shader/Bfres/BFRES.vert
@@ -138,15 +138,15 @@ void main()
if (vBone.x != -1.0)
objPos = skin(vPosition, index);
- vec4 position = mtxCam * mtxMdl * vec4(objPos.xyz, 1.0);
+ vec4 position = mtxCam * (mtxMdl * vec4(objPos.xyz, 1.0));
normal = vNormal;
+
viewNormal = mat3(sphereMatrix) * normal.xyz;
if(vBone.x != -1.0)
normal = normalize((skinNRM(vNormal.xyz, index)).xyz);
-
-
+
if (RigidSkinning == 1)
{
position = mtxCam * mtxMdl * (bones[index.x] * vec4(vPosition, 1.0));
@@ -156,9 +156,10 @@ void main()
{
position = mtxCam * mtxMdl * (SingleBoneBindTransform * vec4(vPosition, 1.0));
normal = mat3(SingleBoneBindTransform) * vNormal.xyz * 1;
- //normal = normalize(normal);
}
+ normal = normalize(mat3(mtxMdl) * normal.xyz);
+
gl_Position =position;
f_texcoord0 = vUV0;
diff --git a/Toolbox/Shader/Bfres/BFRES_PBR.frag b/Toolbox/Shader/Bfres/BFRES_PBR.frag
index fa50c0d1..3b4e338f 100644
--- a/Toolbox/Shader/Bfres/BFRES_PBR.frag
+++ b/Toolbox/Shader/Bfres/BFRES_PBR.frag
@@ -286,10 +286,11 @@ void main()
vec3 V = normalize(I); // view
vec3 L = normalize(specLightDirection); // Light
vec3 H = normalize(specLightDirection + I); // half angle
- vec3 R = reflect(I, N); // reflection
+ vec3 R = reflect(-I, N); // reflection
vec3 f0 = mix(vec3(0.04), albedo, metallic); // dialectric
vec3 kS = FresnelSchlickRoughness(max(dot(N, V), 0.0), f0, roughness);
+
vec3 kD = 1.0 - kS;
kD *= 1.0 - metallic;
@@ -306,7 +307,7 @@ void main()
// Diffuse pass
vec3 diffuseIblColor = texture(irradianceMap, N).rgb;
vec3 diffuseTerm = diffuseIblColor * albedo;
- // diffuseTerm *= kD;
+ diffuseTerm *= kD;
diffuseTerm *= cavity;
diffuseTerm *= ao;
diffuseTerm *= shadow;
@@ -323,7 +324,7 @@ void main()
vec2 envBRDF = texture(brdfLUT, vec2(max(dot(N, V), 0.0), roughness)).rg;
vec3 brdfTerm = (kS * envBRDF.x + envBRDF.y);
- vec3 specularTerm = specularIblColor * brdfTerm * specIntensity * 0.7f;
+ vec3 specularTerm = specularIblColor * (kS * brdfTerm.x + brdfTerm.y) * specIntensity;
// Add render passes.
@@ -339,6 +340,8 @@ void main()
fragColor.rgb *= min(boneWeightsColored, vec3(1));
+ // HDR tonemapping
+ fragColor.rgb = fragColor.rgb / (fragColor.rgb + vec3(1.0));
// Convert back to sRGB.
fragColor.rgb = pow(fragColor.rgb, vec3(1 / gamma));
diff --git a/Toolbox/Shader/HDRSkyBox/HDRSkyBox.vert b/Toolbox/Shader/HDRSkyBox/HDRSkyBox.vert
index 72667164..4dfcea30 100644
--- a/Toolbox/Shader/HDRSkyBox/HDRSkyBox.vert
+++ b/Toolbox/Shader/HDRSkyBox/HDRSkyBox.vert
@@ -3,6 +3,7 @@ layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 rotView;
+uniform mat4 mtxCam;
out vec3 TexCoords;
diff --git a/Toolbox/Shader/PBR/HDR.frag b/Toolbox/Shader/PBR/HDR.frag
new file mode 100644
index 00000000..8ec8f754
--- /dev/null
+++ b/Toolbox/Shader/PBR/HDR.frag
@@ -0,0 +1,22 @@
+#version 330 core
+out vec4 FragColor;
+in vec3 localPos;
+
+uniform sampler2D equirectangularMap;
+
+const vec2 invAtan = vec2(0.1591, 0.3183);
+vec2 SampleSphericalMap(vec3 v)
+{
+ vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
+ uv *= invAtan;
+ uv += 0.5;
+ return uv;
+}
+
+void main()
+{
+ vec2 uv = SampleSphericalMap(normalize(localPos)); // make sure to normalize localPos
+ vec3 color = texture(equirectangularMap, uv).rgb;
+
+ FragColor = vec4(color, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/HDR.vert b/Toolbox/Shader/PBR/HDR.vert
new file mode 100644
index 00000000..7cdc81f3
--- /dev/null
+++ b/Toolbox/Shader/PBR/HDR.vert
@@ -0,0 +1,13 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+
+out vec3 localPos;
+
+uniform mat4 projection;
+uniform mat4 view;
+
+void main()
+{
+ localPos = aPos;
+ gl_Position = projection * view * vec4(localPos, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/brdf.frag b/Toolbox/Shader/PBR/brdf.frag
new file mode 100644
index 00000000..524f2859
--- /dev/null
+++ b/Toolbox/Shader/PBR/brdf.frag
@@ -0,0 +1,113 @@
+#version 330 core
+out vec2 FragColor;
+in vec2 TexCoords;
+
+const float PI = 3.14159265359;
+// ----------------------------------------------------------------------------
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+// efficient VanDerCorpus calculation.
+float RadicalInverse_VdC(uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+// ----------------------------------------------------------------------------
+vec2 Hammersley(uint i, uint N)
+{
+ return vec2(float(i)/float(N), RadicalInverse_VdC(i));
+}
+// ----------------------------------------------------------------------------
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
+{
+ float a = roughness*roughness;
+
+ float phi = 2.0 * PI * Xi.x;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
+
+ // from spherical coordinates to cartesian coordinates - halfway vector
+ vec3 H;
+ H.x = cos(phi) * sinTheta;
+ H.y = sin(phi) * sinTheta;
+ H.z = cosTheta;
+
+ // from tangent-space H vector to world-space sample vector
+ vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangent = normalize(cross(up, N));
+ vec3 bitangent = cross(N, tangent);
+
+ vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
+ return normalize(sampleVec);
+}
+// ----------------------------------------------------------------------------
+float GeometrySchlickGGX(float NdotV, float roughness)
+{
+ // note that we use a different k for IBL
+ float a = roughness;
+ float k = (a * a) / 2.0;
+
+ float nom = NdotV;
+ float denom = NdotV * (1.0 - k) + k;
+
+ return nom / denom;
+}
+// ----------------------------------------------------------------------------
+float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
+{
+ float NdotV = max(dot(N, V), 0.0);
+ float NdotL = max(dot(N, L), 0.0);
+ float ggx2 = GeometrySchlickGGX(NdotV, roughness);
+ float ggx1 = GeometrySchlickGGX(NdotL, roughness);
+
+ return ggx1 * ggx2;
+}
+// ----------------------------------------------------------------------------
+vec2 IntegrateBRDF(float NdotV, float roughness)
+{
+ vec3 V;
+ V.x = sqrt(1.0 - NdotV*NdotV);
+ V.y = 0.0;
+ V.z = NdotV;
+
+ float A = 0.0;
+ float B = 0.0;
+
+ vec3 N = vec3(0.0, 0.0, 1.0);
+
+ const uint SAMPLE_COUNT = 1024u;
+ for(uint i = 0u; i < SAMPLE_COUNT; ++i)
+ {
+ // generates a sample vector that's biased towards the
+ // preferred alignment direction (importance sampling).
+ vec2 Xi = Hammersley(i, SAMPLE_COUNT);
+ vec3 H = ImportanceSampleGGX(Xi, N, roughness);
+ vec3 L = normalize(2.0 * dot(V, H) * H - V);
+
+ float NdotL = max(L.z, 0.0);
+ float NdotH = max(H.z, 0.0);
+ float VdotH = max(dot(V, H), 0.0);
+
+ if(NdotL > 0.0)
+ {
+ float G = GeometrySmith(N, V, L, roughness);
+ float G_Vis = (G * VdotH) / (NdotH * NdotV);
+ float Fc = pow(1.0 - VdotH, 5.0);
+
+ A += (1.0 - Fc) * G_Vis;
+ B += Fc * G_Vis;
+ }
+ }
+ A /= float(SAMPLE_COUNT);
+ B /= float(SAMPLE_COUNT);
+ return vec2(A, B);
+}
+// ----------------------------------------------------------------------------
+void main()
+{
+ vec2 integratedBRDF = IntegrateBRDF(TexCoords.x, TexCoords.y);
+ FragColor = integratedBRDF;
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/brdf.vert b/Toolbox/Shader/PBR/brdf.vert
new file mode 100644
index 00000000..553e3a65
--- /dev/null
+++ b/Toolbox/Shader/PBR/brdf.vert
@@ -0,0 +1,11 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+layout (location = 1) in vec2 aTexCoords;
+
+out vec2 TexCoords;
+
+void main()
+{
+ TexCoords = aTexCoords;
+ gl_Position = vec4(aPos, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/irradianceShader.frag b/Toolbox/Shader/PBR/irradianceShader.frag
new file mode 100644
index 00000000..6ba88776
--- /dev/null
+++ b/Toolbox/Shader/PBR/irradianceShader.frag
@@ -0,0 +1,43 @@
+#version 330 core
+out vec4 FragColor;
+in vec3 WorldPos;
+
+uniform samplerCube environmentMap;
+
+const float PI = 3.14159265359;
+
+void main()
+{
+ // The world vector acts as the normal of a tangent surface
+ // from the origin, aligned to WorldPos. Given this normal, calculate all
+ // incoming radiance of the environment. The result of this radiance
+ // is the radiance of light coming from -Normal direction, which is what
+ // we use in the PBR shader to sample irradiance.
+ vec3 N = normalize(WorldPos);
+
+ vec3 irradiance = vec3(0.0);
+
+ // tangent space calculation from origin point
+ vec3 up = vec3(0.0, 1.0, 0.0);
+ vec3 right = cross(up, N);
+ up = cross(N, right);
+
+ float sampleDelta = 0.025;
+ float nrSamples = 0.0;
+ for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
+ {
+ for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)
+ {
+ // spherical to cartesian (in tangent space)
+ vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
+ // tangent space to world
+ vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
+
+ irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
+ nrSamples++;
+ }
+ }
+ irradiance = PI * irradiance * (1.0 / float(nrSamples));
+
+ FragColor = vec4(irradiance, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/irradianceShader.vert b/Toolbox/Shader/PBR/irradianceShader.vert
new file mode 100644
index 00000000..9d789e76
--- /dev/null
+++ b/Toolbox/Shader/PBR/irradianceShader.vert
@@ -0,0 +1,13 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+
+out vec3 WorldPos;
+
+uniform mat4 projection;
+uniform mat4 view;
+
+void main()
+{
+ WorldPos = aPos;
+ gl_Position = projection * view * vec4(WorldPos, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/preFilter.frag b/Toolbox/Shader/PBR/preFilter.frag
new file mode 100644
index 00000000..edc1e59a
--- /dev/null
+++ b/Toolbox/Shader/PBR/preFilter.frag
@@ -0,0 +1,106 @@
+#version 330 core
+out vec4 FragColor;
+in vec3 WorldPos;
+
+uniform samplerCube environmentMap;
+uniform float roughness;
+
+const float PI = 3.14159265359;
+// ----------------------------------------------------------------------------
+float DistributionGGX(vec3 N, vec3 H, float roughness)
+{
+ float a = roughness*roughness;
+ float a2 = a*a;
+ float NdotH = max(dot(N, H), 0.0);
+ float NdotH2 = NdotH*NdotH;
+
+ float nom = a2;
+ float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+ denom = PI * denom * denom;
+
+ return nom / denom;
+}
+// ----------------------------------------------------------------------------
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+// efficient VanDerCorpus calculation.
+float RadicalInverse_VdC(uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+// ----------------------------------------------------------------------------
+vec2 Hammersley(uint i, uint N)
+{
+ return vec2(float(i)/float(N), RadicalInverse_VdC(i));
+}
+// ----------------------------------------------------------------------------
+vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
+{
+ float a = roughness*roughness;
+
+ float phi = 2.0 * PI * Xi.x;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
+
+ // from spherical coordinates to cartesian coordinates - halfway vector
+ vec3 H;
+ H.x = cos(phi) * sinTheta;
+ H.y = sin(phi) * sinTheta;
+ H.z = cosTheta;
+
+ // from tangent-space H vector to world-space sample vector
+ vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangent = normalize(cross(up, N));
+ vec3 bitangent = cross(N, tangent);
+
+ vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
+ return normalize(sampleVec);
+}
+// ----------------------------------------------------------------------------
+void main()
+{
+ vec3 N = normalize(WorldPos);
+
+ // make the simplyfying assumption that V equals R equals the normal
+ vec3 R = N;
+ vec3 V = R;
+
+ const uint SAMPLE_COUNT = 1024u;
+ vec3 prefilteredColor = vec3(0.0);
+ float totalWeight = 0.0;
+
+ for(uint i = 0u; i < SAMPLE_COUNT; ++i)
+ {
+ // generates a sample vector that's biased towards the preferred alignment direction (importance sampling).
+ vec2 Xi = Hammersley(i, SAMPLE_COUNT);
+ vec3 H = ImportanceSampleGGX(Xi, N, roughness);
+ vec3 L = normalize(2.0 * dot(V, H) * H - V);
+
+ float NdotL = max(dot(N, L), 0.0);
+ if(NdotL > 0.0)
+ {
+ // sample from the environment's mip level based on roughness/pdf
+ float D = DistributionGGX(N, H, roughness);
+ float NdotH = max(dot(N, H), 0.0);
+ float HdotV = max(dot(H, V), 0.0);
+ float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
+
+ float resolution = 512.0; // resolution of source cubemap (per face)
+ float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
+ float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
+
+ float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
+
+ prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL;
+ totalWeight += NdotL;
+ }
+ }
+
+ prefilteredColor = prefilteredColor / totalWeight;
+
+ FragColor = vec4(prefilteredColor, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Shader/PBR/preFilter.vert b/Toolbox/Shader/PBR/preFilter.vert
new file mode 100644
index 00000000..9d789e76
--- /dev/null
+++ b/Toolbox/Shader/PBR/preFilter.vert
@@ -0,0 +1,13 @@
+#version 330 core
+layout (location = 0) in vec3 aPos;
+
+out vec3 WorldPos;
+
+uniform mat4 projection;
+uniform mat4 view;
+
+void main()
+{
+ WorldPos = aPos;
+ gl_Position = projection * view * vec4(WorldPos, 1.0);
+}
\ No newline at end of file
diff --git a/Toolbox/Toolbox.csproj b/Toolbox/Toolbox.csproj
index 7e38127a..51d17027 100644
--- a/Toolbox/Toolbox.csproj
+++ b/Toolbox/Toolbox.csproj
@@ -216,6 +216,30 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest