pbr lights + gamma correction

This commit is contained in:
4sval 2022-11-11 04:45:38 +01:00
parent 65d20fbde8
commit 25de50818d
9 changed files with 110 additions and 91 deletions

@ -1 +1 @@
Subproject commit 68fa4d6fcaca164d13919ab5bc64e5ed0b32ab7f
Subproject commit cc744cfb54e219d7f5d9440d30c4cd55b56afb3c

View File

@ -1,4 +1,6 @@
#version 330 core
#define PI 3.1415926535897932384626433832795
#define MAX_UV_COUNT 8
in vec3 fPos;
@ -39,8 +41,6 @@ struct Parameters
Mask M;
bool HasM;
float Roughness;
float SpecularMult;
float EmissiveMult;
float UVScale;
@ -49,6 +49,8 @@ struct Parameters
uniform Parameters uParameters;
uniform int uNumTexCoords;
uniform vec3 uViewPos;
uniform vec3 uViewDir;
uniform bool bDiffuseOnly;
uniform bool bVertexColors;
uniform bool bVertexNormals;
uniform bool bVertexTangent;
@ -78,6 +80,59 @@ vec3 ComputeNormals(int layer)
return normalize(tbn * normal);
}
vec3 schlickFresnel(int layer, float vDotH)
{
vec3 f0 = vec3(0.04f);
return f0 + (1.0f - f0) * pow(clamp(1.0f - vDotH, 0.0f, 1.0f), 5);
}
float ggxDistribution(float roughness, float nDoth)
{
float alpha2 = roughness * roughness * roughness * roughness;
float d = nDoth * nDoth * (alpha2- 1.0f) + 1.0f;
return alpha2 / (PI * d * d);
}
float geomSmith(float roughness, float dp)
{
float k = (roughness + 1.0f) * (roughness + 1.0f) / 8.0f;
float denom = dp * (1.0f - k) + k;
return dp / denom;
}
vec3 CalcPBRLight(int layer, vec3 normals)
{
vec3 specular_masks = SamplerToVector(uParameters.SpecularMasks[layer].Sampler).rgb;
float roughness = max(0.0f, specular_masks.b);
vec3 intensity = vec3(1.0f) * 1.0f;
vec3 l = -uViewDir;
vec3 n = normals;
vec3 v = normalize(uViewPos - fPos);
vec3 h = normalize(v + l);
float nDotH = max(dot(n, h), 0.0f);
float vDotH = max(dot(v, h), 0.0f);
float nDotL = max(dot(n, l), 0.0f);
float nDotV = max(dot(n, v), 0.0f);
vec3 f = schlickFresnel(layer, vDotH);
vec3 kS = f;
vec3 kD = 1.0 - kS;
kD *= 1.0 - max(0.0f, dot(v, reflect(-v, normals)) * specular_masks.g);
vec3 specBrdfNom = ggxDistribution(roughness, nDotH) * f * geomSmith(roughness, nDotL) * geomSmith(roughness, nDotV);
float specBrdfDenom = 4.0f * nDotV * nDotL + 0.0001f;
vec3 specBrdf = specBrdfNom / specBrdfDenom;
vec3 fLambert = SamplerToVector(uParameters.Diffuse[layer].Sampler).rgb * uParameters.Diffuse[layer].Color.rgb;
vec3 diffuseBrdf = kD * fLambert / PI;
return (diffuseBrdf + specBrdf) * intensity * nDotL;
}
void main()
{
if (bVertexColors)
@ -99,13 +154,10 @@ void main()
else
{
int layer = LayerToIndex();
vec3 normals = ComputeNormals(layer);
vec4 diffuse = SamplerToVector(uParameters.Diffuse[layer].Sampler);
vec3 result = uParameters.Diffuse[layer].Color.rgb * diffuse.rgb;
vec3 normals = ComputeNormals(layer);
vec3 light_direction = normalize(uViewPos - fPos);
result += max(dot(normals, light_direction), 0.0f) * result;
if (uParameters.HasM)
{
vec3 m = SamplerToVector(uParameters.M.Sampler).rgb;
@ -117,20 +169,19 @@ void main()
result *= clamp(color * m.b, 0.0f, 1.0f);
}
result *= m.r * uParameters.M.AmbientOcclusion;
result += m.g * uParameters.M.Cavity;
if (m.r > 0.0f) result *= m.r * uParameters.M.AmbientOcclusion;
if (m.g > 0.0f) result += m.g * uParameters.M.Cavity;
}
vec3 reflect_direction = reflect(-light_direction, normals);
vec3 specular_masks = SamplerToVector(uParameters.SpecularMasks[layer].Sampler).rgb;
float specular = uParameters.SpecularMult * max(0.0f, specular_masks.r);
float metallic = max(0.0f, dot(light_direction, reflect_direction) * specular_masks.g);
float roughness = max(0.0f, uParameters.Roughness * specular_masks.b);
result += metallic * roughness * specular;
vec4 emissive = SamplerToVector(uParameters.Emissive[layer].Sampler);
result += uParameters.Emissive[layer].Color.rgb * emissive.rgb * uParameters.EmissiveMult;
FragColor = vec4(result, 1.0f);
if (!bDiffuseOnly)
{
result += CalcPBRLight(layer, normals);
}
result = result / (result + vec3(1.0f));
FragColor = vec4(pow(result, vec3(1.0f / 2.2f)), 1.0f);
}
}

View File

@ -24,10 +24,10 @@ out vec4 fColor;
void main()
{
vec3 pos = mix(vPos, vMorphTarget, uMorphTime);
gl_Position = uProjection * uView * vInstanceMatrix * vec4(pos, 1.0);
vec4 pos = vec4(mix(vPos, vMorphTarget, uMorphTime), 1.0);
gl_Position = uProjection * uView * vInstanceMatrix * pos;
fPos = vec3(vInstanceMatrix * vec4(pos, 1.0));
fPos = vec3(vInstanceMatrix * pos);
fNormal = mat3(transpose(inverse(vInstanceMatrix))) * vNormal;
fTangent = mat3(transpose(inverse(vInstanceMatrix))) * vTangent;
fTexCoords = vTexCoords;

View File

@ -15,12 +15,14 @@ public class Cache : IDisposable
public readonly Dictionary<FGuid, Texture> Textures;
private ETexturePlatform _platform;
private readonly FGame _game;
public Cache()
{
Models = new Dictionary<FGuid, Model>();
Textures = new Dictionary<FGuid, Texture>();
_platform = UserSettings.Default.OverridedPlatform;
_game = Services.ApplicationService.ApplicationView.CUE4Parse.Game;
}
public bool TryGetCachedModel(UStaticMesh o, out Model model)
@ -34,12 +36,13 @@ public class Cache : IDisposable
return model != null;
}
public bool TryGetCachedTexture(UTexture2D o, out Texture texture)
public bool TryGetCachedTexture(UTexture2D o, bool fix, out Texture texture)
{
var guid = o.LightingGuid;
if (!Textures.TryGetValue(guid, out texture) && o.GetFirstMip() is { } mip)
{
TextureDecoder.DecodeTexture(mip, o.Format, o.isNormalMap, _platform, out var data, out _);
// if (fix) FixChannels(o, mip, ref data);
texture = new Texture(data, mip.SizeX, mip.SizeY, o);
Textures[guid] = texture;
@ -47,6 +50,16 @@ public class Cache : IDisposable
return texture != null;
}
/// <summary>
/// Red : Specular
/// Blue : Roughness
/// Green : Metallic
/// </summary>
private void FixChannels(UTexture2D o, FTexture2DMipMap mip, ref byte[] data)
{
// only if it makes a big difference pls
}
public void Setup()
{
foreach (var model in Models.Values)

View File

@ -29,8 +29,6 @@ public class Material : IDisposable
public Mask M;
public bool HasM;
public float Roughness;
public float SpecularMult = 1f;
public float EmissiveMult = 1f;
public float UVScale = 1f;
@ -89,7 +87,7 @@ public class Material : IDisposable
}
{ // scalars
if (Parameters.TryGetTexture2d(out var original, "M") && cache.TryGetCachedTexture(original, out var transformed))
if (Parameters.TryGetTexture2d(out var original, "M", "AEM") && cache.TryGetCachedTexture(original, false, out var transformed))
{
M = new Mask { Texture = transformed, AmbientOcclusion = 0.7f };
HasM = true;
@ -97,14 +95,6 @@ public class Material : IDisposable
M.SkinBoost = new Boost { Color = new Vector3(l.R, l.G, l.B), Exponent = l.A };
}
if (Parameters.TryGetScalar(out var roughnessMin, "RoughnessMin", "SpecRoughnessMin") &&
Parameters.TryGetScalar(out var roughnessMax, "RoughnessMax", "SpecRoughnessMax"))
Roughness = (roughnessMin + roughnessMax) / 2f;
if (Parameters.TryGetScalar(out var roughness, "Rough", "Roughness"))
Roughness = roughness;
if (Parameters.TryGetScalar(out var specularMult, "SpecularMult"))
SpecularMult = specularMult;
if (Parameters.TryGetScalar(out var emissiveMult, "emissive mult", "Emissive_Mult"))
EmissiveMult = emissiveMult;
@ -124,24 +114,25 @@ public class Material : IDisposable
{
UTexture2D original;
Texture transformed;
var fix = fallback == CMaterialParams2.FallbackSpecularMasks;
var textures = new Texture[numTexCoords];
if (top)
{
for (int i = 0; i < textures.Length; i++)
{
if (Parameters.TryGetTexture2d(out original, triggers[i]) && cache.TryGetCachedTexture(original, out transformed))
if (Parameters.TryGetTexture2d(out original, triggers[i]) && cache.TryGetCachedTexture(original, fix, out transformed))
textures[i] = transformed;
else if (i > 0 && textures[i - 1] != null)
textures[i] = textures[i - 1];
}
}
else if (Parameters.TryGetTexture2d(out original, fallback) && cache.TryGetCachedTexture(original, out transformed))
else if (Parameters.TryGetTexture2d(out original, fallback) && cache.TryGetCachedTexture(original, fix, out transformed))
{
for (int i = 0; i < textures.Length; i++)
textures[i] = transformed;
}
else if (first && Parameters.TryGetFirstTexture2d(out original) && cache.TryGetCachedTexture(original, out transformed))
else if (first && Parameters.TryGetFirstTexture2d(out original) && cache.TryGetCachedTexture(original, fix, out transformed))
{
for (int i = 0; i < textures.Length; i++)
textures[i] = transformed;
@ -206,8 +197,6 @@ public class Material : IDisposable
shader.SetUniform("uParameters.M.Cavity", M.Cavity);
shader.SetUniform("uParameters.HasM", HasM);
shader.SetUniform("uParameters.Roughness", Roughness);
shader.SetUniform("uParameters.SpecularMult", SpecularMult);
shader.SetUniform("uParameters.EmissiveMult", EmissiveMult);
shader.SetUniform("uParameters.UVScale", UVScale);

View File

@ -20,6 +20,8 @@ public class Renderer : IDisposable
private Shader _shader;
private Shader _outline;
public bool bDiffuseOnly;
public PickingTexture Picking { get; }
public Cache Cache { get; }
public Options Settings { get; }
@ -68,7 +70,8 @@ public class Renderer : IDisposable
var projMatrix = cam.GetProjectionMatrix();
// render pass
_shader.Render(viewMatrix, cam.Position, projMatrix);
_shader.Render(viewMatrix, cam.Position, cam.Direction, projMatrix);
_shader.SetUniform("bDiffuseOnly", bDiffuseOnly);
foreach (var model in Cache.Models.Values)
{
if (!model.Show) continue;

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using OpenTK.Graphics.OpenGL4;
@ -10,8 +9,6 @@ namespace FModel.Views.Snooper;
public class Shader : IDisposable
{
private readonly int _handle;
private readonly Dictionary<string, int> _uniformToLocation = new ();
private readonly Dictionary<string, int> _attribLocation = new ();
public Shader() : this("default") {}
@ -57,6 +54,11 @@ public class Shader : IDisposable
GL.UseProgram(_handle);
}
public void Render(Matrix4 viewMatrix, Vector3 viewPos, Vector3 viewDir, Matrix4 projMatrix)
{
Render(viewMatrix, viewPos, projMatrix);
SetUniform("uViewDir", viewDir);
}
public void Render(Matrix4 viewMatrix, Vector3 viewPos, Matrix4 projMatrix)
{
Render(viewMatrix, projMatrix);
@ -72,10 +74,7 @@ public class Shader : IDisposable
public void SetUniform(string name, int value)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
throw new Exception($"{name} uniform not found on shader.");
}
ThrowIfNotFound(location, name);
GL.Uniform1(location, value);
}
@ -83,10 +82,7 @@ public class Shader : IDisposable
{
//A new overload has been created for setting a uniform so we can use the transform in our shader.
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
throw new Exception($"{name} uniform not found on shader.");
}
ThrowIfNotFound(location, name);
GL.UniformMatrix4(location, 1, false, (float*) &value);
}
@ -95,20 +91,14 @@ public class Shader : IDisposable
public void SetUniform(string name, uint value)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
throw new Exception($"{name} uniform not found on shader.");
}
ThrowIfNotFound(location, name);
GL.Uniform1(location, value);
}
public void SetUniform(string name, float value)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
throw new Exception($"{name} uniform not found on shader.");
}
ThrowIfNotFound(location, name);
GL.Uniform1(location, value);
}
@ -117,10 +107,7 @@ public class Shader : IDisposable
public void SetUniform3(string name, float x, float y, float z)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
throw new Exception($"{name} uniform not found on shader.");
}
ThrowIfNotFound(location, name);
GL.Uniform3(location, x, y, z);
}
@ -129,39 +116,16 @@ public class Shader : IDisposable
public void SetUniform4(string name, float x, float y, float z, float w)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
throw new Exception($"{name} uniform not found on shader.");
}
ThrowIfNotFound(location, name);
GL.Uniform4(location, x, y, z, w);
}
public int GetUniformLocation(string uniform)
private void ThrowIfNotFound(int location, string name)
{
if (!_uniformToLocation.TryGetValue(uniform, out int location))
if (location == -1)
{
location = GL.GetUniformLocation(_handle, uniform);
_uniformToLocation.Add(uniform, location);
if (location == -1)
{
Serilog.Log.Debug($"The uniform '{uniform}' does not exist in the shader!");
}
// throw new Exception($"{name} uniform not found on shader.");
}
return location;
}
public int GetAttribLocation(string attrib)
{
if (!_attribLocation.TryGetValue(attrib, out int location))
{
location = GL.GetAttribLocation(_handle, attrib);
_attribLocation.Add(attrib, location);
if (location == -1)
{
Serilog.Log.Debug($"The attrib '{attrib}' does not exist in the shader!");
}
}
return location;
}
public void Dispose()

View File

@ -42,6 +42,7 @@ public class SnimGui
ImGui.DragFloat("Far Plane", ref s.Camera.Far, 0.1f, 5f, s.Camera.Far * 2f, "%.2f m", ImGuiSliderFlags.AlwaysClamp);
ImGui.End();
ImGui.Begin("World");
ImGui.Checkbox("Diffuse Only", ref s.Renderer.bDiffuseOnly);
ImGui.End();
ImGui.Begin("Timeline");
ImGui.End();
@ -95,8 +96,6 @@ public class SnimGui
const int width = 50;
var material = model.Materials[section.MaterialIndex];
ImGui.Checkbox("Show Section", ref section.Show);
ImGui.SetNextItemWidth(width); ImGui.DragFloat("Roughness", ref material.Roughness, .01f, 0f, 1f);
ImGui.SetNextItemWidth(width); ImGui.DragFloat("Specular Multiplier", ref material.SpecularMult, .01f, 0f);
ImGui.SetNextItemWidth(width); ImGui.DragFloat("Emissive Multiplier", ref material.EmissiveMult, .01f, 0f);
ImGui.SetNextItemWidth(width); ImGui.DragFloat("UV Scale", ref material.UVScale, .01f, 0f);
if (material.HasM)

View File

@ -81,7 +81,7 @@ public class Texture : IDisposable
Height = height;
Bind(TextureUnit.Texture0);
GL.TexImage2D(_target, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data);
GL.TexImage2D(_target, 0, texture2D.SRGB ? PixelInternalFormat.Srgb : PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data);
GL.TexParameter(_target, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear);
GL.TexParameter(_target, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear);
GL.TexParameter(_target, TextureParameterName.TextureBaseLevel, 0);