diff --git a/EXE/FLAR.dll b/EXE/FLAR.dll index d6c0c736..f8b3df2a 100644 Binary files a/EXE/FLAR.dll and b/EXE/FLAR.dll differ diff --git a/FLARDATA/MyGUI_Media/DeveloperOptions.layout b/FLARDATA/MyGUI_Media/DeveloperOptions.layout index ecc5835b..734bb104 100644 --- a/FLARDATA/MyGUI_Media/DeveloperOptions.layout +++ b/FLARDATA/MyGUI_Media/DeveloperOptions.layout @@ -1,38 +1,44 @@  - + - + - - - + + + - - + + - + - + - + - + - + + + + + + + diff --git a/FLARDATA/MyGUI_Media/Settings.layout b/FLARDATA/MyGUI_Media/Settings.layout index 028d2064..24946801 100644 --- a/FLARDATA/MyGUI_Media/Settings.layout +++ b/FLARDATA/MyGUI_Media/Settings.layout @@ -61,8 +61,8 @@ - - + + @@ -77,16 +77,17 @@ - + - + - + + diff --git a/FLARDATA/Shader/ColorConversion.inc b/FLARDATA/Shader/ColorConversion.inc index d6401b4b..f270e0dd 100644 --- a/FLARDATA/Shader/ColorConversion.inc +++ b/FLARDATA/Shader/ColorConversion.inc @@ -55,5 +55,5 @@ vec3 ToGammaCorrected(vec3 inColor) //Values are from https://en.wikipedia.org/wiki/Luma_(video) float ToLuma(vec3 color) { - return dot(color, vec3(0.2126, 0.7152f, 0.0722f)); + return dot(color, vec3(0.2126, 0.7152, 0.0722)); } \ No newline at end of file diff --git a/FLARDATA/Shader/fixedFunction.fp b/FLARDATA/Shader/fixedFunction.fp index 06475d78..7283e74c 100644 --- a/FLARDATA/Shader/fixedFunction.fp +++ b/FLARDATA/Shader/fixedFunction.fp @@ -60,6 +60,7 @@ uniform bool enableAlphaTest; uniform bool enableCubemap; uniform bool enableRHWCoordinates; uniform bool enableAccurateSRGB; +uniform bool isInstancedTransparent; in vec3 N; in vec3 v; @@ -246,7 +247,7 @@ void main() else { vertexAmbientColor=matAmbientColor.rgb; - gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor,matDiffuseColor.a); + gouradDiffuseColor=vec4(ambientColor*vertexAmbientColor, isInstancedTransparent ? vertexColor.a : matDiffuseColor.a); } //FL never has specular lighting enabled specularColor=vec4(0,0,0,0); @@ -384,7 +385,7 @@ void main() } else if (fogMode == 1) { - fogFactor =exp(-glFog.density * z); + fogFactor =exp(-glFog.density * z); } else if (fogMode == 2) { @@ -394,8 +395,10 @@ void main() fogFactor = 1; fogFactor = clamp(fogFactor, 0.0, 1.0); - finalColor.rgb = mix(glFog.color.rgb,finalColor.rgb, fogFactor); + finalColor.rgb = mix(glFog.color.rgb,ToGammaCorrected(finalColor.rgb), fogFactor); + gl_FragColor = vec4((finalColor.rgb), finalColor.a); } - gl_FragColor = vec4(ToGammaCorrected(finalColor.rgb), finalColor.a); + else + gl_FragColor = vec4(ToGammaCorrected(finalColor.rgb), finalColor.a); //gl_FragColor = finalColor; } diff --git a/FLARDATA/Shader/fixedFunction.vs b/FLARDATA/Shader/fixedFunction.vs index 24d9fcaa..38486d67 100644 --- a/FLARDATA/Shader/fixedFunction.vs +++ b/FLARDATA/Shader/fixedFunction.vs @@ -26,7 +26,7 @@ uniform bool enableRHWCoordinates; uniform mat4 modelViewMat; uniform mat4 projectionMat; uniform mat3 normalMat; -uniform vec2 projCorrection; +uniform vec2 projCorrection[2]; uniform mat4 textureMatrix[2]; uniform bool isInstanced; uniform bool isInstancedTransparent; @@ -78,7 +78,8 @@ void main() 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); + const float offset=63.0f / 128.0f; + gl_Position = vec4(((inPosition.x+offset)*projCorrection[0].x-1)*projCorrection[1].x,(1-(inPosition.y+offset)*projCorrection[0].y)*projCorrection[1].y,inPosition.z*2-1,1); RHWdepth = inPosition.z/inPosition.w; } diff --git a/FLARDATA/Shader/lighting.fp b/FLARDATA/Shader/lighting.fp index 71a206c7..3250acbd 100644 --- a/FLARDATA/Shader/lighting.fp +++ b/FLARDATA/Shader/lighting.fp @@ -58,6 +58,7 @@ struct Light{ struct glFogParameters { vec3 color; + vec3 colorLinear; float density; float start; float end; @@ -171,15 +172,14 @@ float ShadowCalculation(const float bias, const int shadowMapIndex, const int li float ShadowCalculationForAllSplitPlanes(const int lightIndex, const vec3 lightDirViewSpace, const vec3 normal, float lightIntensity, const sampler2DArrayShadow shadowSampler) { - float distance = v.z; + 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 @@ -468,7 +468,7 @@ void main(void) { float fogFactor = 0; if (enableFog && fogMode > 0) - { + { //Radial fog float z = length(v); if (fogMode == 3) @@ -476,12 +476,12 @@ void main(void) fogFactor = (fogEnd - z) * fogScale; } else if (fogMode == 1) - { - fogFactor = 1.0/exp(glFog.density * z); + { + fogFactor = exp(-glFog.density * z); } else if (fogMode == 2) { - fogFactor = 1.0 /exp( (z * glFog.density)* (z * glFog.density)); + fogFactor = exp(- pow(z * glFog.density,2)); } fogFactor = clamp(fogFactor, 0.0, 1.0); @@ -524,7 +524,8 @@ void main(void) firstTexture = vec4(1,1,1,1); } - float alpha = alphaValue*firstTexture.a; + float alpha = alphaValue*firstTexture.a; + if (enableAlphaTest) if(alphaTestCompareMethod==5) { @@ -592,7 +593,7 @@ void main(void) vec3 radiance; if (enableFog) { - vec3 ambientTint=PBR_FACTOR_ENV*glFog.color.rgb; + vec3 ambientTint=PBR_FACTOR_ENV*glFog.colorLinear.rgb; irradiance = vec3(texture(irradianceMap, n).r)*ambientTint; radiance = vec3(textureLod(envMap, reflectDir, lod).r)*ambientTint; } @@ -715,8 +716,9 @@ void main(void) if (enableFog && fogMode > 0) { - finalColor = mix(vec4(glFog.color,1.0),finalColor, fogFactor); + finalColor.rgb = mix(glFog.color.rgb,ToGammaCorrected(finalColor.rgb), fogFactor); + diffuseColorOut=vec4(finalColor.rgb,finalColor.a); } - - diffuseColorOut=vec4(ToGammaCorrected(finalColor.rgb),finalColor.a); + else + 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 index 1d1908b7..932dc6f7 100644 --- a/FLARDATA/Shader/lighting.vs +++ b/FLARDATA/Shader/lighting.vs @@ -22,6 +22,7 @@ out float fogScale; struct glFogParameters { vec3 color; + vec3 colorLinear; float density; float start; float end; diff --git a/FLARDATA/Shader/postProcess.fp b/FLARDATA/Shader/postProcess.fp index 8e42ad9c..eaa54252 100644 --- a/FLARDATA/Shader/postProcess.fp +++ b/FLARDATA/Shader/postProcess.fp @@ -6,7 +6,7 @@ #version 330 #include "ColorConversion.inc" -#define USE_ACES_CURVE $USE_ACES_CURVE +#define USE_CURVE $USE_CURVE #define USE_PBR_BLOOM $USE_PBR_BLOOM in vec2 TexCoords; @@ -91,6 +91,108 @@ vec3 uchimura(vec3 x) { return uchimura(x, P, a, m, l, c, b); } +//new agx from https://github.com/godotengine/godot/pull/106940 +//C++ Code moved to shader by me (Schmackbolzen): + +const float tonemap_agx_white = 16.29; // Default to Blender's AgX white. +const float tonemap_agx_contrast = 1.25; +const float output_max_value = 1.0; + +// Calculate allenwp tonemapping curve parameters on the CPU to improve shader performance. +// Source and details: https://allenwp.com/blog/2025/05/29/allenwp-tonemapping-curve/ + +// These constants must match the those in the shader code. +// 18% "middle gray" is perceptually 50% of the brightness of reference white. +const float awp_crossover_point = 0.18; +// When output_max_value and/or awp_crossover_point are no longer constant, awp_shoulder_max can +// be calculated on the CPU and passed in as tonemap_parameters.tonemap_e. +const float awp_shoulder_max = output_max_value - awp_crossover_point; + +// awp_toe_a is a solution generated by Mathematica that ensures intersection at awp_crossover_point. +const float awp_toe_a = ((1.0 / awp_crossover_point) - 1.0) * pow(awp_crossover_point, tonemap_agx_contrast); +// Slope formula is simply the derivative of the toe function with an input of awp_crossover_point. +const float awp_slope_denom = pow(awp_crossover_point, tonemap_agx_contrast) + awp_toe_a; +const float awp_slope = (tonemap_agx_contrast * pow(awp_crossover_point, tonemap_agx_contrast - 1.0) * awp_toe_a) / (awp_slope_denom * awp_slope_denom); + +const float awp_high_clip = tonemap_agx_white; +const float awp_w=pow(awp_high_clip - awp_crossover_point,2)/awp_shoulder_max*awp_slope; + +const float awp_contrast = tonemap_agx_contrast; +//End c++ code + +// allenwp tonemapping curve; developed for use in the Godot game engine. +// Source and details: https://allenwp.com/blog/2025/05/29/allenwp-tonemapping-curve/ +// Input must be a non-negative linear scene value. +vec3 allenwp_curve(vec3 x) { + + // Reinhard-like shoulder: + vec3 s = x - awp_crossover_point; + vec3 slope_s = awp_slope * s; + s = slope_s * (1.0 + s / awp_w) / (1.0 + (slope_s / awp_shoulder_max)); + s += awp_crossover_point; + + // Sigmoid power function toe: + vec3 t = pow(x, vec3(awp_contrast)); + t = t / (t + awp_toe_a); + + return mix(s, t, lessThan(x, vec3(awp_crossover_point))); +} + +// This is an approximation and simplification of EaryChow's AgX implementation that is used by Blender. +// This code is based off of the script that generates the AgX_Base_sRGB.cube LUT that Blender uses. +// Source: https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBasesRGB.py +// Colorspace transformation source: https://www.colour-science.org:8010/apps/rgb_colourspace_transformation_matrix +vec3 tonemap_agx(vec3 color) { + // Input color should be non-negative! + // Large negative values in one channel and large positive values in other + // channels can result in a colour that appears darker and more saturated than + // desired after passing it through the inset matrix. For this reason, it is + // best to prevent negative input values. + // This is done before the Rec. 2020 transform to allow the Rec. 2020 + // transform to be combined with the AgX inset matrix. This results in a loss + // of color information that could be correctly interpreted within the + // Rec. 2020 color space as positive RGB values, but is often not worth + // the performance cost of an additional matrix multiplication. + // + // Additionally, this AgX configuration was created subjectively based on + // output appearance in the Rec. 709 color gamut, so it is possible that these + // matrices will not perform well with non-Rec. 709 output (more testing with + // future wide-gamut displays is be needed). + // See this comment from the author on the decisions made to create the matrices: + // https://github.com/godotengine/godot-proposals/issues/12317#issuecomment-2835824250 + + // Combined Rec. 709 to Rec. 2020 and Blender AgX inset matrices: + const mat3 rec709_to_rec2020_agx_inset_matrix = mat3( + 0.544814746488245, 0.140416948464053, 0.0888104196149096, + 0.373787398372697, 0.754137554567394, 0.178871756420858, + 0.0813978551390581, 0.105445496968552, 0.732317823964232); + + // Combined inverse AgX outset matrix and Rec. 2020 to Rec. 709 matrices. + const mat3 agx_outset_rec2020_to_rec709_matrix = mat3( + 1.96488741169489, -0.299313364904742, -0.164352742528393, + -0.855988495690215, 1.32639796461980, -0.238183969428088, + -0.108898916004672, -0.0270845997150571, 1.40253671195648); + + // Apply inset matrix. + color = rec709_to_rec2020_agx_inset_matrix * color; + + // Use the allenwp tonemapping curve to match the Blender AgX curve while + // providing stability across all variable dyanimc range (SDR, HDR, EDR). + color = allenwp_curve(color); + + // Clipping to output_max_value is required to address a cyan colour that occurs + // with very bright inputs. + color = min(vec3(output_max_value), color); + + // Apply outset to make the result more chroma-laden and then go back to Rec. 709. + color = agx_outset_rec2020_to_rec709_matrix * color; + + // Blender's lusRGB.compensate_low_side is too complex for this shader, so + // simply return the color, even if it has negative components. These negative + // components may be useful for subsequent color adjustments. + return color; +} + #if USE_PBR_BLOOM == 1 const float bloomStrength = 0.2f; vec4 bloom_new() @@ -117,14 +219,16 @@ void main() #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); + //Exposure is chosen so that all curves have about the same brightness and the look is fine with very bright starspheres like in Tau-37 +#if USE_CURVE == 0 + color.rgb =tonemap_agx(exposure*color.rgb); +#elif USE_CURVE == 1 + color.rgb=ACESFitted(exposure*color.rgb); +#elif USE_CURVE == 2 + 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/Textures/NormalMaps/m_hatch01.tga.dds b/FLARDATA/Textures/NormalMaps/m_hatch01.tga.dds index e8bfe353..25fdbd3b 100644 Binary files a/FLARDATA/Textures/NormalMaps/m_hatch01.tga.dds and b/FLARDATA/Textures/NormalMaps/m_hatch01.tga.dds differ diff --git a/FLARDATA/Textures/NormalMaps/m_panels.tga.dds b/FLARDATA/Textures/NormalMaps/m_panels.tga.dds index 3d5f644b..016274a0 100644 Binary files a/FLARDATA/Textures/NormalMaps/m_panels.tga.dds and b/FLARDATA/Textures/NormalMaps/m_panels.tga.dds differ diff --git a/FLARDATA/materials.json b/FLARDATA/materials.json index b5f87b78..8d1c3f6e 100644 --- a/FLARDATA/materials.json +++ b/FLARDATA/materials.json @@ -49,6 +49,7 @@ "gasblucld01", "gasblucld02", "gasblucldcap", + "gasblucld_single", "gasgrncld01", "gasgrncld02", "gasgrncldcap", @@ -160,7 +161,7 @@ "uranusside", "venus" ], - "Roughness" : 1.0, + "Roughness" : 0.01, "Metalness" : 0.0 }, { @@ -1088,7 +1089,7 @@ "rock4.PSD", "asteroid_rock_01.tga", "atlantis_stone.tga", - "minable.tga", + "mineable.tga", "mineable_grayscale.tga", "mineable_plain.tga", "minedout.tga", @@ -1101,8 +1102,8 @@ "mineable_beryl.tga", "ast_ice01_outside.dds" ], - "Metalness" : 0.0, - "Roughness" : 0.9, + "Metalness" : 0.2, + "Roughness" : 0.6, "RoughnessTextureBias" : 0.45 } ] diff --git a/FLARDATA/modsettings.cfg b/FLARDATA/modsettings.cfg new file mode 100644 index 00000000..b7653c33 --- /dev/null +++ b/FLARDATA/modsettings.cfg @@ -0,0 +1,8 @@ +ExposureLimitMin=0.2 +ExposureLimitMax=4 +TargetLuminance=0.6 +MinStickyTimeMs=500 +ExposureChangeTimeMs=750 +ApplyProjectileLightAnimCrashFix=1 +DebugLogTextureLoading=0 +EnablePointLights=0