From 90a9ee5f15db7eb2dd4d436b06209a365062137b Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 21 Sep 2020 13:03:05 +0800 Subject: [PATCH] Added loading multiple shader files for GlobalShaderFile option Added a sharpen filter file as a global shader example. Set TextureFilter to be enabled by default. --- artifacts/ddraw.ini | 4 +- .../example_mods/GlobalShaders/sharpen.fx | 113 ++++++++++++++++++ sfall/Graphics.cpp | 63 ++++++---- 3 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 artifacts/example_mods/GlobalShaders/sharpen.fx diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 76095ce6..9988e0c4 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -53,10 +53,12 @@ WindowData=0 ;Uncomment the option to use a hardware shader (requires DX9 graphics mode) ;The shader file .fx must be placed in \\shaders\ and must contain one technique with one or more passes +;You can specify multiple shader files, separated by commas ;GlobalShaderFile=global.fx ;Set to 1 to enable linear texture filtering -TextureFilter=0 +;This can be used in conjunction with GlobalShaderFile +TextureFilter=1 ;Set to 1 to do the palette conversion on the GPU ;Set to 2 to do the palette conversion on the CPU diff --git a/artifacts/example_mods/GlobalShaders/sharpen.fx b/artifacts/example_mods/GlobalShaders/sharpen.fx new file mode 100644 index 00000000..89e59532 --- /dev/null +++ b/artifacts/example_mods/GlobalShaders/sharpen.fx @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////// +// Sharpen filter setting +// +// min: Sharpen 0.5, EdgeSharpen 1.0 +// mid: Sharpen 1.0, EdgeSharpen -0.25 +// max: Sharpen 1.75, EdgeSharpen -0.5 (1.5, -0.25) +/////////////////////////////////////////////////////////////////////////////// +#define Sharpen 0.5 +#define EdgeSharpen 1.5 + + +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; + +static const float CoefBlur = (Sharpen * 0.5); +static const float CoefOrig = (1 + CoefBlur); + +// for the sharpen edge +#define SharpenEdge 0.4 +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); + +// for the blur filter +#define mean 1.0 +static const float dx = (mean * px); +static const float dy = (mean * py); + +float4 SharpenComplexPS(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 +{ + float4 c0 = tex2D(s0, texCoord); // get original pixel + + // edge detection + // Get neighbor points + // [ c1, c2, c3 ] + // [ c4, c0, c5 ] + // [ c6, c7, c8 ] + float4 c1 = tex2D(s0, texCoord + float2(-px, -py)); + float4 c2 = tex2D(s0, texCoord + float2( 0, -py)); + float4 c3 = tex2D(s0, texCoord + float2( px, -py)); + float4 c4 = tex2D(s0, texCoord + float2(-px, 0)); + float4 c5 = tex2D(s0, texCoord + float2( px, 0)); + float4 c6 = tex2D(s0, texCoord + float2(-px, py)); + float4 c7 = tex2D(s0, texCoord + float2( 0, py)); + float4 c8 = tex2D(s0, texCoord + float2( px, py)); + + // using Sobel filter + // horizontal gradient + // [ -1, 0, 1 ] + // [ -2, 0, 2 ] + // [ -1, 0, 1 ] + float delta1 = (c3 + 2 * c5 + c8) - (c1 + 2 * c4 + c6); + + // vertical gradient + // [ -1, - 2, -1 ] + // [ 0, 0, 0 ] + // [ 1, 2, 1 ] + float4 c13 = c1 + c3; + float4 c68 = c6 + c8; + float delta2 = (c68 + 2 * c7) - (c13 + 2 * c2); + + // computation + if (sqrt(mul(delta1, delta1) + mul(delta2, delta2)) > SharpenEdge) { + // if we have an edge, use sharpen + return c0 * sharpenVal0 - (c13 + c2 + c4 + c5 + c68 + c7) * sharpenVal1; + + // Display edges in red... + //return float4( 1.0, 0.0, 0.0, 0.0 ); + } else { + // else return corrected image + + // compute blurred image (gaussian filter) + c1 = tex2D(s0, texCoord + float2(-dx, -dy)); + c2 = tex2D(s0, texCoord + float2( 0, -dy)); + c3 = tex2D(s0, texCoord + float2( dx, -dy)); + c4 = tex2D(s0, texCoord + float2(-dx, 0)); + c5 = tex2D(s0, texCoord + float2( dx, 0)); + c6 = tex2D(s0, texCoord + float2(-dx, dy)); + c7 = tex2D(s0, texCoord + float2( 0, dy)); + c8 = tex2D(s0, texCoord + float2( dx, dy)); + + // gaussian filter + // [ 1, 2, 1 ] + // [ 2, 4, 2 ] + // [ 1, 2, 1 ] + // to normalize the values, we need to divide by the coeff sum + float4 flou = (c1 + c3 + c6 + c8 + 2 * (c2 + c4 + c5 + c7) + 4 * c0) * 0.0625; // 1 / (1+2+1+2+4+2+1+2+1) = 1 / 16 = 0.0625 + + // substract blurred image from original image + return (CoefOrig * c0 - CoefBlur * flou); + } +} + +technique SharpenT +{ + pass P0 { PixelShader = compile ps_2_0 SharpenComplexPS(); } +} diff --git a/sfall/Graphics.cpp b/sfall/Graphics.cpp index f3592f3b..1cb0e4d7 100644 --- a/sfall/Graphics.cpp +++ b/sfall/Graphics.cpp @@ -46,7 +46,7 @@ static DWORD yoffset; static bool DeviceLost = false; static bool mainTexLock = false; -static bool textureFilter = false; +static bool textureFilter = true; static DDSURFACEDESC surfaceDesc; static DDSURFACEDESC mveDesc; @@ -136,9 +136,17 @@ static D3DXHANDLE gpuBltHeadCorner; static float rcpres[2]; static size_t shadersSize; +static bool globalShadersActive = false; -static bool globalShaderActive = false; -std::string gShaderFile; +struct sGlobalShader { + std::string gShaderFile; + bool badShader; + + sGlobalShader(std::string file) { + gShaderFile = std::move(file); + badShader = false; + } +}; struct sShader { ID3DXEffect* Effect; @@ -150,6 +158,7 @@ struct sShader { sShader() : Effect(0), ehTicks(0), mode(0), mode2(0), Active(false) {} }; +static std::vector gShaderFiles; static std::vector shaders; static std::vector shaderTextures; @@ -239,13 +248,18 @@ int __stdcall LoadShader(const char* file) { } static void LoadGlobalShader() { - if (!globalShaderActive) return; - long index = LoadShader(gShaderFile.c_str()); - if (index != -1) { - shaders[index].Effect->SetInt("w", Gfx_GetGameWidthRes()); - shaders[index].Effect->SetInt("h", Gfx_GetGameHeightRes()); - shaders[index].Active = true; - dlogr("Global shader file loaded.", DL_INIT); + if (!globalShadersActive) return; + for (std::vector::iterator it = gShaderFiles.begin(); it != gShaderFiles.end(); ++it) { + if (it->badShader) continue; + long index = LoadShader(it->gShaderFile.c_str()); + if (index != -1) { + shaders[index].Effect->SetInt("w", Gfx_GetGameWidthRes()); + shaders[index].Effect->SetInt("h", Gfx_GetGameHeightRes()); + shaders[index].Active = true; + dlog_f("Global shader file %s is loaded.\n", DL_INIT, it->gShaderFile.c_str()); + } else { + it->badShader = true; + } } } @@ -551,7 +565,7 @@ static void Refresh() { d3d9Device->SetRenderTarget(0, backBuffer); if (!textureFilter && !shadersSize && GPUBlt) { - gpuBltEffect->Begin(&unused, 0); + gpuBltEffect->Begin(&passes, 0); gpuBltEffect->BeginPass(0); } d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); @@ -708,13 +722,6 @@ void Gfx_SetDefaultTechnique() { gpuBltEffect->SetTechnique("T0"); } -void Graphics_OnGameLoad() { // ResetShaders - for (DWORD d = 0; d < shadersSize; d++) SAFERELEASE(shaders[d].Effect); - shaders.clear(); - shadersSize = 0; - LoadGlobalShader(); -} - class FakeDirectDrawSurface : IDirectDrawSurface { private: ULONG Refs; @@ -1030,8 +1037,7 @@ public: } }; -class FakeDirectDraw : IDirectDraw -{ +class FakeDirectDraw : IDirectDraw { private: ULONG Refs; public: @@ -1047,7 +1053,7 @@ public: ULONG __stdcall Release() { // called from game on exit if (!--Refs) { - globalShaderActive = false; + globalShadersActive = false; Graphics_OnGameLoad(); for (DWORD d = 0; d < shaderTextures.size(); d++) shaderTextures[d]->Release(); shaderTextures.clear(); @@ -1252,6 +1258,13 @@ static __declspec(naked) void palette_fade_to_hook() { } } +void Graphics_OnGameLoad() { // ResetShaders + for (DWORD d = 0; d < shadersSize; d++) SAFERELEASE(shaders[d].Effect); + shaders.clear(); + shadersSize = 0; + LoadGlobalShader(); +} + void GraphicsInit() { GraphicsMode = GetConfigInt("Graphics", "Mode", 0); if (GraphicsMode == 6) { @@ -1279,11 +1292,13 @@ void GraphicsInit() { SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2 HookCall(0x44260C, game_init_hook); - textureFilter = (GetConfigInt("Graphics", "TextureFilter", 0) != 0); + textureFilter = (GetConfigInt("Graphics", "TextureFilter", 1) != 0); dlogr(" Done", DL_INIT); - gShaderFile = GetConfigString("Graphics", "GlobalShaderFile", "", MAX_PATH); - globalShaderActive = (gShaderFile.length() > 3); + for each (const std::string& shaderFile in GetConfigList("Graphics", "GlobalShaderFile", "", 1024)) { + if (shaderFile.length() > 3) gShaderFiles.push_back(sGlobalShader(shaderFile)); + } + globalShadersActive = !gShaderFiles.empty(); } fadeMulti = GetConfigInt("Graphics", "FadeMultiplier", 100);