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.
This commit is contained in:
NovaRain
2020-09-21 12:54:42 +08:00
parent bf9deabded
commit 0dd8ea5335
5 changed files with 161 additions and 32 deletions
+3 -1
View File
@@ -69,10 +69,12 @@ WindowData=0
;Uncomment the option to use a hardware shader (requires DX9 graphics mode) ;Uncomment the option to use a hardware shader (requires DX9 graphics mode)
;The shader file <name>.fx must be placed in <GameRoot>\<master_patches>\shaders\ and must contain one technique with one or more passes ;The shader file <name>.fx must be placed in <GameRoot>\<master_patches>\shaders\ and must contain one technique with one or more passes
;You can specify multiple shader files, separated by commas
;GlobalShaderFile=global.fx ;GlobalShaderFile=global.fx
;Set to 1 to enable linear texture filtering ;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 1 to do the palette conversion on the GPU
;Set to 2 to do the palette conversion on the CPU ;Set to 2 to do the palette conversion on the CPU
@@ -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(); }
}
+14 -14
View File
@@ -162,20 +162,20 @@ GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWOR
long __stdcall win_register_button(DWORD winRef, long xPos, long yPos, long width, long height, long hoverOn, long hoverOff, long buttonDown, long buttonUp, BYTE* pictureUp, BYTE* pictureDown, long arg12, long buttonType) { long __stdcall win_register_button(DWORD winRef, long xPos, long yPos, long width, long height, long hoverOn, long hoverOff, long buttonDown, long buttonUp, BYTE* pictureUp, BYTE* pictureDown, long arg12, long buttonType) {
__asm { __asm {
push buttonType push buttonType;
push arg12 push arg12;
push pictureDown push pictureDown;
push pictureUp push pictureUp;
push buttonUp push buttonUp;
push buttonDown push buttonDown;
push hoverOff push hoverOff;
push hoverOn push hoverOn;
push height push height;
mov ecx, width mov ecx, width;
mov ebx, yPos mov ebx, yPos;
mov edx, xPos mov edx, xPos;
mov eax, winRef mov eax, winRef;
call fo::funcoffs::win_register_button_ call fo::funcoffs::win_register_button_;
} }
} }
+4 -5
View File
@@ -50,7 +50,7 @@ static DWORD yoffset;
static bool DeviceLost = false; static bool DeviceLost = false;
static bool mainTexLock = false; static bool mainTexLock = false;
static bool textureFilter = false; static bool textureFilter = true;
static DDSURFACEDESC surfaceDesc; static DDSURFACEDESC surfaceDesc;
static DDSURFACEDESC mveDesc; static DDSURFACEDESC mveDesc;
@@ -886,7 +886,7 @@ public:
HRESULT __stdcall SetEntries(DWORD a, DWORD b, DWORD c, LPPALETTEENTRY destPal) { // used to set palette for splash screen, fades, subtitles HRESULT __stdcall SetEntries(DWORD a, DWORD b, DWORD c, LPPALETTEENTRY destPal) { // used to set palette for splash screen, fades, subtitles
if (!windowInit || c == 0 || b + c > 256) return DDERR_INVALIDPARAMS; if (!windowInit || c == 0 || b + c > 256) return DDERR_INVALIDPARAMS;
__movsd(&palette[b], (unsigned long*)destPal, c); //CopyMemory(&palette[b], destPal, c * 4); __movsd(&palette[b], (unsigned long*)destPal, c);
if (Graphics::GPUBlt && gpuPalette) { if (Graphics::GPUBlt && gpuPalette) {
D3DLOCKED_RECT rect; D3DLOCKED_RECT rect;
@@ -912,8 +912,7 @@ public:
} }
}; };
class FakeDirectDraw : IDirectDraw class FakeDirectDraw : IDirectDraw {
{
private: private:
ULONG Refs; ULONG Refs;
public: public:
@@ -1154,7 +1153,7 @@ void Graphics::init() {
SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2 SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2
HookCall(0x44260C, game_init_hook); HookCall(0x44260C, game_init_hook);
textureFilter = (GetConfigInt("Graphics", "TextureFilter", 0) != 0); textureFilter = (GetConfigInt("Graphics", "TextureFilter", 1) != 0);
dlogr(" Done", DL_INIT); dlogr(" Done", DL_INIT);
} }
+22 -7
View File
@@ -30,9 +30,16 @@ namespace sfall
#define SAFERELEASE(a) { if (a) { a->Release(); a = nullptr; } } #define SAFERELEASE(a) { if (a) { a->Release(); a = nullptr; } }
static size_t shadersSize; static size_t shadersSize;
static bool globalShadersActive = false;
static bool globalShaderActive = false; struct GlobalShader {
std::string gShaderFile; std::string gShaderFile;
bool badShader = false;
GlobalShader(std::string file) {
gShaderFile = std::move(file);
}
};
struct sShader { struct sShader {
ID3DXEffect* Effect; ID3DXEffect* Effect;
@@ -44,6 +51,7 @@ struct sShader {
sShader() : Effect(0), ehTicks(0), mode(0), mode2(0), Active(false) {} sShader() : Effect(0), ehTicks(0), mode(0), mode2(0), Active(false) {}
}; };
static std::vector<GlobalShader> gShaderFiles;
static std::vector<sShader> shaders; static std::vector<sShader> shaders;
static std::vector<IDirect3DTexture9*> shaderTextures; static std::vector<IDirect3DTexture9*> shaderTextures;
@@ -98,13 +106,18 @@ int __stdcall LoadShader(const char* file) {
} }
void ScriptShaders::LoadGlobalShader() { void ScriptShaders::LoadGlobalShader() {
if (!globalShaderActive) return; if (!globalShadersActive) return;
long index = LoadShader(gShaderFile.c_str()); for (auto &shader : gShaderFiles) {
if (shader.badShader) continue;
long index = LoadShader(shader.gShaderFile.c_str());
if (index != -1) { if (index != -1) {
shaders[index].Effect->SetInt("w", Graphics::GetGameWidthRes()); shaders[index].Effect->SetInt("w", Graphics::GetGameWidthRes());
shaders[index].Effect->SetInt("h", Graphics::GetGameHeightRes()); shaders[index].Effect->SetInt("h", Graphics::GetGameHeightRes());
shaders[index].Active = true; shaders[index].Active = true;
dlogr("Global shader file loaded.", DL_INIT); dlog_f("Global shader file %s is loaded.\n", DL_INIT, shader.gShaderFile.c_str());
} else {
shader.badShader = true;
}
} }
} }
@@ -199,7 +212,7 @@ void ScriptShaders::OnLostDevice() {
} }
void ScriptShaders::Release() { void ScriptShaders::Release() {
globalShaderActive = false; globalShadersActive = false;
ResetShaders(); ResetShaders();
for (DWORD d = 0; d < shaderTextures.size(); d++) shaderTextures[d]->Release(); for (DWORD d = 0; d < shaderTextures.size(); d++) shaderTextures[d]->Release();
shaderTextures.clear(); shaderTextures.clear();
@@ -207,8 +220,10 @@ void ScriptShaders::Release() {
void ScriptShaders::init() { void ScriptShaders::init() {
if (Graphics::mode) { if (Graphics::mode) {
gShaderFile = GetConfigString("Graphics", "GlobalShaderFile", "", MAX_PATH); for each (const auto& shaderFile in GetConfigList("Graphics", "GlobalShaderFile", "", 1024)) {
globalShaderActive = (gShaderFile.length() > 3); if (shaderFile.length() > 3) gShaderFiles.push_back(GlobalShader(shaderFile));
}
globalShadersActive = !gShaderFiles.empty();
LoadGameHook::OnGameReset() += ResetShaders; LoadGameHook::OnGameReset() += ResetShaders;
} }