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)
;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
;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
@@ -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) {
__asm {
push buttonType
push arg12
push pictureDown
push pictureUp
push buttonUp
push buttonDown
push hoverOff
push hoverOn
push height
mov ecx, width
mov ebx, yPos
mov edx, xPos
mov eax, winRef
call fo::funcoffs::win_register_button_
push buttonType;
push arg12;
push pictureDown;
push pictureUp;
push buttonUp;
push buttonDown;
push hoverOff;
push hoverOn;
push height;
mov ecx, width;
mov ebx, yPos;
mov edx, xPos;
mov eax, winRef;
call fo::funcoffs::win_register_button_;
}
}
+4 -5
View File
@@ -50,7 +50,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;
@@ -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
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) {
D3DLOCKED_RECT rect;
@@ -912,8 +912,7 @@ public:
}
};
class FakeDirectDraw : IDirectDraw
{
class FakeDirectDraw : IDirectDraw {
private:
ULONG Refs;
public:
@@ -1154,7 +1153,7 @@ void Graphics::init() {
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);
}
+22 -7
View File
@@ -30,9 +30,16 @@ namespace sfall
#define SAFERELEASE(a) { if (a) { a->Release(); a = nullptr; } }
static size_t shadersSize;
static bool globalShadersActive = false;
static bool globalShaderActive = false;
struct GlobalShader {
std::string gShaderFile;
bool badShader = false;
GlobalShader(std::string file) {
gShaderFile = std::move(file);
}
};
struct sShader {
ID3DXEffect* Effect;
@@ -44,6 +51,7 @@ struct sShader {
sShader() : Effect(0), ehTicks(0), mode(0), mode2(0), Active(false) {}
};
static std::vector<GlobalShader> gShaderFiles;
static std::vector<sShader> shaders;
static std::vector<IDirect3DTexture9*> shaderTextures;
@@ -98,13 +106,18 @@ int __stdcall LoadShader(const char* file) {
}
void ScriptShaders::LoadGlobalShader() {
if (!globalShaderActive) return;
long index = LoadShader(gShaderFile.c_str());
if (!globalShadersActive) return;
for (auto &shader : gShaderFiles) {
if (shader.badShader) continue;
long index = LoadShader(shader.gShaderFile.c_str());
if (index != -1) {
shaders[index].Effect->SetInt("w", Graphics::GetGameWidthRes());
shaders[index].Effect->SetInt("h", Graphics::GetGameHeightRes());
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() {
globalShaderActive = false;
globalShadersActive = false;
ResetShaders();
for (DWORD d = 0; d < shaderTextures.size(); d++) shaderTextures[d]->Release();
shaderTextures.clear();
@@ -207,8 +220,10 @@ void ScriptShaders::Release() {
void ScriptShaders::init() {
if (Graphics::mode) {
gShaderFile = GetConfigString("Graphics", "GlobalShaderFile", "", MAX_PATH);
globalShaderActive = (gShaderFile.length() > 3);
for each (const auto& shaderFile in GetConfigList("Graphics", "GlobalShaderFile", "", 1024)) {
if (shaderFile.length() > 3) gShaderFiles.push_back(GlobalShader(shaderFile));
}
globalShadersActive = !gShaderFiles.empty();
LoadGameHook::OnGameReset() += ResetShaders;
}