- 好友
- 11
- 在线时间
- 0 小时
- 最后登录
- 2024-12-26
见习骑士
- UID
- 3257703
- 第纳尔
- 2747
- 精华
- 0
- 互助
- 19
- 荣誉
- 2
- 贡献
- 10
- 魅力
- 167
- 注册时间
- 2021-8-1
鲜花( 86) 鸡蛋( 0)
|
本帖最后由 fengguoyehao 于 2023-2-1 20:22 编辑
如果大家体验过战团重置版,肯定会对战团重置版提升画质的方法感到好奇。今天我们就来聊一聊提升战团重置版画质的核心:postFX.fx
在阅读本文之前,如果你不了解战团的shaders,可以阅读这个帖子,里面的介绍写得很清晰:【shaders技术研究】关于骑砍中的着色器的编辑方法 - MOD制作资料区 - 骑马与砍杀中文站论坛 - Powered by Discuz! (mountblade.com.cn)(其实我不太懂高级着色器语言,以下内容是我花了半年时间自学的。如果有会高级着色器语言的大神看到这篇文章,欢迎补充内容!顺便请帮忙看看Reshade的光追效果有没有可能移植到战团的postFX.fx里,万分感谢!)
让我们进入正题:
postFX.fx控制着战团的HDR、自动调光和动态模糊效果。战团重置版的postFX.fx包含SSAO效果和后期调色效果。其中,SSAO效果勾选“动态模糊”启用,后期调色效果可以通过打开HDR启用。
以下为postFX.fx代码,可以使用Sublime Text来编写。
SSAO(环境光遮蔽):
关于SSAO效果,在外网论坛上有代码(Pure Depth SSAO (theorangeduck.com))。这个代码不够完整,不过Tama将这份代码改了改,成功地写入了postFX.fx(OSP - Shaders - Tama's Shaders (Dynamic Parallax Occlusion & Parallax & SSAO) | TaleWorlds Forums),完整代码如下:- sampler postFX_sampler5 : register(s5);// depth
- float3 randomNormal(float2 tex)
- {
- float noiseX = (frac(sin(dot(tex, float2(15.8989f, 76.132f)*1.0f))*46336.23745f));
- float noiseY = (frac(sin(dot(tex, float2(11.9899f, 62.223f)*2.0f))*34748.34744f));
- float noiseZ = (frac(sin(dot(tex, float2(13.3238f, 63.122f)*3.0f))*59998.47362f));
- return normalize(float3(noiseX, noiseY, noiseZ));
- }
-
- float3 normal_from_depth(float depth, float2 texcoords) {
-
- const float2 offset1 = float2(0.0,0.001);
- const float2 offset2 = float2(0.001,0.0);
-
- float depth1 = tex2D(postFX_sampler5, texcoords + offset1).r;
- float depth2 = tex2D(postFX_sampler5, texcoords + offset2).r;
-
- float3 p1 = float3(offset1, depth1 - depth);
- float3 p2 = float3(offset2, depth2 - depth);
-
- float3 normal = cross(p1, p2);
- normal.z = -normal.z;
-
- return normalize(normal);
- }
- const float total_strength = 1.5f;
- const float base = 0.6f;
-
- const float area = 0.0075;
- const float falloff = 0.00001;
-
- const float radius = 0.0002;
-
- const int samples = 16;
- float3 sample_sphere[samples] = {
- float3( 0.5381, 0.1856,-0.4319), float3( 0.1379, 0.2486, 0.4430),
- float3( 0.3371, 0.5679,-0.0057), float3(-0.6999,-0.0451,-0.0019),
- float3( 0.0689,-0.1598,-0.8547), float3( 0.0560, 0.0069,-0.1843),
- float3(-0.0146, 0.1402, 0.0762), float3( 0.0100,-0.1924,-0.0344),
- float3(-0.3577,-0.5301,-0.4358), float3(-0.3169, 0.1063, 0.0158),
- float3( 0.0103,-0.5869, 0.0046), float3(-0.0897,-0.4940, 0.3287),
- float3( 0.7119,-0.0154,-0.0918), float3(-0.0533, 0.0596,-0.5411),
- float3( 0.0352,-0.0631, 0.5460), float3(-0.4776, 0.2847,-0.0271)
- };
-
- float3 random = normalize( randomNormal( inTex * 4.0) );
-
- float depth = tex2D(postFX_sampler5, inTex).r;
-
- float3 position = float3(inTex, depth);
- float3 normal = normal_from_depth(depth, inTex);
-
- float radius_depth = radius/depth;
- float occlusion = 0.0;
- for(int i=0; i < samples; i++) {
-
- float3 ray = radius_depth * reflect(sample_sphere[i], random);
- float3 hemi_ray = position + sign(dot(ray,normal)) * ray;
-
- float occ_depth = tex2D(postFX_sampler5, saturate(hemi_ray.xy)).r;
- float difference = depth - occ_depth;
-
- occlusion += step(falloff, difference) * (1.0-smoothstep(falloff, area, difference));
- }
-
- float ao = 1.0 - total_strength * occlusion * (1.0 / samples);
-
- float ssao = saturate(ao + base);
-
- return float4(color, ssao); //WEIRD!
- color.rgb *= tex2D(postFX_sampler1, texCoord).a; //Enhanced
复制代码
后期调色功能(HDR):
思路是移植Reshade和sweetfx(其实两个是一个东西)里面的fx文件语言到postFX.fx里,也就是大家熟知的“滤镜”效果。
Reshade是一个开源的二次渲染软件,但用于战团时有很多问题,比如说ui渲染不同步,无法获取深度信息...最重要的是,它和ENB一样十分吃配置。将Reshade的语言移植到postFX.fx里面可以最大程度上进行帧数优化。
后期调色功能得以实现,要感谢@杜撰。以下的Filimcpass,DPX,Vibrance,Technicolor2,Tint(Sepia),LiftGammaGain都是@杜撰最早移植的。可以说,@杜撰为战团的画质带来了一场革命!
下面,我来展示一些移植成功的语言。
移植fx代码:- //FilmicPass {{{2
- float3 LumCoeff = float3(0.212656, 0.715158, 0.072186);
- color.rgb = FilmicPass(color.rgb,
- 0.7, 0.30, 1.0,
- 0.5, 0.0, -0.1,
- 1.0, 1.0, 1.5,
- 1,
- 1.0,
- 1.50,
- 0.900, 1.300, 1.20,
- LumCoeff);
复制代码- //Tonemap {{{2
- float3 Tonemap(float3 color, float Gamma, float Exposure, float Saturation, float Bleach, float Defog, float3 FogColor)
- {
- float3 colorr = color;
- colorr = saturate(colorr - Defog * FogColor * 2.55); // Defog
- colorr *= pow(2.0f, Exposure); // Exposure
- colorr = pow(colorr, Gamma); // Gamma
- const float3 coefLuma = float3(0.2126, 0.7152, 0.0722);
- float lum = dot(coefLuma, colorr);
-
- float L = saturate(10.0 * (lum - 0.45));
- float3 A2 = Bleach * colorr;
- float3 result1 = 2.0f * colorr * lum;
- float3 result2 = 1.0f - 2.0f * (1.0f - lum) * (1.0f - colorr);
-
- float3 newColor = lerp(result1, result2, L);
- float3 mixRGB = A2 * newColor;
- colorr += ((1.0f - A2) * mixRGB);
-
- float3 middlegray = dot(colorr, (1.0 / 3.0));
- float3 diffcolor = colorr - middlegray;
- colorr = (colorr + diffcolor * Saturation) / (1 + (diffcolor * Saturation)); // Saturation
-
- return colorr;
- }
复制代码- //Sepia {{{2
- float3 Sepia(float3 col, float I, float3 RGB)
- {
- return lerp(col, col * RGB * 2.55, I);
- }
复制代码- //LiftGammaGain {{{2
- float3 LiftGammaGain(float3 color, float3 RGB_Lift, float3 RGB_Gamma, float3 RGB_Gain)
- {
- color = color * (1.5 - 0.5 * RGB_Lift) + 0.5 * RGB_Lift - 0.5;
- color = saturate(color); // Is not strictly necessary, but does not cost performance
- // -- Gain --
- color *= RGB_Gain;
- // -- Gamma --
- color = pow(color, 1.0 / RGB_Gamma);
- return saturate(color);
- }
复制代码- //Technicolor {{{2
- //
- float3 Technicolor(float3 color, float Power, float3 RGBNegativeAmount, float Strength)
- {
- const float3 cyanfilter = float3(0.0, 1.30, 1.0);
- const float3 magentafilter = float3(1.0, 0.0, 1.05);
- const float3 yellowfilter = float3(1.6, 1.6, 0.05);
- const float2 redorangefilter = float2(1.05, 0.620); // RG_
- const float2 greenfilter = float2(0.30, 1.0); // RG_
- const float2 magentafilter2 = magentafilter.rb; // R_B
- float3 tcol = color;
-
- float2 negative_mul_r = tcol.rg * (1.0 / (RGBNegativeAmount.r * Power));
- float2 negative_mul_g = tcol.rg * (1.0 / (RGBNegativeAmount.g * Power));
- float2 negative_mul_b = tcol.rb * (1.0 / (RGBNegativeAmount.b * Power));
- float3 output_r = dot(redorangefilter, negative_mul_r).xxx + cyanfilter;
- float3 output_g = dot(greenfilter, negative_mul_g).xxx + magentafilter;
- float3 output_b = dot(magentafilter2, negative_mul_b).xxx + yellowfilter;
- return lerp(tcol, output_r * output_g * output_b, Strength);
- }
复制代码- //Technicolor2 {{{2
- //
- float3 Technicolor2(float3 color, float3 colorStrength, float Brightness, float Saturation, float Strength)
- {
- float3 colorr = color;
- float3 temp = 1.0 - colorr;
- float3 target = temp.grg;
- float3 target2 = temp.bbr;
- float3 temp2 = colorr * target;
- temp2 *= target2;
- temp = temp2 * colorStrength;
- temp2 *= Brightness;
- target = temp.grg;
- target2 = temp.bbr;
- temp = colorr - target;
- temp += temp2;
- temp2 = temp - target2;
- colorr = lerp(colorr, temp2, Strength);
- colorr = lerp(dot(colorr, 0.333), colorr, Saturation);
- return colorr;
- }
复制代码- //DPX {{{2
- //
- static const float3x3 RGB = float3x3(
- 2.6714711726599600, -1.2672360578624100, -0.4109956021722270,
- -1.0251070293466400, 1.9840911624108900, 0.0439502493584124,
- 0.0610009456429445, -0.2236707508128630, 1.1590210416706100
- );
- static const float3x3 XYZ = float3x3(
- 0.5003033835433160, 0.3380975732227390, 0.1645897795458570,
- 0.2579688942747580, 0.6761952591447060, 0.0658358459823868,
- 0.0234517888692628, 0.1126992737203000, 0.8668396731242010
- );
- float3 DPX(float3 color, float3 RGB_Curve, float3 RGB_C, float Contrast, float Saturation, float Colorfulness, float Strength)
- {
- float3 input = color;
- float3 B = input;
- B = B * (1.0 - Contrast) + (0.5 * Contrast);
- float3 Btemp = (1.0 / (1.0 + exp(RGB_Curve / 2.0)));
- B = ((1.0 / (1.0 + exp(-RGB_Curve * (B - RGB_C)))) / (-2.0 * Btemp + 1.0)) + (-Btemp / (-2.0 * Btemp + 1.0));
- float value = max(max(B.r, B.g), B.b);
- float3 colorr = B / value;
- colorr = pow(abs(colorr), 1.0 / Colorfulness);
- float3 c0 = colorr * value;
- c0 = mul(XYZ, c0);
- float luma = dot(c0, float3(0.30, 0.59, 0.11));
- c0 = (1.0 - Saturation) * luma + Saturation * c0;
- c0 = mul(RGB, c0);
- return lerp(input, c0, Strength);
- }
复制代码- //Vibrance {{{2
- float3 Vibrance(float3 color, float I, float3 RGB)
- {
- const float3 coefLuma = float3(0.212656, 0.715158, 0.072186);
- float luma = dot(coefLuma, color);
- float max_color = max(color.r, max(color.g, color.b)); // Find the strongest color
- float min_color = min(color.r, min(color.g, color.b)); // Find the weakest color
- float color_saturation = max_color - min_color; // The difference between the two is the saturation
- float3 coeffVibrance = float3(RGB * I);
- color = lerp(luma, color, 1.0 + (coeffVibrance * (1.0 - (sign(coeffVibrance) * color_saturation))));
- return color;
- }
复制代码
输出代码:
- //Technicolor {{{2
- color.rgb = Technicolor(color.rgb, 0.1, float3(0.4,0.3,0.6), 1.0);
复制代码- //Sepia {{{2
- color.rgb = Sepia(color.rgb, 0.3, float3(0.6,0.47,0.5));
复制代码- //Technicolor2 {{{2
- color.rgb = Technicolor2(color.rgb, float3(0.4,0.3,0.6), 1.0, 0.9, 0.5);
复制代码- //FilmicPass {{{2
- float3 LumCoeff = float3(0.212656, 0.715158, 0.072186);
- color.rgb = FilmicPass(color.rgb,
- 0.7, 0.30, 1.0,
- 0.5, 0.0, -0.1,
- 1.0, 1.0, 1.5,
- 1,
- 1.0,
- 1.50,
- 0.900, 1.300, 1.20,
- LumCoeff);
复制代码- //Vibrance {{{2
- color.rgb = Vibrance(color.rgb, 0.3, float3(0.6,0.6,1.0));
复制代码- //Lift Gamma Gain {{{2
- color.rgb = LiftGammaGain(color.rgb,
- float3(1.00,1.00,1.00),
- float3(1.00,1.00,1.00),
- float3(1.00,1.00,1.00));
复制代码- //DPX {{{2
- color.rgb = DPX(color.rgb, float3(15,15,15), float3(0.33,0.33,0.33), 0.20, 3.0, 1.4, 0.20);
复制代码- //Tonemap {{{2
- color.rgb = Tonemap(color.rgb, 1.0, 0.0, 0.0, 0.0, 1.0, float3(0.0,0.0,0.0));
复制代码
写入方法(以写入Vibrance功能和DPX功能为例,其余的以此类推):
1)找到这一段代码:- /////////////////////////////////////////////////////////////////////////////////////
- float4 FinalScenePassPS(uniform const bool use_dof, uniform const int use_hdr, uniform const bool use_auto_exp, float2 texCoord: TEXCOORD0) : COLOR {
-
- // Sample the scene
- float4 scene = tex2D(postFX_sampler0, texCoord);
- scene.rgb = pow(scene.rgb, output_gamma);
复制代码
在“//////////////////////////////////////////////////////////”下面一行添加// Func {{{1
就像这样:
- /////////////////////////////////////////////////////////////////////////////////////
- // Func {{{1
复制代码 再重起一行,添加Vibrance和DPX的fx代码,就像这样。在代码的最底下添加// Final {{{1(表示结束):- /////////////////////////////////////////////////////////////////////////////////////
- // Func {{{1
- //Vibrance {{{2
- float3 Vibrance(float3 color, float I, float3 RGB)
- {
- const float3 coefLuma = float3(0.212656, 0.715158, 0.072186);
- float luma = dot(coefLuma, color);
- float max_color = max(color.r, max(color.g, color.b)); // Find the strongest color
- float min_color = min(color.r, min(color.g, color.b)); // Find the weakest color
- float color_saturation = max_color - min_color; // The difference between the two is the saturation
- float3 coeffVibrance = float3(RGB * I);
- color = lerp(luma, color, 1.0 + (coeffVibrance * (1.0 - (sign(coeffVibrance) * color_saturation))));
- return color;
- }
- //DPX {{{2
- //
- static const float3x3 RGB = float3x3(
- 2.6714711726599600, -1.2672360578624100, -0.4109956021722270,
- -1.0251070293466400, 1.9840911624108900, 0.0439502493584124,
- 0.0610009456429445, -0.2236707508128630, 1.1590210416706100
- );
- static const float3x3 XYZ = float3x3(
- 0.5003033835433160, 0.3380975732227390, 0.1645897795458570,
- 0.2579688942747580, 0.6761952591447060, 0.0658358459823868,
- 0.0234517888692628, 0.1126992737203000, 0.8668396731242010
- );
- float3 DPX(float3 color, float3 RGB_Curve, float3 RGB_C, float Contrast, float Saturation, float Colorfulness, float Strength)
- {
- float3 input = color;
- float3 B = input;
- B = B * (1.0 - Contrast) + (0.5 * Contrast);
- float3 Btemp = (1.0 / (1.0 + exp(RGB_Curve / 2.0)));
- B = ((1.0 / (1.0 + exp(-RGB_Curve * (B - RGB_C)))) / (-2.0 * Btemp + 1.0)) + (-Btemp / (-2.0 * Btemp + 1.0));
- float value = max(max(B.r, B.g), B.b);
- float3 colorr = B / value;
- colorr = pow(abs(colorr), 1.0 / Colorfulness);
- float3 c0 = colorr * value;
- c0 = mul(XYZ, c0);
- float luma = dot(c0, float3(0.30, 0.59, 0.11));
- c0 = (1.0 - Saturation) * luma + Saturation * c0;
- c0 = mul(RGB, c0);
- return lerp(input, c0, Strength);
- }
- // Final {{{1
复制代码 2)找到这段代码:
- //--float2 luminanceAvgMax = tex2D(postFX_sampler2, float2(0.5f, 0.5f)).rg;
- //--return tex2D(postFX_sampler2, texCoord).y * 100;
复制代码
另起一行添加输出代码:- //--float2 luminanceAvgMax = tex2D(postFX_sampler2, float2(0.5f, 0.5f)).rg;
- //--return tex2D(postFX_sampler2, texCoord).y * 100;
- //Vibrance {{{2
- color.rgb = Vibrance(color.rgb, 0.3, float3(0.6,0.6,1.0));
- //DPX {{{2
- color.rgb = DPX(color.rgb, float3(15,15,15), float3(0.33,0.33,0.33), 0.58, 1.6, 1.5, 0.20);
复制代码
3)保存文件
分析部分:
1)关于调整数据:
以DPX为例,它的移植代码里面有这一行:
- float3 DPX(float3 color, float3 RGB_Curve, float3 RGB_C, float Contrast, float Saturation, float Colorfulness, float Strength)
复制代码 输出代码里面有这一行:
- color.rgb = DPX(color.rgb, float3(15,15,15), float3(0.33,0.33,0.33), 0.58, 1.6, 1.5, 0.20);
复制代码 看到这,你会发现float是一一对应的关系:
float3 RGB_Curve对应float3(15,15,15);float3 RGB_C对应float3(0.33,0.33,0.33);float Contrast对应0.58;float Saturation对应1.6;float Colorfulness对应1.5;float Strength对应0.20
2)实时调色
移植代码里面的功能和Reshade里面是一致的。
可以先下载一个Reshade,在Reshade里面把数据调好,再写入postFX.fx
总结:
postFX.fx可以实现的功能还有很多,比如说DOF。目前,我成功移植的Reshade语言仅限于调色功能。也许未来的某一天会有人找到移植MXAO,Lightroomdof,RTGI等高级功能的方法。
愿战团再战十年!
|
评分
-
查看全部评分
|