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