diff --git a/EXE/FLAR.dll b/EXE/FLAR.dll new file mode 100644 index 00000000..d6c0c736 Binary files /dev/null and b/EXE/FLAR.dll differ diff --git a/EXE/MinHook.x86.dll b/EXE/MinHook.x86.dll deleted file mode 100644 index d6167c83..00000000 Binary files a/EXE/MinHook.x86.dll and /dev/null differ diff --git a/EXE/REM-Client.dll b/EXE/REM-Client.dll index b29f49fc..28820fd9 100644 Binary files a/EXE/REM-Client.dll and b/EXE/REM-Client.dll differ diff --git a/EXE/ReShade.ini b/EXE/ReShade.ini index bff8fd03..3b6d2de2 100644 --- a/EXE/ReShade.ini +++ b/EXE/ReShade.ini @@ -1,4 +1,4 @@ -[APP] +[APP] Force10BitFormat=0 ForceFullscreen=0 ForceResolution=0,0 @@ -30,10 +30,10 @@ KeyReload=0,0,0,0 KeyScreenshot=44,0,0,0 [OVERLAY] +AutoSavePreset=1 ClockFormat=0 FPSPosition=1 NoFontScaling=0 -SavePresetOnModification=1 SaveWindowState=0 ShowClock=0 ShowForceLoadEffectsButton=1 @@ -75,3 +75,5 @@ ScrollbarRounding=0.000000 StyleIndex=2 TabRounding=4.000000 WindowRounding=0.000000 + + diff --git a/EXE/ReShade.log b/EXE/ReShade.log new file mode 100644 index 00000000..332a71a5 --- /dev/null +++ b/EXE/ReShade.log @@ -0,0 +1,15 @@ + +If you are reading this after launching the game at least once, it likely means ReShade was not loaded by the game. + +In that event here are some steps you can try to resolve this: + +1) Make sure this file and the related DLL are really in the same directory as the game executable. + If that is the case and it does not work regardless, check if there is a 'bin' directory, move them there and try again. + +2) Try running the game with elevated user permissions by doing a right click on its executable and choosing 'Run as administrator'. + +3) If the game crashes, try disabling all game overlays (like Origin), recording software (like Fraps), FPS displaying software, + GPU overclocking and tweaking software and other proxy DLLs (like ENB, Helix or Umod). + +4) If none of the above helps, you can get support on the forums at https://reshade.me/forum. But search for your problem before + creating a new topic, as somebody else may have already found a solution. diff --git a/EXE/dxgi.dll b/EXE/dxgi.dll deleted file mode 100644 index d36a3bb8..00000000 Binary files a/EXE/dxgi.dll and /dev/null differ diff --git a/EXE/opengl32.dll b/EXE/opengl32.dll new file mode 100644 index 00000000..79265f13 Binary files /dev/null and b/EXE/opengl32.dll differ diff --git a/EXE/rp8.dll b/EXE/rp8.dll index a56ed923..af4cea62 100644 Binary files a/EXE/rp8.dll and b/EXE/rp8.dll differ diff --git a/FLARDATA/MyGUI_Media/DejaVuSans.ttf b/FLARDATA/MyGUI_Media/DejaVuSans.ttf new file mode 100644 index 00000000..e5f7eecc Binary files /dev/null and b/FLARDATA/MyGUI_Media/DejaVuSans.ttf differ diff --git a/FLARDATA/MyGUI_Media/DejaVuSansFontGenerated_15.png b/FLARDATA/MyGUI_Media/DejaVuSansFontGenerated_15.png new file mode 100644 index 00000000..e01aa94e Binary files /dev/null and b/FLARDATA/MyGUI_Media/DejaVuSansFontGenerated_15.png differ diff --git a/FLARDATA/MyGUI_Media/DeveloperOptions.layout b/FLARDATA/MyGUI_Media/DeveloperOptions.layout new file mode 100644 index 00000000..ecc5835b --- /dev/null +++ b/FLARDATA/MyGUI_Media/DeveloperOptions.layout @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/EditMaterial.layout b/FLARDATA/MyGUI_Media/EditMaterial.layout new file mode 100644 index 00000000..36948023 --- /dev/null +++ b/FLARDATA/MyGUI_Media/EditMaterial.layout @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_BlackBlueImages.xml b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueImages.xml new file mode 100644 index 00000000..747ecf9f --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueImages.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_BlackBlueSkins.png b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueSkins.png new file mode 100644 index 00000000..8228f363 Binary files /dev/null and b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueSkins.png differ diff --git a/FLARDATA/MyGUI_Media/MyGUI_BlackBlueSkins.xml b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueSkins.xml new file mode 100644 index 00000000..4161a995 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueSkins.xml @@ -0,0 +1,1126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_BlackBlueTemplates.xml b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueTemplates.xml new file mode 100644 index 00000000..55625f3d --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueTemplates.xml @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_BlackBlueTheme.xml b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueTheme.xml new file mode 100644 index 00000000..50e433d0 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_BlackBlueTheme.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_CommonSkins.xml b/FLARDATA/MyGUI_Media/MyGUI_CommonSkins.xml new file mode 100644 index 00000000..cee2f26f --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_CommonSkins.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_Core.xml b/FLARDATA/MyGUI_Media/MyGUI_Core.xml new file mode 100644 index 00000000..9352b8f8 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_Core.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_Fonts.xml b/FLARDATA/MyGUI_Media/MyGUI_Fonts.xml new file mode 100644 index 00000000..7fd82af0 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_Fonts.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_GeneratedFonts.xml b/FLARDATA/MyGUI_Media/MyGUI_GeneratedFonts.xml new file mode 100644 index 00000000..ff9334cc --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_GeneratedFonts.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_Layers.xml b/FLARDATA/MyGUI_Media/MyGUI_Layers.xml new file mode 100644 index 00000000..92cadfe6 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_Layers.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_OpenGL3_FP.glsl b/FLARDATA/MyGUI_Media/MyGUI_OpenGL3_FP.glsl new file mode 100644 index 00000000..52c15523 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_OpenGL3_FP.glsl @@ -0,0 +1,8 @@ +#version 130 +in vec4 Color; +in vec2 TexCoord; +uniform sampler2D Texture; +void main(void) +{ + gl_FragColor = texture2D(Texture, TexCoord) * Color; +} \ No newline at end of file diff --git a/FLARDATA/MyGUI_Media/MyGUI_OpenGL3_VP.glsl b/FLARDATA/MyGUI_Media/MyGUI_OpenGL3_VP.glsl new file mode 100644 index 00000000..6a248494 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_OpenGL3_VP.glsl @@ -0,0 +1,15 @@ +#version 130 +out vec4 Color; +out vec2 TexCoord; +in vec3 VertexPosition; +in vec4 VertexColor; +in vec2 VertexTexCoord; +uniform float YScale; +void main() +{ + TexCoord = VertexTexCoord; + Color = VertexColor; + vec4 vpos = vec4(VertexPosition,1.0); + vpos.y *= YScale; + gl_Position = vpos; +} \ No newline at end of file diff --git a/FLARDATA/MyGUI_Media/MyGUI_PointerImages.xml b/FLARDATA/MyGUI_Media/MyGUI_PointerImages.xml new file mode 100644 index 00000000..22d6a0e5 --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_PointerImages.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_Pointers.png b/FLARDATA/MyGUI_Media/MyGUI_Pointers.png new file mode 100644 index 00000000..9e028e2e Binary files /dev/null and b/FLARDATA/MyGUI_Media/MyGUI_Pointers.png differ diff --git a/FLARDATA/MyGUI_Media/MyGUI_Pointers.xml b/FLARDATA/MyGUI_Media/MyGUI_Pointers.xml new file mode 100644 index 00000000..41cec68a --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_Pointers.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/MyGUI_Settings.xml b/FLARDATA/MyGUI_Media/MyGUI_Settings.xml new file mode 100644 index 00000000..cc0c1b0d --- /dev/null +++ b/FLARDATA/MyGUI_Media/MyGUI_Settings.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/FLARDATA/MyGUI_Media/Settings.layout b/FLARDATA/MyGUI_Media/Settings.layout new file mode 100644 index 00000000..028d2064 --- /dev/null +++ b/FLARDATA/MyGUI_Media/Settings.layout @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FLARDATA/Shader/ColorConversion.inc b/FLARDATA/Shader/ColorConversion.inc new file mode 100644 index 00000000..d6401b4b --- /dev/null +++ b/FLARDATA/Shader/ColorConversion.inc @@ -0,0 +1,59 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//Color conversion include shader for FLAR by Schmackbolzen + +vec3 ToLinearAccurate(vec3 inColor) +{ + vec3 treshold=step(vec3(0.04045),inColor); + return mix(inColor / 12.92,pow ((inColor + 0.055) / 1.055, vec3(2.4)),treshold); +} + +vec3 ToGammaCorrectedAccurate(vec3 inColor) +{ + vec3 treshold=step(vec3(0.0031308),inColor); + return mix(inColor * 12.92,pow (inColor, vec3(1.0/2.4)) * 1.055 - 0.055,treshold); +} + +vec3 ToLinearFast(vec3 inColor) +{ + return pow(inColor,vec3(2.2)); +} + +vec3 ToGammaCorrectedFast(vec3 inColor) +{ + return pow(inColor.rgb,1./vec3(2.2)); +} + +$SRGB_CONVERSION_DEFINE +#ifdef ALWAYS_USE_FAST_SRGB_CONVERSION +vec3 ToLinear(vec3 inColor) +{ + return ToLinearFast(inColor); +} + +vec3 ToGammaCorrected(vec3 inColor) +{ + return ToGammaCorrectedFast(inColor); +} +#endif + +#ifdef ALWAYS_USE_ACCURATE_SRGB_CONVERSION +vec3 ToLinear(vec3 inColor) +{ + return ToLinearAccurate(inColor); +} + +vec3 ToGammaCorrected(vec3 inColor) +{ + return ToGammaCorrectedAccurate(inColor); +} +#endif + +//Works on gamma compressed and linear values (note that the values are not identical) +//Values are from https://en.wikipedia.org/wiki/Luma_(video) +float ToLuma(vec3 color) +{ + return dot(color, vec3(0.2126, 0.7152f, 0.0722f)); +} \ No newline at end of file diff --git a/FLARDATA/Shader/Irradiance.fp b/FLARDATA/Shader/Irradiance.fp new file mode 100644 index 00000000..dde25ac1 --- /dev/null +++ b/FLARDATA/Shader/Irradiance.fp @@ -0,0 +1,47 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL + +#version 330 +#include "ColorConversion.inc" +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform bool convertToLinear; + +const float PI = 3.14159265359; + +void main() +{ + 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 = normalize(cross(up, N)); + up = normalize(cross(N, right)); + + float sampleDelta = 0.025; + float nrSamples = 0.0f; + 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; + + vec3 texColor=texture(environmentMap, sampleVec).rgb; + if(convertToLinear) + texColor=ToLinear(texColor); + irradiance += texColor * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = PI * irradiance * (1.0 / float(nrSamples)); + + gl_FragColor = vec4(ToGammaCorrected(irradiance), 1.0); +} \ No newline at end of file diff --git a/FLARDATA/Shader/bloomDownsample.fs b/FLARDATA/Shader/bloomDownsample.fs new file mode 100644 index 00000000..6892e9cf --- /dev/null +++ b/FLARDATA/Shader/bloomDownsample.fs @@ -0,0 +1,81 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//PBR bloom downsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom +//The code has been modified to be more like the original presentation and also blog article from the original +//authors of the technique (referenced in the link above). + +#version 330 +#include "ColorConversion.inc" + +uniform sampler2D srcTexture; +uniform vec2 srcTexelSize[$NUM_MIPS]; + + +uniform int mipLevel; + +in vec2 texCoord; +layout (location = 0) out vec3 downsample; + +float KarisAverage(vec3 col) +{ + // Formula is 1 / (1 + luma) + float luma = ToLuma(col); + return 1.0f / (1.0f + luma); +} + +void main() +{ + vec2 texelSize = srcTexelSize[mipLevel]; + float x = texelSize.x; + float y = texelSize.y; + + // Take 13 samples around current texel: + // a - b - c + // - j - k - + // d - e - f + // - l - m - + // g - h - i + // === ('e' is the current texel) === + vec3 a = texture(srcTexture, vec2(texCoord.x - 2*x, texCoord.y + 2*y)).rgb; + vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + 2*y)).rgb; + vec3 c = texture(srcTexture, vec2(texCoord.x + 2*x, texCoord.y + 2*y)).rgb; + + vec3 d = texture(srcTexture, vec2(texCoord.x - 2*x, texCoord.y)).rgb; + vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; + vec3 f = texture(srcTexture, vec2(texCoord.x + 2*x, texCoord.y)).rgb; + + vec3 g = texture(srcTexture, vec2(texCoord.x - 2*x, texCoord.y - 2*y)).rgb; + vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - 2*y)).rgb; + vec3 i = texture(srcTexture, vec2(texCoord.x + 2*x, texCoord.y - 2*y)).rgb; + + vec3 j = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; + vec3 k = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; + vec3 l = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; + vec3 m = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; + + vec3 groups[5]; + const float factor1=0.125f/4.f; + const float factor2=0.5f/4.f; + groups[0] = (a+b+d+e) * factor1; + groups[1] = (b+c+e+f) * factor1; + groups[2] = (d+e+g+h) * factor1; + groups[3] = (e+f+h+i) * factor1; + groups[4] = (j+k+l+m) * factor2; + if (mipLevel == 0) + { + float avg1=KarisAverage(groups[0]); + float avg2=KarisAverage(groups[1]); + float avg3=KarisAverage(groups[2]); + float avg4=KarisAverage(groups[3]); + float avg5=KarisAverage(groups[4]); + float normalization=avg1+avg2+avg3+avg4+avg5+0.0001; + downsample = (groups[0]*avg1+groups[1]*avg2+groups[2]*avg3+groups[3]*avg4+groups[4]*avg5)/normalization; + downsample = max(downsample, 0.0001f); + } + else + { + downsample = (groups[0]+groups[1]+groups[2]+groups[3]+groups[4]); + } +} diff --git a/FLARDATA/Shader/bloomDownsample.vs b/FLARDATA/Shader/bloomDownsample.vs new file mode 100644 index 00000000..8296cc93 --- /dev/null +++ b/FLARDATA/Shader/bloomDownsample.vs @@ -0,0 +1,18 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//PBR bloom downsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom + +#version 330 + +layout (location = 0) in vec2 aPosition; +layout (location = 1) in vec2 aTexCoord; + +out vec2 texCoord; + +void main() +{ + gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0); + texCoord = aTexCoord; +} diff --git a/FLARDATA/Shader/bloomUpsample.fs b/FLARDATA/Shader/bloomUpsample.fs new file mode 100644 index 00000000..53e9417a --- /dev/null +++ b/FLARDATA/Shader/bloomUpsample.fs @@ -0,0 +1,46 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//PBR bloom upsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom +//The only bug fix is using different filter radii for each direction since the texture is not square + +#version 330 +uniform sampler2D srcTexture; +uniform float filterRadiusX; +uniform float filterRadiusY; + +in vec2 texCoord; +layout (location = 0) out vec3 upsample; + +void main() +{ + float x = filterRadiusX; + float y = filterRadiusY; + + // Take 9 samples around current texel: + // a - b - c + // d - e - f + // g - h - i + // === ('e' is the current texel) === + vec3 a = texture(srcTexture, vec2(texCoord.x - x, texCoord.y + y)).rgb; + vec3 b = texture(srcTexture, vec2(texCoord.x, texCoord.y + y)).rgb; + vec3 c = texture(srcTexture, vec2(texCoord.x + x, texCoord.y + y)).rgb; + + vec3 d = texture(srcTexture, vec2(texCoord.x - x, texCoord.y)).rgb; + vec3 e = texture(srcTexture, vec2(texCoord.x, texCoord.y)).rgb; + vec3 f = texture(srcTexture, vec2(texCoord.x + x, texCoord.y)).rgb; + + vec3 g = texture(srcTexture, vec2(texCoord.x - x, texCoord.y - y)).rgb; + vec3 h = texture(srcTexture, vec2(texCoord.x, texCoord.y - y)).rgb; + vec3 i = texture(srcTexture, vec2(texCoord.x + x, texCoord.y - y)).rgb; + + // Apply weighted distribution, by using a 3x3 tent filter: + // 1 | 1 2 1 | + // -- * | 2 4 2 | + // 16 | 1 2 1 | + upsample = e*4.0; + upsample += (b+d+f+h)*2.0; + upsample += (a+c+g+i); + upsample *= 1.0 / 16.0; +} diff --git a/FLARDATA/Shader/bloomUpsample.vs b/FLARDATA/Shader/bloomUpsample.vs new file mode 100644 index 00000000..a3cda365 --- /dev/null +++ b/FLARDATA/Shader/bloomUpsample.vs @@ -0,0 +1,18 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//PBR bloom upsample shader for FLAR by Schmackbolzen based on code from https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom + +#version 330 + +layout (location = 0) in vec2 aPosition; +layout (location = 1) in vec2 aTexCoord; + +out vec2 texCoord; + +void main() +{ + gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0); + texCoord = aTexCoord; +} diff --git a/FLARDATA/Shader/brdf.fp b/FLARDATA/Shader/brdf.fp new file mode 100644 index 00000000..511b8a15 --- /dev/null +++ b/FLARDATA/Shader/brdf.fp @@ -0,0 +1,128 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL + + +#version 330 +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 roughnessSquared) +{ + //float a = roughness*roughness; + float a = roughnessSquared; + + 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 + 0.00001; // 0.00001 to prevent divide by zero. + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(float NdotV, float NdotL, float roughness) +{ + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +//"PBR Diffuse Lighting for GGX+Smith Microsurfaces", Earl Hammon, Jr. +float GeometrySmithG2Hammon(float NdotV, float NdotL, float roughnessSquared) +{ + float nom = 2*NdotL*NdotV; + float denom = mix(2*NdotL*NdotV,NdotL+NdotV,roughnessSquared) + 0.00001; // 0.00001 to prevent divide by zero. + return nom/denom; +} + +// ---------------------------------------------------------------------------- +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); + + float roughnessSquared = roughness*roughness; + + 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, roughnessSquared); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(L.z, 0.0); + + if(NdotL > 0.0) + { + float NdotH = max(H.z, 0.0); + float VdotH = max(dot(V, H), 0.0); + //float G = GeometrySmith(NdotV, NdotL, roughness); + float G = GeometrySmithG2Hammon(NdotV, NdotL, roughnessSquared); + 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); + gl_FragColor.rg = integratedBRDF; +} \ No newline at end of file diff --git a/FLARDATA/Shader/brdf.vs b/FLARDATA/Shader/brdf.vs new file mode 100644 index 00000000..02c52233 --- /dev/null +++ b/FLARDATA/Shader/brdf.vs @@ -0,0 +1,17 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL + + +#version 330 +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/FLARDATA/Shader/cubemap.vs b/FLARDATA/Shader/cubemap.vs new file mode 100644 index 00000000..bd0b5c52 --- /dev/null +++ b/FLARDATA/Shader/cubemap.vs @@ -0,0 +1,18 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL + +#version 330 +layout (location = 0) in vec3 aPos; + +out vec3 WorldPos; + +uniform mat4 projectionMat; +uniform mat4 viewMat; + +void main() +{ + WorldPos = aPos; + gl_Position = projectionMat * viewMat * vec4(WorldPos, 1.0); +} \ No newline at end of file diff --git a/FLARDATA/Shader/depthOnly.fp b/FLARDATA/Shader/depthOnly.fp new file mode 100644 index 00000000..f5e9bc93 --- /dev/null +++ b/FLARDATA/Shader/depthOnly.fp @@ -0,0 +1,20 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Depth only shader for FLAR by Schmackbolzen + +#version 330 + +uniform sampler2D texture; +uniform float alphaTestValue; +in vec2 outTexCoords; + +void main() +{ + if (alphaTestValue > 0) + { + if (texture2D(texture, outTexCoords).a < alphaTestValue) + discard; + } + gl_FragColor = vec4(1,0,0,1); +} \ No newline at end of file diff --git a/FLARDATA/Shader/depthOnly.gs b/FLARDATA/Shader/depthOnly.gs new file mode 100644 index 00000000..4b19ff5e --- /dev/null +++ b/FLARDATA/Shader/depthOnly.gs @@ -0,0 +1,30 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on "Parallel-Split Shadow Maps on Programmable GPUs" GPU Gems 3 (2005) + +#version 330 +const int g_iNumSplits = $NUM_SPLITS; + +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; + +flat in int splitIndex[]; + +in vec2 inTexCoords[]; +uniform mat4 mvpMat[g_iNumSplits]; + +out vec2 outTexCoords; + +void main() +{ + for(int iVertex = 0; iVertex < 3; iVertex++) + { + int iSplit = splitIndex[iVertex]; + gl_Layer = iSplit; + gl_Position = mvpMat[iSplit]*gl_in[iVertex].gl_Position; + outTexCoords = inTexCoords[iVertex]; + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/FLARDATA/Shader/depthOnly.vs b/FLARDATA/Shader/depthOnly.vs new file mode 100644 index 00000000..c33f1cd1 --- /dev/null +++ b/FLARDATA/Shader/depthOnly.vs @@ -0,0 +1,46 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on "Parallel-Split Shadow Maps on Programmable GPUs" GPU Gems 3 (2005) +#version 330 + +layout (location = 0) in vec4 inPosition; +layout (location = 4) in vec2 inTexCoord0; +layout (location = 6) in mat4 inMVPMatInstanced; +layout (location = 10) in int inSplitIndexInstanced; + +out vec2 inTexCoords; +flat out int splitIndex; + +const int g_iNumSplits = $NUM_SPLITS; + +uniform mat4 worldMat; +uniform bool isInstanced; +uniform bool isInstancedSplits; +uniform float alphaTestValue; +uniform int firstSplit; + +void main(){ + mat4 mvp; + + if(!isInstanced) + mvp=worldMat; + else + { + mvp=inMVPMatInstanced; + } + + if(!isInstancedSplits) + { + splitIndex = firstSplit + gl_InstanceID; + } + else + { + splitIndex = inSplitIndexInstanced; + } + + gl_Position = mvp * inPosition; + if (alphaTestValue > 0) + inTexCoords = inTexCoord0.st; +} + diff --git a/FLARDATA/Shader/fixedFunction.fp b/FLARDATA/Shader/fixedFunction.fp new file mode 100644 index 00000000..06475d78 --- /dev/null +++ b/FLARDATA/Shader/fixedFunction.fp @@ -0,0 +1,401 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Fixed function shader for FLAR by Schmackbolzen + +#version 330 +#define TEXTURESTAGE_COUNT 2 +#include "ColorConversion.inc" + +struct Light{ + vec3 ambient; + vec3 diffuse; + vec4 position; + vec3 spotDirection; + float spotExponent; + float spotCosPhi; + float spotCosTheta; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; + float range; +}; + +struct glFogParameters +{ + vec3 color; + float density; + float start; + float end; +}; + + +uniform Light glLightSource[8]; +uniform glFogParameters glFog; +uniform sampler2D textures[TEXTURESTAGE_COUNT]; +uniform samplerCube cubemap; +uniform int colorOp[TEXTURESTAGE_COUNT]; +uniform int alphaOp[TEXTURESTAGE_COUNT]; +uniform int colorArg1[TEXTURESTAGE_COUNT]; +uniform int colorArg2[TEXTURESTAGE_COUNT]; +uniform int alphaArg1[TEXTURESTAGE_COUNT]; +uniform int alphaArg2[TEXTURESTAGE_COUNT]; +uniform bool textureBound[TEXTURESTAGE_COUNT]; +uniform vec3 ambientColor; +uniform vec3 matAmbientColor; +uniform vec4 matDiffuseColor; +uniform vec3 matEmissiveColor; +uniform vec4 matSpecularColor; +uniform float alphaTestValue; +uniform int alphaTestCompareMethod; +uniform int lightCount; +uniform int texture1Index; +uniform int fogMode; + +uniform bool enableVertexColor; +uniform bool vertexColorAvailable; +uniform bool specularVertexColorAvailable; +uniform bool enableLighting; +uniform bool enableAlphaTest; +uniform bool enableCubemap; +uniform bool enableRHWCoordinates; +uniform bool enableAccurateSRGB; + +in vec3 N; +in vec3 v; +in float RHWdepth; +in vec2 texCoords[2]; +in vec4 vertexColor; +in vec4 vertexColorSecondary; +in float fogEnd; +in float fogScale; + +#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) +#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) +#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) +#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) +#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) +#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) +#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 x (read modifier) +#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) + +#define D3DTOP_DISABLE 1 // disables stage +#define D3DTOP_SELECTARG1 2 // the default +#define D3DTOP_SELECTARG2 3 + + // Modulate +#define D3DTOP_MODULATE 4 // multiply args together +#define D3DTOP_MODULATE2X 5 // multiply and << 1 bit +#define D3DTOP_MODULATE4X 6 // multiply and << 2 bits + + // Add +#define D3DTOP_ADD 7 // add arguments together +#define D3DTOP_ADDSIGNED 8 // add with -0.5 bias +#define D3DTOP_ADDSIGNED2X 9 // as above but left << 1 bit + +vec3 ToLinear(vec3 inColor) +{ + if (enableAccurateSRGB) + return ToLinearAccurate(inColor); + else + return ToLinearFast(inColor); +} + +vec3 ToGammaCorrected(vec3 inColor) +{ + if (enableAccurateSRGB) + return ToGammaCorrectedAccurate(inColor); + else + return ToGammaCorrectedFast(inColor); +} + +vec4 GetColorForStage(const int stage, int colorArg, int alphaArg, vec4 previousColor, vec4 gouradDiffuseColor, vec4 specularColor, vec2 texCoords, vec3 cubeMapTexCoords) +{ + vec4 color; + vec4 textureColor; + if(colorArg == D3DTA_TEXTURE || alphaArg == D3DTA_TEXTURE) + if(textureBound[stage]) + //Use if because some glsl compilers can not propagate the constant stage even though it has a constant value + //when the function gets called (0 or 1) and complain about missing glsl compliance for texture lookup (no constant index) + if (stage==0) + textureColor=texture2D(textures[0],texCoords); + else + if (!enableCubemap) + textureColor=texture2D(textures[1],texCoords); + else + textureColor=texture(cubemap,cubeMapTexCoords); + else + textureColor=vec4(1); + + //textureColor.rgb=ToLinear(textureColor.rgb); + + if(colorArg == D3DTA_DIFFUSE) + color.rgb=gouradDiffuseColor.rgb; + else if(colorArg == D3DTA_CURRENT) + color.rgb=previousColor.rgb; + else if(colorArg == D3DTA_TEXTURE) + color.rgb=textureColor.rgb; + else if(colorArg == D3DTA_SPECULAR) + color.rgb =specularColor.rgb; + else + color=vec4(1,0,0,1); + + if(alphaArg == D3DTA_DIFFUSE) + color.a=gouradDiffuseColor.a; + else if(alphaArg == D3DTA_CURRENT) + color.a=previousColor.a; + else if(alphaArg == D3DTA_TEXTURE) + color.a=textureColor.a; + else if(alphaArg == D3DTA_SPECULAR) + color.a =specularColor.a; + else + color=vec4(1,0,0,1); + return color; +} + +vec4 ApplyFunctionForStage(const int stage, vec4 previousColor, vec4 gouradDiffuseColor, vec4 specularColor, vec2 texCoords, vec3 cubeMapTexCoords) +{ + vec4 color1=GetColorForStage(stage,colorArg1[stage],alphaArg1[stage], previousColor, gouradDiffuseColor, specularColor, texCoords, cubeMapTexCoords); + vec4 color2=GetColorForStage(stage,colorArg2[stage],alphaArg2[stage], previousColor, gouradDiffuseColor, specularColor, texCoords, cubeMapTexCoords); + + if (colorOp[stage]==D3DTOP_SELECTARG2) + { + color1.rgb = color2.rgb; + } + else if (colorOp[stage]==D3DTOP_MODULATE) + { + color1.rgb*=color2.rgb; + } + else if (colorOp[stage]==D3DTOP_MODULATE2X) + { + color1.rgb=color1.rgb*color2.rgb*4.6; //2^2.2 since rendering is gamma correct + } + else if (colorOp[stage]==D3DTOP_MODULATE4X) + { + color1.rgb=color1.rgb*color2.rgb*21.11; //4^2.2 since rendering is gamma correct + } + else if (colorOp[stage]==D3DTOP_ADD) + { + color1.rgb=color1.rgb+color2.rgb; + } + else if (colorOp[stage]==D3DTOP_ADDSIGNED) + { + color1.rgb=color1.rgb+color2.rgb-0.5; + } + else if (colorOp[stage]==D3DTOP_ADDSIGNED2X) + { + color1.rgb=(color1.rgb+color2.rgb-0.5)*4.6; //2^2.2 since rendering is gamma correct + } + + if (alphaOp[stage]==D3DTOP_SELECTARG2) + { + color1.a = color2.a; + } + else if (alphaOp[stage]==D3DTOP_MODULATE) + { + color1.a*=color2.a; + } + else if (alphaOp[stage]==D3DTOP_MODULATE2X) + { + color1.a=(color1.a*color2.a)*4.6; //2^2.2 since rendering is gamma correct + } + else if (alphaOp[stage]==D3DTOP_MODULATE4X) + { + color1.a=(color1.a*color2.a)*21.11; //4^2.2 since rendering is gamma correct + } + else if (alphaOp[stage]==D3DTOP_ADD) + { + color1.a=(color1.a+color2.a); + } + else if (alphaOp[stage]==D3DTOP_ADDSIGNED) + { + color1.a=color1.a+color2.a-0.5; + } + else if (alphaOp[stage]==D3DTOP_ADDSIGNED2X) + { + color1.a=(color1.a+color2.a-0.5)*4.6; //2^2.2 since rendering is gamma correct + } + color1.a=pow(color1.a,1.2); + + return color1; +} + +void main() +{ + vec4 gouradDiffuseColor; + vec4 specularColor; + vec3 vertexAmbientColor; + + if (enableLighting) + { + if(enableVertexColor) + { + + float alpha = vertexColorAvailable ? vertexColor.a : matDiffuseColor.a; + if (specularVertexColorAvailable) + { + vertexAmbientColor=ToLinear(vertexColorSecondary.rgb); + gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,alpha); + } + else + { + vertexAmbientColor=matAmbientColor.rgb; + gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,alpha); + } + } + else + { + vertexAmbientColor=matAmbientColor.rgb; + gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,matDiffuseColor.a); + } + //FL never has specular lighting enabled + specularColor=vec4(0,0,0,0); + } + else + { + if(vertexColorAvailable) + { + //gouradDiffuseColor=vec4(ToLinear(vertexColor.rgb),vertexColor.a); + //TODO: Weird bug with MSAA and float16 render target + vec4 vertexColorAboveZero=max(vertexColor,0); + gouradDiffuseColor=vec4(ToLinear(vertexColorAboveZero.rgb),vertexColorAboveZero.a); + } + else + gouradDiffuseColor=vec4(1,1,1,1); + + if(specularVertexColorAvailable) + specularColor=vec4(ToLinear(vertexColorSecondary.rgb),vertexColor.a); + else + specularColor=vec4(0,0,0,0); + } + + vec3 normal=normalize(N); + if (enableLighting) + { + gouradDiffuseColor.rgb+=matEmissiveColor; + vec3 vertexDiffuseColor=vertexColorAvailable&&enableVertexColor ? ToLinear(vertexColor.rgb): matDiffuseColor.rgb; + + for (int index = 0; index < lightCount; index++) + { + + vec3 lightDir; + float attenFactor; + // attenuation and light direction + if(glLightSource[index].spotCosTheta != -1.) + { + lightDir = normalize(glLightSource[index].position.xyz - v); + + float angle = max(dot(normalize(glLightSource[index].spotDirection), -lightDir),0); + + if (angle > glLightSource[index].spotCosPhi) + { + float spotAtten; + if (angle < glLightSource[index].spotCosTheta) + spotAtten = (angle-glLightSource[index].spotCosPhi)/(glLightSource[index].spotCosTheta-glLightSource[index].spotCosPhi); + else + spotAtten = 1; + + if(glLightSource[index].spotExponent != 1.0) + spotAtten = pow(spotAtten, glLightSource[index].spotExponent); + + float dist = distance(glLightSource[index].position.xyz, v); + attenFactor = spotAtten * min(1.0/ (glLightSource[index].constantAttenuation + + glLightSource[index].linearAttenuation * dist + + glLightSource[index].quadraticAttenuation * dist * dist),1); + } + else + attenFactor = 0.; + } + else if (glLightSource[index].position.w != 0.0) + { + // positional light source + float dist = distance(glLightSource[index].position.xyz, v); + if (dist <= glLightSource[index].range ) + { + attenFactor = min(1.0/( glLightSource[index].constantAttenuation + + glLightSource[index].linearAttenuation * dist + + glLightSource[index].quadraticAttenuation * dist * dist ),1); + lightDir = normalize(glLightSource[index].position.xyz - v); + } + else + attenFactor = 0; + } + else + { + attenFactor = 1; + lightDir = normalize(glLightSource[index].position.xyz); + } + if(attenFactor > 0) + { + float intensity = max(dot(normal,lightDir),0.0); + + vec3 lightColorAmbient = glLightSource[index].ambient.rgb*vertexAmbientColor; + vec3 lightColorDiffuse = glLightSource[index].diffuse.rgb*vertexDiffuseColor*intensity; + gouradDiffuseColor.rgb += (lightColorAmbient + lightColorDiffuse)*attenFactor; + } + } + } + + vec4 finalColor=gouradDiffuseColor; + if (colorOp[0]!=D3DTOP_DISABLE) + { + vec3 cubeMapTexCoords; + finalColor=ApplyFunctionForStage(0,finalColor,gouradDiffuseColor,specularColor,texCoords[0], cubeMapTexCoords); + + if (colorOp[1]!=D3DTOP_DISABLE) + { + + if(enableCubemap) + cubeMapTexCoords=reflect(v,normal); + finalColor=ApplyFunctionForStage(1,finalColor,gouradDiffuseColor,specularColor,texCoords[1], cubeMapTexCoords); + } + } + else + finalColor=gouradDiffuseColor; + + if (enableAlphaTest) + if(alphaTestCompareMethod==5) + { + if( finalColor.a <= alphaTestValue) + discard; + } + else if(alphaTestCompareMethod==2) + { + if( finalColor.a > alphaTestValue) + discard; + } + else + finalColor =vec4(1,0,0,1); + + if (fogMode > 0) + { + float z; + if(enableRHWCoordinates) + z = RHWdepth; + else + //Radial fog + z = length(v); + + const float LOG2E = 1.442695; + float fogFactor; + if (fogMode == 3) + { + fogFactor = (fogEnd - z) * fogScale; + } + else if (fogMode == 1) + { + fogFactor =exp(-glFog.density * z); + } + else if (fogMode == 2) + { + fogFactor = exp2(-glFog.density * glFog.density * z * z * LOG2E); + } + else + fogFactor = 1; + + fogFactor = clamp(fogFactor, 0.0, 1.0); + finalColor.rgb = mix(glFog.color.rgb,finalColor.rgb, fogFactor); + } + gl_FragColor = vec4(ToGammaCorrected(finalColor.rgb), finalColor.a); + //gl_FragColor = finalColor; +} diff --git a/FLARDATA/Shader/fixedFunction.vs b/FLARDATA/Shader/fixedFunction.vs new file mode 100644 index 00000000..24d9fcaa --- /dev/null +++ b/FLARDATA/Shader/fixedFunction.vs @@ -0,0 +1,109 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Fixed function shader for FLAR by Schmackbolzen + +#version 330 +out vec2 texCoords[2]; +out vec3 N; +out vec3 v; +out float RHWdepth; +out vec4 vertexColor; +out vec4 vertexColorSecondary; +out float fogEnd; +out float fogScale; + +struct glFogParameters +{ + vec3 color; + float density; + float start; + float end; +}; + +uniform glFogParameters glFog; +uniform bool enableRHWCoordinates; +uniform mat4 modelViewMat; +uniform mat4 projectionMat; +uniform mat3 normalMat; +uniform vec2 projCorrection; +uniform mat4 textureMatrix[2]; +uniform bool isInstanced; +uniform bool isInstancedTransparent; +uniform bool isInstancedFog; +uniform bool enableTextureTransform0; +uniform bool enableTextureTransform1; +uniform int texture1Index; + +layout (location = 0) in vec4 inPosition; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec4 inColor; +layout (location = 3) in vec4 inSecondColor; +layout (location = 4) in vec4 inTexCoord0; +layout (location = 6) in mat4 inModelViewMatInstanced; +layout (location = 10) in float inAlphaValue; +layout (location = 11) in vec2 inFogStartEndInstanced; + +void main() +{ + mat4 mv; + if(!isInstanced) + mv=modelViewMat; + else + mv=inModelViewMatInstanced; + + vertexColor.rgba = (inColor).bgra; + vertexColorSecondary.rgba=inSecondColor.bgra; + + if(isInstancedTransparent) + { + vertexColor.a = inAlphaValue; + } + + if(!isInstancedFog) + { + fogEnd = glFog.end; + fogScale = 1.0f / (glFog.end - glFog.start); + } + else + { + fogEnd = inFogStartEndInstanced.y; + fogScale = 1.0f / (inFogStartEndInstanced.y - inFogStartEndInstanced.x); + } + + v = vec3(mv * inPosition); + N = normalize(mat3(mv) * inNormal); + + if (!enableRHWCoordinates) + gl_Position = projectionMat * mv * inPosition; + else + { + gl_Position = vec4((inPosition.x+63.0f / 128.0f)*projCorrection[0]-1,-(inPosition.y+63.0f / 128.0f)*projCorrection[1]+1,inPosition.z*2-1,1); + RHWdepth = inPosition.z/inPosition.w; + } + + if(enableTextureTransform0) + { + vec4 texCoords0=vec4(inTexCoord0.xy,0,1); + texCoords[0] = (textureMatrix[0]*texCoords0).xy; + } + else + texCoords[0] = inTexCoord0.xy; + + if (texture1Index == 0) + if(enableTextureTransform1) + { + vec4 texCoords0=vec4(inTexCoord0.xy,0,1); + texCoords[1] = (textureMatrix[1]*texCoords0).xy; + } + else + texCoords[1] = inTexCoord0.xy; + else if (texture1Index == 1) + if(enableTextureTransform1) + { + vec4 texCoords1=vec4(inTexCoord0.zw,0,1); + texCoords[1] = (textureMatrix[1]*texCoords1).xy; + } + else + texCoords[1] = inTexCoord0.zw; +} \ No newline at end of file diff --git a/FLARDATA/Shader/histogramBin.fp b/FLARDATA/Shader/histogramBin.fp new file mode 100644 index 00000000..21fc7f7d --- /dev/null +++ b/FLARDATA/Shader/histogramBin.fp @@ -0,0 +1,25 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//Simple histogram shader for FLAR by Schmackbolzen + +#version 330 +#include "ColorConversion.inc" +#define NUM_LIMITS $NUM_LIMITS +in vec2 TexCoords; + +uniform sampler2D scene; +uniform vec2 limits[NUM_LIMITS]; +uniform int index; + +void main() +{ + float luma = clamp(ToLuma(texture2D(scene, TexCoords).rgb),limits[0].x,limits[NUM_LIMITS-1].x); + vec2 currentLimits=limits[index]; + bool withinLimits; + withinLimits = (luma >= currentLimits.x) && (luma < currentLimits.y); + if (!withinLimits) + discard; + gl_FragDepth= 0; +} \ No newline at end of file diff --git a/FLARDATA/Shader/lighting.fp b/FLARDATA/Shader/lighting.fp new file mode 100644 index 00000000..71a206c7 --- /dev/null +++ b/FLARDATA/Shader/lighting.fp @@ -0,0 +1,722 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//PBR lighting shader for FLAR by Schmackbolzen +//Sources are either mentioned in the comments below, +//from https://learnopengl.com/PBR/Lighting or https://learnopengl.com/PBR/IBL/Specular-IBL +//or "Parallel-Split Shadow Maps on Programmable GPUs" GPU Gems 3 (2005) + +#version 330 +#include "ColorConversion.inc" +#define MAX_SHADOWS $MAX_SHADOWS +#define NUM_SPLITS $NUM_SPLITS +#define USE_PCF $USE_PCF +#define USE_HQ_DIFFUSE $USE_HQ_DIFFUSE +#define USE_PARALLAX_MAPS $USE_PARALLAX_MAPS +#define USE_CLUSTERED_SHADING $USE_CLUSTERED_SHADING + + +//#define SIMPLE_KD +#define IBL_MULTIPLE_SCATTERING + +#if USE_CLUSTERED_SHADING == 1 +#define NUM_POSSIBLE_LIGHTS $NUM_POSSIBLE_LIGHTS +#define LIGHT_GRID_TILE_DIM_X $LIGHT_GRID_TILE_DIM_X +#define LIGHT_GRID_TILE_DIM_Y $LIGHT_GRID_TILE_DIM_Y +#define LIGHT_GRID_MAX_DIM_X $LIGHT_GRID_MAX_DIM_X +#define LIGHT_GRID_MAX_DIM_Y $LIGHT_GRID_MAX_DIM_Y +#endif + +const float PBR_FACTOR = 2; +const float PBR_FACTOR_ENV = 1.5; + +in vec3 eyeVec; +in vec3 v,vWorld,worldNormal; +in vec3 N; +in mat3 tbnMatrix,tbnMatrixObj; +in vec4 shadowCoord[MAX_SHADOWS*NUM_SPLITS]; +in vec4 texCoords; +in mat3 worldRotMat; +in float alphaValue; + +in float fogEnd; +in float fogScale; + +struct Light{ + vec3 ambient; + vec3 diffuse; + vec4 position; + vec3 spotDirection; + float spotExponent; + float spotCosPhi; + float spotCosTheta; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; +}; + +struct glFogParameters +{ + vec3 color; + float density; + float start; + float end; +}; + +#if USE_CLUSTERED_SHADING == 1 +//Has to be 16 byte aligned (otherwise it will be padded) +struct ClusteredLight{ + vec4 position; + vec4 diffuse; +}; + +layout (std140) uniform LightSourceClustered +{ + ClusteredLight clusteredLights[NUM_POSSIBLE_LIGHTS]; +}; + +uniform isamplerBuffer clusterLightIndexListsTex; +uniform usamplerBuffer clusterGridTex; +#endif + +uniform glFogParameters glFog; +uniform Light glLightSource[8]; +uniform sampler2D tex; +uniform sampler2D tex2; +uniform sampler2D heightMap; +uniform sampler2D normalMap; +uniform sampler2D roughnessMap; +uniform sampler2D metalnessMap; +uniform sampler2D reflectionMap; +uniform sampler2D brdfLUT; +uniform sampler2DArrayShadow shadowMap[MAX_SHADOWS]; +uniform float splitPlanes[NUM_SPLITS]; + +uniform samplerCube envMap; +uniform samplerCube irradianceMap; +uniform vec2 texture1Size; +uniform vec2 textureShadowSize; +uniform int lightCount; +uniform int shadowCount; +uniform int tex2Mode; +uniform int fogMode; +uniform float metalnessConst; +uniform float roughnessConst; +uniform float roughnessTextureBias; + +uniform mat4 invWorldView; +uniform vec3 camPos; +uniform vec3 ambientColor; +uniform vec3 matAmbientColor; +uniform vec3 matDiffuseColor; +uniform vec3 matEmissiveColor; +uniform int alphaTestCompareMethod; +uniform float alphaTestValue; + +uniform bool enableNormalMaps; +uniform bool enableParallaxMaps; +uniform bool enableFirstTexture; +uniform bool enableSecondTexture; +uniform bool enableFog; +uniform bool enableEnvMap; +uniform bool enableTex2Modulate2X; +uniform bool enableRoughnessMap; +uniform bool enableMetalnessMap; +uniform bool enableAlphaTest; +#if USE_CLUSTERED_SHADING == 1 +uniform bool enableClusteredShading; +uniform float recNear; /**< 1.0f / g_near */ +uniform float recLogSD1; /**< 1.0f / logf(sD + 1.0f), used to compute cluster index. */ +#endif + + + +float HEIGHT_SCALE = 0.01; + +const float PI = 3.141592654; + +out vec4 diffuseColorOut; + + +float ShadowCalculation(const float bias, const int shadowMapIndex, const int lightIndex, const sampler2DArrayShadow shadowSampler) +{ + vec4 fragPosLightSpace = shadowCoord[lightIndex*NUM_SPLITS+shadowMapIndex]; + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + #if USE_PCF == 1 + float currentDepth = clamp(projCoords.z,0,1); + + + // Check whether current frag pos is in shadow + //if(projCoords.z <= 1.0) + { + float shadow = 0.0; + vec2 texelSize = 1.0 / vec2(textureShadowSize); + for(int x = -1; x <= 1; ++x) + { + for(int y = -1; y <= 1; ++y) + { + float pcfDepth = clamp(texture(shadowSampler, vec4(projCoords.xy + vec2(x, y) * texelSize, shadowMapIndex, projCoords.z - bias)),0,1); + shadow += pcfDepth; + } + } + shadow *= 1.0/9.0; + return shadow; + } + //else + //return 1; + #else + return texture(shadowSampler, vec4(projCoords.xy, shadowMapIndex, projCoords.z - bias)); + #endif +} + +float ShadowCalculationForAllSplitPlanes(const int lightIndex, const vec3 lightDirViewSpace, const vec3 normal, float lightIntensity, const sampler2DArrayShadow shadowSampler) +{ + float distance = v.z; + float bias = max(0.001 * (1.0 - dot(normal, lightDirViewSpace)), 0.0003); + + bool applied = false; + + for (int i = 0; i < NUM_SPLITS; i++) + if(!applied && (distance < splitPlanes[i])) + { + //bias = ((i+1)*0.1)*0.001; + lightIntensity *= ShadowCalculation(bias, i, lightIndex, shadowSampler); + applied=true; + //Graphics cards hate break (SLOW), hence boolean value above + //break; + } + return lightIntensity; + +} + +//Parallax mapping with offset limiting +//You can try different parallax mapping techniques, but they all have problems with steep angles so I decided this is something for later +vec2 ParallaxMapping(vec3 V, vec2 T) +{ + // get depth for this fragment + float initialHeight = texture2D(heightMap, T).r-0.5; + + // calculate amount of offset for Parallax Mapping With Offset Limiting + vec2 texCoordOffset = HEIGHT_SCALE * V.xy * initialHeight; + + // return modified texture coordinates + return T + texCoordOffset; +} + +float DistributionGGX(float NdotH, float roughnessSquared) +{ + float a = roughnessSquared; + float a2 = a*a; + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = NdotH2 * (a2 - 1.0) + 1.0; + denom = PI * denom * denom + 0.0001; + + return nom / denom; +} + +//"PBR Diffuse Lighting for GGX+Smith Microsurfaces", Earl Hammon, Jr. +float GeometrySmithG2HammonDenom(float NdotL, float NdotV, float roughnessSquared) +{ + float denom = mix(2*NdotL*NdotV,NdotL+NdotV,roughnessSquared); + return denom; +} + +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta,0), 5.0); +} + + +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0); +} + +struct LightValues +{ + vec3 lightVec; + vec3 lightDir; + vec3 lightDirViewSpace; + float attenFactor; + float lightDist; +}; + +LightValues CalculateLightValues(const int index) +{ + LightValues result; + if(glLightSource[index].spotCosTheta != -1.) + { + result.lightVec = glLightSource[index].position.xyz - v; + result.lightDirViewSpace=normalize(result.lightVec); + result.lightDist = length(result.lightVec); + result.lightDir = normalize(result.lightVec); + + float angle = max(dot(normalize(glLightSource[index].spotDirection), -result.lightDir),0); + + if (angle > glLightSource[index].spotCosPhi) + { + float spotAtten; + if (angle < glLightSource[index].spotCosTheta) + spotAtten = (angle-glLightSource[index].spotCosPhi)/(glLightSource[index].spotCosTheta-glLightSource[index].spotCosPhi); + else + spotAtten = 1; + + + if(glLightSource[index].spotExponent != 1.0) + spotAtten = pow(spotAtten, glLightSource[index].spotExponent); + + result.attenFactor = spotAtten * min(1.0/ (glLightSource[index].constantAttenuation + + glLightSource[index].linearAttenuation * result.lightDist + + glLightSource[index].quadraticAttenuation * result.lightDist * result.lightDist),1); + } + else + result.attenFactor = 0.; + } + else if (glLightSource[index].position.w != 0.0) + { + result.lightVec = glLightSource[index].position.xyz - v; + result.lightDirViewSpace=normalize(result.lightVec); + result.lightDist = length(result.lightVec); + + if (enableNormalMaps) + result.lightVec = tbnMatrix*result.lightVec; + result.lightDir = normalize(result.lightVec); + + + // positional light source + result.attenFactor = clamp(1.0/( glLightSource[index].constantAttenuation + + glLightSource[index].linearAttenuation * result.lightDist + + glLightSource[index].quadraticAttenuation * result.lightDist * result.lightDist ),0,1); + } + else + { + // directional light source + result.attenFactor = 1.0; + + if (enableNormalMaps) + { + result.lightDirViewSpace=normalize(glLightSource[index].position.xyz); + result.lightVec = tbnMatrix*glLightSource[index].position.xyz; + result.lightDir = normalize(result.lightVec); + } + else + { + result.lightVec = glLightSource[index].position.xyz; + result.lightDir = normalize(result.lightVec); + result.lightDirViewSpace = result.lightDir; + } + result.lightDist = length(result.lightVec); + } + return result; +} + +#if USE_CLUSTERED_SHADING == 1 +LightValues CalculateLightValuesClustered(const int index) +{ + LightValues result; + + result.lightVec = clusteredLights[index].position.xyz - v; + result.lightDirViewSpace=normalize(result.lightVec); + result.lightDist = length(result.lightVec); + + if (enableNormalMaps) + result.lightVec = tbnMatrix*result.lightVec; + result.lightDir = normalize(result.lightVec); + + // positional light source + float inner = 0.0; + float att = max(1.0 - max(0.0, (result.lightDist - inner) / (clusteredLights[index].position.w - inner)), 0.0); + result.attenFactor = att; + return result; +} +#endif + +vec3 ApplyAmbientLight(const int index,const vec3 firstTexture, const float intensity, vec3 lightSum) +{ + vec3 IAmbient = (matAmbientColor)*(PBR_FACTOR*glLightSource[index].ambient)*firstTexture; + lightSum.rgb += IAmbient*intensity; + return lightSum; +} + +vec3 ApplyPBRLight(vec3 lightDiffuseColor, const LightValues lightValues, const vec3 mapNormal, const vec3 eyeV, const vec3 F0, const float roughness, const vec3 IDiffuse, const vec3 firstTexture, vec3 lightSum, const float metalness) +{ + + float visible = 1.0; + float intensity = lightValues.attenFactor; + + //vec3 IAmbient = (matAmbientColor.rgb)*(PBR_FACTOR*glLightSource[index].ambient)*firstTexture; + //lightSum.rgb += IAmbient*intensity; + + vec3 L = lightValues.lightDir; + vec3 V = normalize(eyeV); + vec3 H = normalize(L + V); + + vec3 reflected; + vec3 N = mapNormal; + + float HdotV = max(dot(H, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float NdotV = max(dot(N, V), 0.0001); + float NdotH = max(dot(N, H), 0.0001); + + vec3 F = fresnelSchlick(HdotV, F0); + + // Cook-Torrance BRDF + float roughnessSquared = roughness*roughness; + float NDF = DistributionGGX(NdotH, roughnessSquared); + + vec3 nominator = NDF * F; + float denominator = 2.0 * GeometrySmithG2HammonDenom(NdotV, NdotL, roughnessSquared) + 0.00001; // 0.00001 to prevent divide by zero. + vec3 specular = nominator/denominator; + + #ifndef SIMPLE_KD + vec3 kD=mix(vec3(1.0)-F,vec3(0.0),metalness); + #else + float kD = 1.0 - metalness; + #endif + + #if USE_HQ_DIFFUSE == 1 + //GGX Diffuse Approximation from + //"PBR Diffuse Lighting for GGX+Smith Microsurfaces, Earl Hammon, Jr." + float LdotV = dot(L, V); + float facing = 0.5+0.5*LdotV; + float rough = facing*(0.9-0.4*facing)*(.5/(NdotH+0.05) + 1); //+0.05 to prevent too large values + float smooth_ = 1.05*(1-pow(1-NdotL,5))*(1-pow(1-NdotV,5)); + float single = 1./PI*mix(smooth_, rough, roughnessSquared); + float multi = 0.1159*roughnessSquared; + vec3 diffuse = kD*IDiffuse.rgb*(single+IDiffuse.rgb*multi); + #else + vec3 diffuse = kD*IDiffuse.rgb/PI; + #endif + + lightSum+= PBR_FACTOR*lightDiffuseColor*(diffuse + specular)*intensity*NdotL; + + + +return lightSum; +} + +vec3 ApplyLight(const int index, const LightValues lightValues, const vec3 mapNormal, const vec3 eyeV, const vec3 F0, const float roughness, const vec3 IDiffuse, const vec3 firstTexture, vec3 lightSum, const float metalness) +{ + lightSum=ApplyAmbientLight(index, firstTexture, lightValues.attenFactor, lightSum); + lightSum=ApplyPBRLight(glLightSource[index].diffuse.rgb, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse, firstTexture, lightSum, metalness); + return lightSum; +} + +#if USE_CLUSTERED_SHADING == 1 +//Clustered shading code partially from +//"Demo code implementing Clustered Forward Shading, accompanying the talk +//'Tiled and Clustered Forward Shading' presented at Siggraph 2012." + +/** + * Computes the {i,j,k} integer index into the cluster grid. For details see our paper: + * 'Clustered Deferred and Forward Shading' + * http://www.cse.chalmers.se/~olaolss/main_frame.php?contents=publication&id=clustered_shading + */ +ivec3 calcClusterLoc(vec2 fragPos, float viewSpaceZ) +{ + // i and j coordinates are just the same as tiled shading, and based on screen space position. + ivec2 l = ivec2(int(fragPos.x) / LIGHT_GRID_TILE_DIM_X, int(fragPos.y) / LIGHT_GRID_TILE_DIM_Y); + + // k is based on the log of the view space Z coordinate. + float gridLocZ = log(viewSpaceZ * recNear) * recLogSD1; + + return ivec3(l, int(gridLocZ)); +} + +/** + * Linearlizes the 3D cluster location into an offset, which can be used as an + * address into a linear buffer. + */ +int calcClusterOffset(ivec3 clusterLoc) +{ + return (clusterLoc.z * LIGHT_GRID_MAX_DIM_Y + clusterLoc.y) * LIGHT_GRID_MAX_DIM_X + clusterLoc.x; +} + +/** + * Convenience shorthand function, see above... + */ +int calcClusterOffset(vec2 fragPos, float viewSpaceZ) +{ + return calcClusterOffset(calcClusterLoc(fragPos, viewSpaceZ)); +} + +vec3 ApplyClusteredLights(const vec3 mapNormal, const vec3 eyeV, const vec3 F0, const float roughness, const vec3 IDiffuse, const vec3 firstTexture, vec3 lightSum, const float metalness) +{ + // fetch cluster data (i.e. offset to light indices, and numer of lights) from grid buffer. + uvec2 offsetCount = texelFetch(clusterGridTex, calcClusterOffset(gl_FragCoord.xy, v.z)).xy; + + int lightOffset = int(offsetCount.x); + int lightCount = int(offsetCount.y); + + for (int i = 0; i < lightCount; ++i) + { + // fetch light index from list of lights for the cluster. + int lightIndex = texelFetch(clusterLightIndexListsTex, lightOffset + i).x; + LightValues lightValues = CalculateLightValuesClustered(lightIndex); + // compute and accumulate shading. + lightSum = ApplyPBRLight(clusteredLights[lightIndex].diffuse.rgb*2, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse, firstTexture, lightSum, metalness); + } + + return lightSum; +} +#endif + +void main(void) +{ + float fogFactor = 0; + if (enableFog && fogMode > 0) + { + //Radial fog + float z = length(v); + if (fogMode == 3) + { + fogFactor = (fogEnd - z) * fogScale; + } + else if (fogMode == 1) + { + fogFactor = 1.0/exp(glFog.density * z); + } + else if (fogMode == 2) + { + fogFactor = 1.0 /exp( (z * glFog.density)* (z * glFog.density)); + } + + fogFactor = clamp(fogFactor, 0.0, 1.0); + } + + vec3 eyeV=normalize(eyeVec); + vec3 normal=normalize(N); + + vec2 texCoordsProcessed; + +#if USE_PARALLAX_MAPS == 1 + if (enableParallaxMaps) + texCoordsProcessed = ParallaxMapping(eyeV, texCoords.st); + else +#endif + texCoordsProcessed = texCoords.st; + + vec4 firstTexture; + vec4 lightSum = vec4(0); + if (enableFirstTexture) + { + firstTexture = texture2D(tex, texCoordsProcessed); + if (enableSecondTexture) + { + if(tex2Mode == 0) + { + firstTexture *= texture2D(tex2, texCoords.pq); + if (enableTex2Modulate2X) + firstTexture.rgb*=4.6; //2^2.2 since rendering is gamma correct + + } + else + { + lightSum.rgb += texture2D(tex2, texCoords.pq).rgb; + } + } + + } + else{ + firstTexture = vec4(1,1,1,1); + } + + float alpha = alphaValue*firstTexture.a; + if (enableAlphaTest) + if(alphaTestCompareMethod==5) + { + if( alpha <= alphaTestValue) + discard; + } + else if(alphaTestCompareMethod==2) + { + if( alpha > alphaTestValue) + discard; + } + else + firstTexture =vec4(1,0,0,1); + + vec3 mapNormal; + if (enableNormalMaps) + { + vec3 textureNormal = texture2D(normalMap, texCoordsProcessed).rgb; + textureNormal.xy = (textureNormal.rg * 2.0 - 1.0); + textureNormal.z = sqrt(1.0-dot(textureNormal.xy,textureNormal.xy)); + mapNormal = normalize(textureNormal.xyz); + } + else + mapNormal = normal; + + lightSum+=vec4(((matEmissiveColor.rgb))* firstTexture.rgb, alpha); + + float metalness; + if (enableMetalnessMap) + { + metalness=texture2D(metalnessMap, texCoordsProcessed.st).r; + } + else + { + metalness=metalnessConst; + + } + + vec3 IDiffuse = (matDiffuseColor)*firstTexture.rgb; + + float roughness; + if (enableRoughnessMap) + { + roughness=clamp(roughnessTextureBias+texture2D(roughnessMap, texCoordsProcessed.st).r,0.0,1.0); + } + else + { + roughness=roughnessConst; + } + + #define DIELECTRIC_SPECULAR 0.04 + vec3 F0 = mix(vec3(DIELECTRIC_SPECULAR), IDiffuse, metalness); + if (enableEnvMap) + { + vec3 n; + if (enableNormalMaps) + n=normalize( worldRotMat * (tbnMatrixObj * mapNormal )); + else + n=normalize(worldNormal); + vec3 v = normalize( camPos - vWorld); + vec3 reflectDir = reflect(-v, n); + const float MAX_REFLECTION_LOD = 7; + float lod = roughness * (2.0 - roughness) * MAX_REFLECTION_LOD; + vec3 irradiance; + vec3 radiance; + if (enableFog) + { + vec3 ambientTint=PBR_FACTOR_ENV*glFog.color.rgb; + irradiance = vec3(texture(irradianceMap, n).r)*ambientTint; + radiance = vec3(textureLod(envMap, reflectDir, lod).r)*ambientTint; + } + else + { + irradiance = texture(irradianceMap, n).rgb*PBR_FACTOR_ENV; + radiance = textureLod(envMap, reflectDir, lod).rgb*PBR_FACTOR_ENV; + } + + float NdotV = max(dot(n,v),0.0); + vec2 brdf = texture(brdfLUT, vec2(NdotV, roughness)).rg; + + #ifdef IBL_MULTIPLE_SCATTERING + vec3 diffuseColor = mix(IDiffuse.rgb, vec3(0), metalness); + // Multiple scattering, from: + //"A Multiple-Scattering Microfacet Model for Real-Time Image-based Lighting", Carmelo J. Fdez-Agüera + vec3 kS = F0; + + vec3 FssEss = kS * brdf.x + brdf.y; + + float Ess = brdf.x + brdf.y; + float Ems = 1.0-Ess; + vec3 Favg = F0 + (1.0-F0)/21.0; + vec3 Fms = FssEss*Favg/(1.0-Ems*Favg); + vec3 FmsEms = Fms * Ems; + // Dielectrics + vec3 Edss = 1.0 - (FssEss + FmsEms); + vec3 kD = diffuseColor * Edss; + // Composition + lightSum.rgb += FssEss * radiance + (FmsEms+kD) * irradiance; + #else + vec3 diffuse = irradiance * IDiffuse; + vec3 F = fresnelSchlickRoughness(NdotV, F0, roughness); + #ifndef SIMPLE_KD + vec3 kD=mix(vec3(1.0)-F,vec3(0.0),metalness); + #else + float kD = 1.0 - metalness; + #endif + + vec3 specular = radiance * (F0 * brdf.x + brdf.y); + lightSum.rgb += kD*diffuse + specular; + #endif + } + else + { + if (enableNormalMaps) + { + vec3 dir = vec3(0,0,1); + float ambientIntensity = dot(dir,mapNormal); + lightSum.rgb+=matAmbientColor.rgb * ambientColor.rgb* ambientIntensity*IDiffuse.rgb; + } + else + lightSum.rgb+=matAmbientColor.rgb * ambientColor.rgb* IDiffuse.rgb; + } + + //Unrolled loop and a separated shadow pass to help some glsl compilers. Also some glsl compilers need a constant value (not variable!) for sampler arrays. + if(lightCount > 0) + { + const int lightIndex = 0; + LightValues lightValues = CalculateLightValues(lightIndex); + #if MAX_SHADOWS > 0 + if (shadowCount > 0) + lightValues.attenFactor = ShadowCalculationForAllSplitPlanes(lightIndex, lightValues.lightDirViewSpace, normal, lightValues.attenFactor, shadowMap[0]); + #endif + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if(lightCount > 1) + { + const int lightIndex = 1; + LightValues lightValues = CalculateLightValues(lightIndex); + #if MAX_SHADOWS > 1 + if (shadowCount > 1) + lightValues.attenFactor = ShadowCalculationForAllSplitPlanes(lightIndex, lightValues.lightDirViewSpace, normal, lightValues.attenFactor, shadowMap[1]); + #endif + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if (lightCount > 2) + { + const int lightIndex = 2; + LightValues lightValues = CalculateLightValues(lightIndex); + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if (lightCount > 3) + { + const int lightIndex = 3; + LightValues lightValues = CalculateLightValues(lightIndex); + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if (lightCount > 4) + { + const int lightIndex = 4; + LightValues lightValues = CalculateLightValues(lightIndex); + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if (lightCount > 5) + { + const int lightIndex = 5; + LightValues lightValues = CalculateLightValues(lightIndex); + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if (lightCount > 6) + { + const int lightIndex = 6; + LightValues lightValues = CalculateLightValues(lightIndex); + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + if (lightCount > 7) + { + const int lightIndex = 7; + LightValues lightValues = CalculateLightValues(lightIndex); + lightSum.rgb = ApplyLight(lightIndex, lightValues, mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + } + #if USE_CLUSTERED_SHADING == 1 + if(enableClusteredShading) + lightSum.rgb = ApplyClusteredLights(mapNormal, eyeV, F0, roughness, IDiffuse.rgb, firstTexture.rgb, lightSum.rgb, metalness); + #endif + + vec4 finalColor = lightSum; + + + if (enableFog && fogMode > 0) + { + finalColor = mix(vec4(glFog.color,1.0),finalColor, fogFactor); + } + + diffuseColorOut=vec4(ToGammaCorrected(finalColor.rgb),finalColor.a); +} \ No newline at end of file diff --git a/FLARDATA/Shader/lighting.vs b/FLARDATA/Shader/lighting.vs new file mode 100644 index 00000000..1d1908b7 --- /dev/null +++ b/FLARDATA/Shader/lighting.vs @@ -0,0 +1,145 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//PBR lighting shader for FLAR by Schmackbolzen + +#version 330 + +#define MAX_SHADOWS $MAX_SHADOWS +#define NUM_SPLITS $NUM_SPLITS + +out vec3 eyeVec; +out vec3 v,vWorld,worldNormal; +out mat3 tbnMatrix,tbnMatrixObj; +out vec3 N; +out vec4 shadowCoord[MAX_SHADOWS*NUM_SPLITS]; +out vec4 texCoords; +out mat3 worldRotMat; +out float alphaValue; +out float fogEnd; +out float fogScale; + +struct glFogParameters +{ + vec3 color; + float density; + float start; + float end; +}; + +uniform glFogParameters glFog; +uniform mat4 depthBiasMVP[MAX_SHADOWS*NUM_SPLITS]; +uniform mat4 modelViewMat; +uniform mat4 projectionMat; +uniform mat4 invViewMat; +uniform mat4 textureMatrix[2]; +uniform bool enableNormalMaps; +uniform int shadowCount; +uniform bool enableEnvMap; +uniform bool isInstanced; +uniform bool isInstancedTransparent; +uniform bool isInstancedFog; +uniform float matDiffuseAlpha; +uniform int tex2Mode; +uniform int texture1Index; + +layout (location = 0) in vec4 inPosition; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec4 inColor; +layout (location = 3) in vec4 inSecondColor; +layout (location = 4) in vec4 inTexCoord0; +layout (location = 5) in vec4 inTexCoord2; +layout (location = 6) in mat4 inModelViewMatInstanced; +layout (location = 10) in float inAlphaValueInstanced; +layout (location = 11) in vec2 inFogStartEndInstanced; + +const mat4 biasMatrix = mat4(0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f); + + +void main(void) +{ + + + mat4 mv; + if(!isInstanced) + mv=modelViewMat; + else + mv=inModelViewMatInstanced; + + if(!isInstancedTransparent) + { + alphaValue = matDiffuseAlpha; + } + else + { + alphaValue = inAlphaValueInstanced; + } + + if(!isInstancedFog) + { + fogEnd = glFog.end; + fogScale = 1 / (glFog.end - glFog.start); + } + else + { + fogEnd = inFogStartEndInstanced.y; + fogScale = 1 / (inFogStartEndInstanced.y - inFogStartEndInstanced.x); + } + + mat3 normalMat = mat3(mv); + v = vec3(mv * inPosition); + mat4 worldMat = invViewMat*mv; + if(enableEnvMap) + { + vWorld = vec3(worldMat * inPosition); + worldRotMat = mat3(worldMat); + worldNormal = worldRotMat * inNormal; + } + if (shadowCount > 0) + { + for(int i=0;i 1) + for(int i=0;i XYZ => D65_2_D60 => AP1 => RRT_SAT +const mat3 ACESInputMat = mat3( + 0.59719, 0.07600, 0.02840, + 0.35458, 0.90834, 0.13383, + 0.04823, 0.01566, 0.83777); + +// ODT_SAT => XYZ => D60_2_D65 => sRGB +const mat3 ACESOutputMat = mat3( + 1.60475, -0.10208, -0.00327, + -0.53108, 1.10813, -0.07276, + -0.07367, -0.00605, 1.07602 +); + +vec3 RRTAndODTFit(vec3 v) +{ + vec3 a = v * (v + 0.0245786f) - 0.000090537f; + vec3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f; + return a / b; +} + +vec3 ACESFitted(vec3 color) +{ + color = ACESInputMat * color; + + // Apply RRT and ODT + color = RRTAndODTFit(color); + + color = ACESOutputMat * color; + + // Clamp to [0, 1] + color = clamp(color,0.,1.); + + return color; +} + +// Uchimura 2017, "HDR theory and practice" +// Math: https://www.desmos.com/calculator/gslcdxvipg +// Source: https://www.slideshare.net/nikuque/hdr-theory-and-practicce-jp +// Used in "Gran Turismo Sport" game +vec3 uchimura(vec3 x, float P, float a, float m, float l, float c, float b) { + float l0 = ((P - m) * l) / a; + float L0 = m - m / a; + float L1 = m + (1.0 - m) / a; + float S0 = m + l0; + float S1 = m + a * l0; + float C2 = (a * P) / (P - S1); + float CP = -C2 / P; + + vec3 w0 = vec3(1.0 - smoothstep(0.0, m, x)); + vec3 w2 = vec3(step(m + l0, x)); + vec3 w1 = vec3(1.0 - w0 - w2); + + vec3 T = vec3(m * pow(x / m, vec3(c)) + b); + vec3 S = vec3(P - (P - S1) * exp(CP * (x - S0))); + vec3 L = vec3(m + a * (x - m)); + + return T * w0 + L * w1 + S * w2; +} + +vec3 uchimura(vec3 x) { + const float P = 1.0; // max display brightness + const float a = 1.0; // contrast + const float m = 0.22; // linear section start + const float l = 0.4; // linear section length + const float c = 1.33; // black + const float b = 0.0; // pedestal + + return uchimura(x, P, a, m, l, c, b); +} + +#if USE_PBR_BLOOM == 1 +const float bloomStrength = 0.2f; +vec4 bloom_new() +{ + vec4 hdrColor = texture(scene, TexCoords); + //hdrColor.rgb=vec3(0); + vec3 bloomColor = texture(bloomtex, TexCoords).rgb; + //Blend in linear space + /*hdrColor.rgb=ToLinear(hdrColor.rgb); + bloomColor=ToLinear(bloomColor);*/ + vec4 blended=vec4(mix(hdrColor.rgb, bloomColor, bloomStrength),hdrColor.a); // linear interpolation + //Blend in gamma corrected space + blended.rgb=ToLinear(blended.rgb); + return blended; +} +#endif + +void main() +{ +#if USE_PBR_BLOOM == 0 + vec4 color = texture2D(scene, TexCoords); + //Not a nice solution to convert two times (ideally there would be none), but not easily solvable currently + color.rgb = ToLinear(color.rgb); +#else + vec4 color = bloom_new(); +#endif + //Exposure is chosen so that both curves have about the same brightness and the look is fine with very bright starspheres like in Tau-37 +#if USE_ACES_CURVE == 1 + color.rgb=ACESFitted((exposure)*color.rgb); +#else + color.rgb=uchimura((exposure)*color.rgb); +#endif + + color.rgb=ToGammaCorrected(color.rgb); + gl_FragColor = color; + +} \ No newline at end of file diff --git a/FLARDATA/Shader/postProcess.vs b/FLARDATA/Shader/postProcess.vs new file mode 100644 index 00000000..5fdfa4b9 --- /dev/null +++ b/FLARDATA/Shader/postProcess.vs @@ -0,0 +1,16 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Post processing shader for FLAR by Schmackbolzen + +#version 330 +layout (location = 0) in vec4 vertex; + +out vec2 TexCoords; + +void main() +{ + gl_Position = vec4(vertex.xy, 1.0f, 1.0f); + vec2 texture = vertex.zw; + TexCoords = texture; +} \ No newline at end of file diff --git a/FLARDATA/Shader/postProcessLightScatter.fp b/FLARDATA/Shader/postProcessLightScatter.fp new file mode 100644 index 00000000..ec1ac49b --- /dev/null +++ b/FLARDATA/Shader/postProcessLightScatter.fp @@ -0,0 +1,46 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://fabiensanglard.net/lightScattering/index.php which is based on +//"Volumetric Light Scattering as a Post-Process" GPU Gems 3 (2005) and +//"Light Shaft Rendering" ShadersX3 (2004). + +#version 330 +#define MAX_NUM_LIGHTS $MAX_NUM_LIGHTS +in vec2 TexCoords; + +uniform float exposure; +uniform float decay; +uniform float density; +uniform float weight; +uniform vec2 lightPositionOnScreen[MAX_NUM_LIGHTS]; +uniform sampler2D myTexture; +uniform int numActiveLights; + +const int NUM_SAMPLES = 75; + +void main() +{ + vec4 result = vec4(0); + + for (int lightIndex = 0; lightIndex < MAX_NUM_LIGHTS && lightIndex < numActiveLights; lightIndex++ ) + { + vec2 deltaTextCoord = vec2( TexCoords.st - lightPositionOnScreen[lightIndex].xy ); + vec2 textCoord = TexCoords.st; + deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density; + float illuminationDecay = 1.0; + + for(int i=0; i < NUM_SAMPLES ; i++) + { + textCoord -= deltaTextCoord; + vec4 sample = texture2D(myTexture, textCoord ); + sample *= illuminationDecay * weight; + result += sample; + illuminationDecay *= decay; + } + } + + result=min(result,vec4(NUM_SAMPLES*weight)); + result *= exposure; + gl_FragColor = result; +} diff --git a/FLARDATA/Shader/postProcessLightScatter.vs b/FLARDATA/Shader/postProcessLightScatter.vs new file mode 100644 index 00000000..66fdac71 --- /dev/null +++ b/FLARDATA/Shader/postProcessLightScatter.vs @@ -0,0 +1,18 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://fabiensanglard.net/lightScattering/index.php which is based on +//"Volumetric Light Scattering as a Post-Process" GPU Gems 3 (2005) and +//"Light Shaft Rendering" ShadersX3 (2004). + +#version 330 +layout (location = 0) in vec4 vertex; + +out vec2 TexCoords; + +void main() +{ + gl_Position = vec4(vertex.xy, 0.0f, 1.0f); + vec2 texture = vertex.zw; + TexCoords = texture; +} diff --git a/FLARDATA/Shader/prefilter.fp b/FLARDATA/Shader/prefilter.fp new file mode 100644 index 00000000..71b45427 --- /dev/null +++ b/FLARDATA/Shader/prefilter.fp @@ -0,0 +1,129 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +//Code based on https://learnopengl.com/PBR/IBL/Specular-IBL + +#version 330 +in vec3 WorldPos; + +uniform samplerCube environmentMap; +uniform float roughness; +uniform bool convertToLinear; +uniform bool copyOnly; + +const float PI = 3.14159265359; + +vec3 ToGammaCorrected(vec3 inColor){ + return pow(inColor.rgb,1./vec3(2.2)); +} + +vec3 ToLinear(vec3 inColor){ + return pow(inColor,vec3(2.2)); +} + +// ---------------------------------------------------------------------------- +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 + 0.0001; + + 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; + + if (!copyOnly) + { + 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 = 1024.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); + vec3 texColor=textureLod(environmentMap, L, mipLevel).rgb; + if(convertToLinear) + texColor=ToLinear(texColor); + prefilteredColor += texColor * NdotL; + totalWeight += NdotL; + } + } + + prefilteredColor = prefilteredColor / totalWeight; + + gl_FragColor = vec4(ToGammaCorrected(prefilteredColor), 1.0); + //gl_FragColor = vec4(prefilteredColor, 1.0); + } + else + gl_FragColor = vec4(textureLod(environmentMap, V, 0).rgb, 1.0); +} diff --git a/FLARDATA/Shader/simpleColor.fp b/FLARDATA/Shader/simpleColor.fp new file mode 100644 index 00000000..8db47601 --- /dev/null +++ b/FLARDATA/Shader/simpleColor.fp @@ -0,0 +1,14 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//Simple color shader for FLAR by Schmackbolzen + +#version 330 + +in vec3 currentColor; + +void main() +{ + gl_FragColor = vec4(currentColor,1); +} diff --git a/FLARDATA/Shader/simpleColor.vs b/FLARDATA/Shader/simpleColor.vs new file mode 100644 index 00000000..90a0c295 --- /dev/null +++ b/FLARDATA/Shader/simpleColor.vs @@ -0,0 +1,36 @@ +//This shader file is part of FLAR - Advanced Renderer for Freelancer by Schmackbolzen +//If you use the supplied shader files you may not modify them unless you state in them what you changed +//and also mention the source or who the author is. +// +//Simple color shader for FLAR by Schmackbolzen + +#version 330 + +uniform mat4 modelViewMat; +uniform mat4 projectionMat; +uniform vec3 position; +uniform vec3 color; +uniform float size; +uniform bool isInstanced; + +layout (location = 0) in vec3 inVertex; +layout (location = 1) in vec3 inPositionInstanced; +layout (location = 2) in float inSizeInstanced; +layout (location = 3) in vec3 inColorInstanced; +out vec3 currentColor; + +void main() +{ + vec3 worldSpacePos; + if(!isInstanced) + { + currentColor=color; + worldSpacePos=size * inVertex + position; + } + else + { + currentColor=inColorInstanced; + worldSpacePos=inSizeInstanced * inVertex + inPositionInstanced; + } + gl_Position = projectionMat * modelViewMat * vec4(worldSpacePos,1); +} diff --git a/FLARDATA/Textures/NebulaCubeMap.dds b/FLARDATA/Textures/NebulaCubeMap.dds new file mode 100644 index 00000000..8b38db1d Binary files /dev/null and b/FLARDATA/Textures/NebulaCubeMap.dds differ diff --git a/FLARDATA/config.cfg b/FLARDATA/config.cfg new file mode 100644 index 00000000..ee33fef5 --- /dev/null +++ b/FLARDATA/config.cfg @@ -0,0 +1,22 @@ +MSAAMode=3 +AnisotropicFilteringMode=4 +ToneMappingType=0 +ShadowNumSplits=5 +ShadowmapSize=4096 +ShadowCastingLights=2 +EnableNewLighting=1 +EnableShadows=1 +EnableEnvMaps=1 +EnablePostProcessing=1 +EnableLightScattering=1 +EnableParallaxMaps=1 +EnableHQDiffuse=1 +EnableShadowPCF=1 +EnableAsteroidShadows=1 +LightScatteringSunLimit=8 +EnableClusteredShading=1 +MaxNumberOfLightsIndex=3 +ReplaceFakeLights=1 +EnablePointLights=0 +EnableAutomaticExposure=1 +AlwaysUseAccurateSRGBConversion=1 diff --git a/FLARDATA/materials.json b/FLARDATA/materials.json new file mode 100644 index 00000000..b815415f --- /dev/null +++ b/FLARDATA/materials.json @@ -0,0 +1,102 @@ +{ + "DefaultMaterial": { + "Roughness" : 0.4, + "Metalness" : 0.9, + "RoughnessTextureBias" : 0.03 + }, + "ExactMatchedMaterials": [ + { + "TextureNames": [ + "atmosphere", "cratermoon", "desert_clouds_01", "desert_clouds_02", "desert_clouds_cap", "desert_med_01", "desert_med_02", "desert_med_cap", "desert_red_01", "desert_red_02", "desert_red_cap", "desert_rock_01", "desert_rock_02", "desert_rock_cap", "desert01", "desert02", "desertcap", "detailmap_city", "detailmap_crater_high", "detailmap_crater_low", "detailmap_crater_mid", "detailmap_ground01", "detailmap_lava", "detailmap_ocean", "detailmap_rock01", "earthcity01", "earthcity02", "earthcitycap", "earthgaia", "earthgaiacap", "earthgrncld01", "earthgrncld02", "earthgrncldcap", "earthlike01", "earthlike02", "earthlikecap", "earthsnwcld01", "earthsnwcld02", "earthsnwcldcap", "gasblucld01", "gasblucld02", "gasblucldcap", "gasgrncld01", "gasgrncld02", "gasgrncldcap", "gasicecld", "gasorgcld01", "gasorgcld02", "gasorgcldcap", "gaspurcld01", "gaspurcld02", "gaspurcldcap", "gasyelcld", "greenwater01", "greenwater02", "greenwatercap", "icegrey01", "icegrey02", "icegreycap", "icelndwat01", "icelndwat02", "icelndwatcap", "icemntcld01", "icemntcld02", "icemntcldcap", "icemoon", "icepurple01", "icepurple02", "icepurplecap", "icewatcld01", "icewatcld02", "icewatcldcap", "icewatind01", "icewatind02", "icewatindcap", "icewhiteblue01", "icewhiteblue02", "icewhitebluecap", "indust01", "indust02", "industcap", "jupiter_eirope", "jupiter_ganimed", "jupiter_io", "mercury01", "mercury02", "mercurycap", "moon_body.tga", "moonblu", "moonred", "moonyellow", "neptuncap", "neptunside", "neutron", "NUPS_fun_pl01_side1.tga", "NUPS_fun_pl02_side1.tga", "NUPS_fun_pl03_side1.tga", "nups_pla_des01_atmosphere.tga", "nups_pla_des01_side1.tga", "nups_pla_des01_side2.tga", "nups_pla_des01_side3.tga", "nups_pla_des01_side4.tga", "nups_pla_des01_sidebottom.tga", "nups_pla_des01_sidetop.tga", "NUPS_planet_capricacap1", "NUPS_planet_capricacap2", "NUPS_planet_capricaside", "NUPS_planet_scorpio01_bottom.tga", "NUPS_planet_scorpio01_side1.tga", "NUPS_planet_scorpio01_side2.tga", "NUPS_planet_scorpio01_side3.tga", "NUPS_planet_scorpio01_side4.tga", "NUPS_planet_scorpio01_top.tga", "ocean_bluclds_01", "ocean_bluclds_02", "ocean_bluclds_cap", "ocean_bluislclds_01", "ocean_bluislclds_02", "ocean_bluislclds_cap", "ocean_blusmlcld_01", "ocean_blusmlcld_02", "ocean_blusmlcld_cap", "ocean_drkclds_01", "ocean_drkclds_02", "ocean_drkclds_cap", "ocean_grnclds_01", "ocean_grnclds_02", "ocean_grnclds_cap", "plutoside", "rckbrn_01", "rckbrn_02", "rckbrn_cap", "rockdes_01", "rockdes_02", "rockdes_cap", "rockmnt", "rockmnt_01", "rockmnt_cap", "saturncap1", "saturncap2", "saturnside", "sw_planet1_earthside1.tga", "sw_planet1_earthside2.tga", "sw_planet1_earthside3.tga", "sw_planet1_earthside4.tga", "sw_planet1_earthsidebottom.tga", "sw_planet1_earthsidetop.tga", "upiter01", "upiter02", "upitercap", "uranusside", "venus" + ], + "Roughness" : 1.0, + "Metalness" : 0.0 + }, + { + "TextureNames": [ + "tree_64.tga","Sprauge_Grass.tga" + ], + "Roughness" : 0.2, + "Metalness" : 0.1 + }, + { + "TextureNames": [ + "APE.TGA", "br_bartender_head02.TGA", "br_brighton_head02.TGA", "br_captain_head01.tga", "br_carina_head02.TGA", "br_darcy_head01.tga", "br_kaitlyn_head01.tga", "br_newscaster_head01.TGA", "br_quigly_head02.TGA", "br_sales_head02.TGA", "br_tobias_head.tga", "eyeblue.tga", "eyebrown.tga", "eyebrown_grey.TGA", "eyebrown_juni.TGA", "eyebrown_Orillion.TGA", "eyebrown_shiny.TGA", "eyegreen.tga", "eyeshinehilights2.tga", "eyetealblue.tga", "eyetealblueDARK.TGA", "eyetealblueTRENT.TGA", "ge_female1_head02.TGA", "ge_male1_head02.TGA", "ge_male2_head02.TGA", "ge_male3_head02.TGA", "ge_male4_head02.TGA", "ge_male6_head02.TGA", "ge_male7_head02.TGA", "ku_bartender_head02.TGA", "ku_captain_head02.TGA", "ku_edo_head01.tga", "ku_kym_head02.TGA", "ku_newscaster_head02.TGA", "ku_sales_head02.TGA", "ku_tashi_head02.TGA", "ku_tenji_head01.tga", "li_bartender_head01.tga", "li_captain_head02.TGA", "li_hatcher_head02.TGA", "li_newscaster_head02.TGA", "li_rockford_head01.tga", "li_sales_head02.TGA", "li_scrote_head02.TGA", "mandril.TGA", "N-dtl2-256.TGA_0", "pi_pirate1_head02.TGA", "pi_pirate2_head02.TGA", "pi_pirate3_head_HURT.TGA", "pi_pirate3_head02.TGA", "pi_pirate4_head02.TGA", "pi_pirate5_head04.TGA", "pl_female1_head02.TGA", "pl_female2_head02.TGA", "pl_female3_head01.tga", "pl_female4_head03.TGA", "pl_female5_head02.TGA", "pl_female6_head02.tga", "pl_male1_head03.TGA", "pl_male2_head03.TGA", "pl_male3_head02.TGA", "pl_male4_head01.tga", "pl_male5_head02.tga", "pl_male6_head02.TGA", "pl_male7_head01.tga", "pl_male8_head.tga", "rh_alaric_head02.TGA", "rh_bartender_head02.TGA", "rh_captain_head03.TGA", "rh_dedrich_head02.TGA", "rh_gruenwald_head02.TGA", "rh_hassler_head02.tga", "rh_newscaster_head02.tga", "rh_reichman_head02.TGA", "rh_sales_head02.TGA", "rh_wilhelm_head03.TGA", "sc_male1_head02.TGA", "sc_male2_head02.TGA", "sh_female1_head02.TGA", "sh_female2_head02.TGA", "sh_male1_head01.tga", "sh_male2_head01.tga", "sh_male3_head02.TGA", "sh_male4_head02.TGA", "Syd_head02.TGA", "teeth_white1.bmp", + "Female_Hand.TGA", "Female_Hand_black.TGA", "Male_Hand.tga", "Male_Hand_black.TGA" + ], + "Roughness" : 0.6, + "Metalness" : 0.0 + }, + { + "TextureNames": [ + "robot01.TGA","robotB.TGA", "robotA.TGA", "robotC.TGA" + ], + "Roughness" : 0.3, + "Metalness" : 0.9 + }, + { + "TextureNames": [ + "2P_S 13.tga", "2P_S 14.tga", "br_carina_body_1.tga", "br_carina_body_2.tga", "br_carina_body_3.tga", "br_commtrader_body_1.tga", "br_commtrader_body_2.tga", "br_commtrader_body_3.tga", "br_darcey_body_1.tga", "br_darcey_body_2.tga", "br_darcey_body_3.tga", "br_female_elite_1.tga", "br_female_elite_2.tga", "br_female_elite_3.tga", "br_female_guard_1 01.tga", "br_female_guard_2 01.tga", "br_female_guard_3 01.tga", "br_kaitlyn_body_1.tga", "br_kaitlyn_body_2.tga", "br_kaitlyn_body_3.tga", "br_male_elite_1.TGA", "br_male_elite_2.TGA", "br_male_elite_3.tga", "br_male_guard_1.tga", "br_male_guard_2.tga", "br_male_guard_3.TGA", "br_shipdealer_body_1.tga", "br_shipdealer_body_2.tga", "br_shipdealer_body_3.tga", "bretonia_equip_25.tga", "brighton01.TGA", "brighton02.TGA", "brighton03.TGA", "escpod.TGA", "ku_commtrader_body_1 .tga", "ku_commtrader_body_2 .tga", "ku_commtrader_body_3.tga", "ku_edo_body_1.tga", "ku_edo_body_2.tga", "ku_edo_body_3.tga", "ku_shipdealer_body_1.tga", "ku_shipdealer_body_2.tga", "ku_shipdealer_body_3.tga", "kufemgrd1.tga", "kufemgrd2.tga", "kufemgrd3.tga", "kufmelite1.tga", "kufmelite2.tga", "kufmelite3.tga", "kukym_bust1.TGA", "kukym_bust2.TGA", "kukym_bust3.TGA", "kukym1.tga", "kukym2.tga", "kukym3.tga", "kumelite1.tga", "kumgrd1.tga", "kumgrd2.tga", "kumgrd3.tga", "li_commtrader_body_1.tga", "li_commtrader_body_2.tga", "li_commtrader_body_3.tga", "li_elite_female_1.tga", "li_elite_female_2.tga", "li_elite_female_3.tga", "li_elite_male_1.tga", "li_elite_male_2.tga", "li_elite_male_3.tga", "li_guard_female_1.TGA", "li_guard_female_2.TGA", "li_guard_female_3.TGA", "li_guard_male_1.tga", "li_guard_male_2.tga", "li_guard_male_3.tga", "li_hatcher_body_1.tga", "li_hatcher_body_2.TGA", "li_hatcher_body_3.TGA", "li_Rockford_body_1.tga", "li_Rockford_body_2.tga", "li_Rockford_body_3.tga", "li_scrote_body_1.tga", "li_scrote_body_2.tga", "li_scrote_body_3.tga", "li_shipdealer_body_1.tga", "li_shipdealer_body_2.tga", "li_shipdealer_body_3.tga", "li_Tilton_body_1a.TGA", "li_Tilton_body_2a.TGA", "li_Tilton_body_3a.tga", "pi_Orillion_body_1.tga", "pi_Orillion_body_2.TGA", "pi_Orillion_body_3.TGA", "pi_pirate1_body_1.tga", "pi_pirate1_body_2.tga", "pi_pirate1_body_3.tga", "pi_pirate2_body_1.TGA", "pi_pirate2_body_2.TGA", "pi_pirate2_body_3.TGA", "pi_pirate3_body_1.TGA", "pi_pirate3_body_2.tga", "pi_pirate3_body_3.TGA", "pi_pirate4_body_1.TGA", "pi_pirate4_body_2.TGA", "pi_pirate4_body_3.TGA", "pi_pirate5_body_1.TGA", "pi_pirate5_body_2.TGA", "pi_pirate5_body_3.TGA", "pi_pirate6_body_1.TGA", "pi_pirate6_body_2.TGA", "pi_pirate6_body_3.TGA", "pi_pirate7_body_1.TGA", "pi_pirate7_body_2.TGA", "pi_pirate7_body_3.TGA", "pi_pirate8_body_1.TGA", "pi_pirate8_body_2.TGA", "pi_pirate8_body_3.TGA", "pl_female1_ 1 JY.TGA", "pl_female1_ 2 JY.TGA", "pl_female1_ 3 JY.TGA", "pl_female1_ 4 JY.TGA", "pl_female1_1 PE.TGA", "pl_female1_1 PE_bust.TGA", "pl_female1_2 PE.tga", "pl_female1_2 PE_bust.TGA", "pl_female1_3 PE.tga", "pl_female1_3 PE_bust.TGA", "pl_female2_1 JY.tga", "pl_female2_1 PE.tga", "pl_female2_2 JY.tga", "pl_female2_2 PE.tga", "pl_female2_3 JY.tga", "pl_female2_3 PE.TGA", "pl_female2_4 JY.TGA", "pl_female6_head02.tga", "pl_male1_1 JY.tga", "pl_male1_1 PE.tga", "pl_male1_2 JY.tga", "pl_male1_2 PE.tga", "pl_male1_3 JY.tga", "pl_male1_3 PE.tga", "pl_male2_ 1 JY.tga", "pl_male2_ 2 JY.tga", "pl_male2_ 3 JY.tga", "pl_male2_1 PE.tga", "pl_male2_2 PE.TGA", "pl_male2_3 PE.TGA", "pl_male3_1 JY.tga", "pl_male3_1 PE.TGA", "pl_male3_2 JY.tga", "pl_male3_2 PE.TGA", "pl_male3_3 JY.tga", "pl_male3_3 PE.TGA", "pl_male3_4 JY.tga", "Quigley 1 01.tga", "Quigley 2 01.tga", "Quigley 3 01.tga", "rh_commtrader_body_1 .tga", "rh_commtrader_body_2 .tga", "rh_commtrader_body_3 .tga", "rh_didrbod_1.tga", "rh_didrbod_2.tga", "rh_didrbod_3.tga", "rh_elite_female_1.tga", "rh_elite_female_2.tga", "rh_elite_female_3.tga", "rh_elite_male_1.tga", "rh_elite_male_2.tga", "rh_elite_male_3.tga", "rh_gruenwald_body_1.tga", "rh_gruenwald_body_2.tga", "rh_gruenwald_body_3.tga", "rh_guard_female_1.tga", "rh_guard_female_2.tga", "rh_guard_female_3.tga", "rh_guard_male_1.tga", "rh_guard_male_2.tga", "rh_guard_male_3.tga", "rh_reichman_body_1.tga", "rh_reichman_body_2.tga", "rh_reichman_body_3.tga", "rh_shipdealer_body_1.tga", "rh_shipdealer_body_2.tga", "rh_shipdealer_body_3.tga", "rh_wilhelm_body_1.tga", "rh_wilhelm_body_2.tga", "rh_wilhelm_body_3.tga", "sc_female1_1.TGA", "sc_female1_2.TGA", "sc_female1_3.TGA", "sc_scientist1_1.TGA", "sc_scientist1_2.TGA", "sc_scientist1_3.TGA", "sc_scientist2_1.TGA", "sc_scientist2_2.TGA", "sc_scientist2_3.TGA", "sc_scientist3_1.TGA", "sc_scientist3_2.TGA", "sc_scientist3_3.TGA", "sc_scientist4_1.TGA", "sc_scientist4_2.TGA", "sc_scientist4_3.TGA", "sh_female1_body_1.tga", "sh_female1_body_2.tga", "sh_female1_body_3.tga", "sh_male1_body_1.tga", "sh_male1_body_2.tga", "sh_male1_body_3.tga", "sh_male2_body_1.tga", "sh_male2_body_2.tga", "sh_male2_body_3.tga", "sh_male3_body_1.tga", "sh_male3_body_2.tga", "sh_male3_body_3.tga", "WORM.TGA", "x_li_bartender_body_1.tga", "x_li_bartender_body_2.tga", "x_li_bartender_body_3.tga" + ], + "Roughness" : 0.8, + "Metalness" : 0.0 + }, + { + "TextureNames": [ + "pl_trent_1.tga","pl_trent_2.tga","pl_trent_3.tga","pl_trent_4.tga" + ], + "Roughness" : 0.9, + "Metalness" : 0.5 + }, + { + "TextureNames": [ + "li_bartender_body_1.tga","li_bartender_body_2.tga","li_bartender_body_3.tga", + "br_bartender_body_1.tga","br_bartender_body_2.tga","br_bartender_body_3.tga", + "ku_bartender_body 1.tga", "ku_bartender_body 2.tga", "ku_bartender_body 3.tga", + "rh_bartender_body_1.tga", "rh_bartender_body_2.tga", "rh_bartender_body_3.tga", + "l_bar#3_18.tga030106132759" + ], + "Roughness" : 0.9, + "Metalness" : 0.3 + }, + { + "TextureNames": [ + "bottles01.tga","glass01.tga","lib_bar_n_klava.tga" + ], + "Roughness" : 0.01, + "Metalness" : 0.0 + }, + { + "TextureNames": [ + "ast_icecrystal.tga","ice asteroid.tga","ice_block.tga","ice_carbon.tga","order base_snow straight.tga021126124128","order base_snow in corner.tga021126124128" + ], + "Roughness" : 0.1, + "Metalness" : 0.0, + "RoughnessTextureBias" : -0.1 + }, + { + "TextureName": "space_girder01.tgaspace_girder_op.tga", + "Roughness" : 0.01, + "Metalness" : 0.99, + "AlphaTestValue" : 0.9 + }, + { + "TextureName": "x_pnl_a.tga", + "AlphaTestValue" : 0.9 + }, + { + "TextureName": "bad_obsidian.tga", + "Metalness" : 0.0, + "RoughnessTextureBias" : 0.5 + }, + { + "TextureNames": [ + "lavastroid.tga","lavastroid02.tga","rock_detail.tga","rock3b.tga","rock3c.tga","rock3d128.tga","rock4.PSD","asteroid_rock_01.tga","atlantis_stone.tga","minable.tga","mineable_grayscale.tga","mineable_plain.tga","minedout.tga","nomad02.tga","nomad_01.tga", + "order base_snow rock.tga021126124128","order base_cliff.tga021126124128","order base Transiton End Corner.tga021126124128","order base Transiton Fade.tga021126124128","order base Transiton Corner.tga021126124128","uranium_tile.tga","uranium_tile1.tga","mineable_beryl.tga" + ], + "Metalness" : 0.0, + "Roughness" : 0.9, + "RoughnessTextureBias" : 0.45 + } + ] +} \ No newline at end of file