diff --git a/artifacts/example_mods/GlobalShaders/LumaSharpen.fx b/artifacts/example_mods/GlobalShaders/LumaSharpen.fx new file mode 100644 index 00000000..ef1b9617 --- /dev/null +++ b/artifacts/example_mods/GlobalShaders/LumaSharpen.fx @@ -0,0 +1,128 @@ +/************************************************************* + LumaSharpen version 1.5.0 for Reshade 3.x + by Christian Cann Schuldt Jensen ~ CeeJay.dk + + It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image. + It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts. + This is similar to using Unsharp Mask in Photoshop. + + Adapted to sfall by Mr.Stalin +*************************************************************/ + +// Strength of the sharpening +// min 0.1, max 3.0 +#define sharp_strength 0.75 + +// Limits maximum amount of sharpening a pixel receives. This helps avoid "haloing" artifacts which would otherwise occur when you raised the strength too much +// min 0.0, max 1.0, step 0.005 +#define sharp_clamp 0.035 + +// Offset bias adjusts the radius of the sampling pattern. I designed the pattern for an offset bias of 1.0, but feel free to experiment +// min 0.0, max 6.0 +#define offset_bias 1.0 + +//------------------------------------------------------// +// Developer settings // +//------------------------------------------------------// + +#define CoefLuma float3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television) +//#define CoefLuma float3(0.299, 0.587, 0.114) // BT.601 luma coefficient (SD Television) +//#define CoefLuma float3(1.0/3.0, 1.0/3.0, 1.0/3.0) // Equal weight coefficient + +sampler s0; + +float2 rcpres; // pixel size + +float4 LumaSharpenPS(float4 color : COLOR0, float2 tex : TEXCOORD) : COLOR0 +{ + // Get the original pixel + float3 ori = tex2D(s0, tex).rgb; // ori = original pixel + + // Combining the strength and luma multipliers + float3 sharp_strength_luma = (CoefLuma * sharp_strength); // I'll be combining even more multipliers with it later on + + //------------------------------------------------------// + // Sampling patterns // + //------------------------------------------------------// + float3 blur_ori; + + // [ NW, , NE ] Each texture lookup (except ori) + // [ ,ori, ] samples 4 pixels + // [ SW, , SE ] + + // -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches. + // + // -- Gaussian filter -- + // [ .25, .50, .25] [ 1 , 2 , 1 ] + // [ .50, 1, .50] = [ 2 , 4 , 2 ] + // [ .25, .50, .25] [ 1 , 2 , 1 ] + + blur_ori = tex2D(s0, tex + float2(rcpres.x, -rcpres.y) * 0.5 * offset_bias).rgb; // South East + blur_ori += tex2D(s0, tex - rcpres * 0.5 * offset_bias).rgb; // South West + blur_ori += tex2D(s0, tex + rcpres * 0.5 * offset_bias).rgb; // North East + blur_ori += tex2D(s0, tex - float2(rcpres.x, -rcpres.y) * 0.5 * offset_bias).rgb; // North West + blur_ori *= 0.25; // Divide by 4 the number of texture fetches + + // -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches. + // Wider is less sensitive to noise but also to fine details. + // -- Gaussian filter -- + // [ , 4 , 6 , , ] + // [ ,16 ,24 ,16 , 4 ] + // [ 6 ,24 , ,24 , 6 ] + // [ 4 ,16 ,24 ,16 , ] + // [ , , 6 , 4 , ] + + //blur_ori = tex2D(s0, tex + rcpres * float2(0.4, -1.2) * offset_bias).rgb; // South South East + //blur_ori += tex2D(s0, tex - rcpres * float2(1.2, 0.4) * offset_bias).rgb; // West South West + //blur_ori += tex2D(s0, tex + rcpres * float2(1.2, 0.4) * offset_bias).rgb; // East North East + //blur_ori += tex2D(s0, tex - rcpres * float2(0.4, -1.2) * offset_bias).rgb; // North North West + //blur_ori *= 0.25; // Divide by the number of texture fetches + //sharp_strength_luma *= 0.51; + + // -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches. + // Pyramid has a slightly more aggresive look + // -- Gaussian filter -- + // [ .50, .50, .50] [ 1 , 1 , 1 ] + // [ .50, , .50] = [ 1 , , 1 ] + // [ .50, .50, .50] [ 1 , 1 , 1 ] + + //blur_ori = tex2D(s0, tex + float2(0.5 * rcpres.x, -rcpres.y * offset_bias)).rgb; // South South East + //blur_ori += tex2D(s0, tex + float2(offset_bias * -rcpres.x, 0.5 * -rcpres.y)).rgb; // West South West + //blur_ori += tex2D(s0, tex + float2(offset_bias * rcpres.x, 0.5 * rcpres.y)).rgb; // East North East + //blur_ori += tex2D(s0, tex + float2(0.5 * -rcpres.x, rcpres.y * offset_bias)).rgb; // North North West + ////blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect. + //blur_ori /= 4.0; // Divide by the number of texture fetches + //sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2 + + //------------------------------------------------------// + // Sharpen // + //------------------------------------------------------// + + // Calculate the sharpening -- + float3 sharp = ori - blur_ori; // Subtracting the blurred image from the original image + + // Adjust strength of the sharpening and clamp it + float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / sharp_clamp), 0.5); // Roll part of the clamp into the dot + + //sharp_luma = saturate((0.5 / sharp_clamp) * sharp_luma + 0.5); // scale up and clamp + float sharp_luma = saturate(dot(float4(sharp, 1.0), sharp_strength_luma_clamp)); // Calculate the luma, adjust the strength, scale up and clamp + sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; // scale down + + // Combining the values to get the final sharpened pixel + float3 outputcolor = ori + sharp_luma; // Add the sharpening to the the original. + + //------------------------------------------------------// + // Returning the output // + //------------------------------------------------------// + + // Show sharpening pattern + // Visualize the strength of the sharpen\nThis is useful for seeing what areas the sharpning affects the most + //outputcolor = saturate(0.5 + (sharp_luma * 4.0)).rrr; //outputcolor = abs(sharp * 4.0); + + return float4(saturate(outputcolor), 1); +} + +technique LumaSharpen +{ + pass P0 { PixelShader = compile ps_2_0 LumaSharpenPS(); } +} diff --git a/artifacts/example_mods/GlobalShaders/global.fx b/artifacts/example_mods/GlobalShaders/global.fx index fac25d02..4991b3ed 100644 --- a/artifacts/example_mods/GlobalShaders/global.fx +++ b/artifacts/example_mods/GlobalShaders/global.fx @@ -31,11 +31,16 @@ sampler BloomSampler : samplerstate AddressV = Clamp; }; -// Variables that set the width and height of the current game resolution from sfall -float w; -float h; +// Variables that set the width and height of the current game resolution from sfall (only for global shaders) +int w; +int h; + +// the pixel size is computed as: 1.0f / resolution +float2 rcpRes; + +// system ticks (received from sfall) +//int tickcount; -static const float2 resolution = float2(w, h); static const float2 wPass = float2(1, 0); static const float2 hPass = float2(0, 1); @@ -60,7 +65,7 @@ float4 BlurDeltaPassPS(float2 uv : TEXCOORD0, uniform float2 delta) : COLOR0 float3 sumColor = (tex2D(s0, uv).rgb); float brightness = Brightness(sumColor); - delta *= (1 / resolution); + delta *= rcpRes; float totalWeight = 1; float2 pointUV = uv + delta; @@ -72,8 +77,8 @@ float4 BlurDeltaPassPS(float2 uv : TEXCOORD0, uniform float2 delta) : COLOR0 return float4((sumColor / totalWeight), 1); } -static const float2 wDelta = float2(1, 0) * (1 / resolution); -static const float2 hDelta = float2(0, 1) * (1 / resolution); +static const float2 wDelta = float2(1, 0) * rcpRes; +static const float2 hDelta = float2(0, 1) * rcpRes; float4 BlurPS(float4 color : COLOR0, float2 uv : TEXCOORD0) : COLOR0 { @@ -166,8 +171,8 @@ static const float sharpenVal0 = (Sharpen * (1.5 + EdgeSharpen)); static const float sharpenVal1 = ((sharpenVal0 - 1) / 8.0); // pixel "width" -static const float px = (1.0 / w); -static const float py = (1.0 / h); +static const float px = rcpRes.x; +static const float py = rcpRes.y; // for the blur filter #define mean 1.0 diff --git a/artifacts/example_mods/GlobalShaders/sharpen.fx b/artifacts/example_mods/GlobalShaders/sharpen.fx index 89e59532..165a3a51 100644 --- a/artifacts/example_mods/GlobalShaders/sharpen.fx +++ b/artifacts/example_mods/GlobalShaders/sharpen.fx @@ -1,3 +1,6 @@ +// Shader from Media Player Classic - Home Cinema +// Adapted to sfall by Mr.Stalin + /////////////////////////////////////////////////////////////////////////////// // Sharpen filter setting // @@ -6,24 +9,14 @@ // max: Sharpen 1.75, EdgeSharpen -0.5 (1.5, -0.25) /////////////////////////////////////////////////////////////////////////////// #define Sharpen 0.5 -#define EdgeSharpen 1.5 +#define EdgeSharpen 1.1 - -texture sharpenTex; sampler s0; -sampler SharpenSampler : samplerstate -{ - Texture = sharpenTex; - MinFilter = Linear; - MagFilter = Linear; - AddressU = Clamp; - AddressV = Clamp; -}; - // Variables that set the width and height of the current game resolution from sfall float w; float h; +float2 rcpres; // pixel size static const float CoefBlur = (Sharpen * 0.5); static const float CoefOrig = (1 + CoefBlur); @@ -34,8 +27,8 @@ static const float sharpenVal0 = (Sharpen * (1.5 + EdgeSharpen)); static const float sharpenVal1 = ((sharpenVal0 - 1) / 8.0); // pixel "width" -static const float px = (1.0 / w); -static const float py = (1.0 / h); +static const float px = rcpres.x; +static const float py = rcpres.y; // for the blur filter #define mean 1.0 diff --git a/sfall/FalloutEngine/Functions.cpp b/sfall/FalloutEngine/Functions.cpp index 37ee9ac2..fb3e9a80 100644 --- a/sfall/FalloutEngine/Functions.cpp +++ b/sfall/FalloutEngine/Functions.cpp @@ -42,71 +42,72 @@ void dev_printf(...) {} __asm call fo::funcoffs::offs #define WRAP_WATCOM_CALL1(offs, arg1) \ - __asm mov eax, arg1 \ + __asm mov eax, arg1 \ WRAP_WATCOM_CALL0(offs) #define WRAP_WATCOM_CALL2(offs, arg1, arg2) \ - __asm mov edx, arg2 \ + __asm mov edx, arg2 \ WRAP_WATCOM_CALL1(offs, arg1) #define WRAP_WATCOM_CALL3(offs, arg1, arg2, arg3) \ - __asm mov ebx, arg3 \ + __asm mov ebx, arg3 \ WRAP_WATCOM_CALL2(offs, arg1, arg2) #define WRAP_WATCOM_CALL4(offs, arg1, arg2, arg3, arg4) \ - __asm mov ecx, arg4 \ + __asm mov ecx, arg4 \ WRAP_WATCOM_CALL3(offs, arg1, arg2, arg3) #define WRAP_WATCOM_CALL5(offs, arg1, arg2, arg3, arg4, arg5) \ - __asm push arg5 \ + __asm push arg5 \ WRAP_WATCOM_CALL4(offs, arg1, arg2, arg3, arg4) #define WRAP_WATCOM_CALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) \ - __asm push arg6 \ + __asm push arg6 \ WRAP_WATCOM_CALL5(offs, arg1, arg2, arg3, arg4, arg5) #define WRAP_WATCOM_CALL7(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - __asm push arg7 \ + __asm push arg7 \ WRAP_WATCOM_CALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) // defines wrappers for __fastcall #define WRAP_WATCOM_FCALL1(offs, arg1) \ - __asm mov eax, ecx \ + __asm mov eax, ecx \ WRAP_WATCOM_CALL0(offs) #define WRAP_WATCOM_FCALL2(offs, arg1, arg2) \ WRAP_WATCOM_FCALL1(offs, arg1) #define WRAP_WATCOM_FCALL3(offs, arg1, arg2, arg3) \ - __asm mov ebx, arg3 \ + __asm mov ebx, arg3 \ WRAP_WATCOM_FCALL1(offs, arg1) #define WRAP_WATCOM_FCALL4(offs, arg1, arg2, arg3, arg4) \ - __asm mov eax, ecx \ - __asm mov ebx, arg3 \ - __asm mov ecx, arg4 \ + __asm mov eax, ecx \ + __asm mov ebx, arg3 \ + __asm mov ecx, arg4 \ WRAP_WATCOM_CALL0(offs) #define WRAP_WATCOM_FCALL5(offs, arg1, arg2, arg3, arg4, arg5) \ - __asm push arg5 \ + __asm push arg5 \ WRAP_WATCOM_FCALL4(offs, arg1, arg2, arg3, arg4) #define WRAP_WATCOM_FCALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) \ - __asm push arg6 \ + __asm push arg6 \ WRAP_WATCOM_FCALL5(offs, arg1, arg2, arg3, arg4, arg5) #define WRAP_WATCOM_FCALL7(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - __asm push arg7 \ + __asm push arg7 \ WRAP_WATCOM_FCALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) #define WRAP_WATCOM_FCALL8(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - __asm push arg8 \ + __asm push arg8 \ WRAP_WATCOM_FCALL7(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7) #define WRAP_WATCOM_FCALL9(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ - __asm push arg9 \ + __asm push arg9 \ WRAP_WATCOM_FCALL8(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + // prints message to debug.log file void __declspec(naked) debug_printf(const char* fmt, ...) { __asm jmp fo::funcoffs::debug_printf_; @@ -355,26 +356,21 @@ void __cdecl trans_buf_to_buf(BYTE* src, long width, long height, long src_width size_t s_pitch = src_width - width; size_t d_pitch = dst_width - width; - __asm { - mov esi, src; - mov edi, dst; - pxor mm3, mm3; - } + __asm mov esi, src; + __asm mov edi, dst; do { size_t count = blockCount; while (count--) { __asm { - movq mm0, qword ptr [esi]; // 8 bytes - movq mm1, qword ptr [edi]; - movq mm2, mm0; // src copy to mm2 - pcmpeqb mm2, mm3; // mm2 = (src == 0) ? 1 : 0; - lea esi, [esi + 8]; - movq mm4, mm2; - pandn mm2, mm0; // mm2 = mm2 AND (NOT mm0) - pand mm4, mm1; - por mm2, mm4; - movq qword ptr [edi], mm2; - lea edi, [edi + 8]; + pxor mm2, mm2; + movq mm0, qword ptr [esi]; // 8 bytes + movq mm1, qword ptr [edi]; + pcmpeqb mm2, mm0; // mm2 = (src == 0) ? 1 : 0; + lea esi, [esi + 8]; + pand mm2, mm1; + por mm0, mm2; + movq qword ptr [edi], mm0; // src or dst + lea edi, [edi + 8]; } } size_t bytes = lastBytes; @@ -389,10 +385,8 @@ void __cdecl trans_buf_to_buf(BYTE* src, long width, long height, long src_width lea edi, [edi + 1]; } } - __asm { - add esi, s_pitch; - add edi, d_pitch; - } + __asm add esi, s_pitch; + __asm add edi, d_pitch; } while (--height); __asm emms; } diff --git a/sfall/FalloutEngine/Functions_def.h b/sfall/FalloutEngine/Functions_def.h index b7a787be..db3848da 100644 --- a/sfall/FalloutEngine/Functions_def.h +++ b/sfall/FalloutEngine/Functions_def.h @@ -47,9 +47,9 @@ WRAP_WATCOM_FFUNC4(long, register_object_run_to_object, GameObject*, source, Gam WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value) WRAP_WATCOM_FFUNC3(long, scr_set_local_var, long, sid, long, varId, long, value) WRAP_WATCOM_FFUNC3(long, tile_num_in_direction, long, tile, long, rotation,long, distance) -WRAP_WATCOM_FFUNC8(void, trans_cscale, void*, fromBuff, long, width, long, height, long, pitch, void*, toBuff, long, toWidth, long, toHeight, long, toPitch) +WRAP_WATCOM_FFUNC8(void, trans_cscale, void*, fromBuff, long, width, long, height, long, fromPitch, void*, toBuff, long, toWidth, long, toHeight, long, toPitch) WRAP_WATCOM_FFUNC3(void, win_clip, Window*, window, RectList**, rects, void*, buffer) -WRAP_WATCOM_FFUNC9(long, windowWrapLineWithSpacing, long, winID, const char*, text, long, width, long, height, long, x, long, y, long, color, long, alignment, long, unknown) +WRAP_WATCOM_FFUNC9(long, windowWrapLineWithSpacing, long, winID, const char*, text, long, width, long, height, long, x, long, y, long, color, long, alignment, long, lineSpacing) WRAP_WATCOM_FFUNC3(const char*, interpretGetString, Program*, scriptPtr, DWORD, dataType, DWORD, strId)