mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
+3
-1
@@ -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(); }
|
||||
}
|
||||
@@ -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_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user