mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added a sharpen filter file as a global shader example. Set TextureFilter to be enabled by default.
233 lines
6.8 KiB
C++
233 lines
6.8 KiB
C++
/*
|
|
* sfall
|
|
* Copyright (C) 2008-2019 The sfall team
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "..\main.h"
|
|
#include "..\FalloutEngine\Fallout2.h"
|
|
|
|
#include "Graphics.h"
|
|
#include "LoadGameHook.h"
|
|
|
|
#include "ScriptShaders.h"
|
|
|
|
namespace sfall
|
|
{
|
|
|
|
#define SAFERELEASE(a) { if (a) { a->Release(); a = nullptr; } }
|
|
|
|
static size_t shadersSize;
|
|
static bool globalShadersActive = false;
|
|
|
|
struct GlobalShader {
|
|
std::string gShaderFile;
|
|
bool badShader = false;
|
|
|
|
GlobalShader(std::string file) {
|
|
gShaderFile = std::move(file);
|
|
}
|
|
};
|
|
|
|
struct sShader {
|
|
ID3DXEffect* Effect;
|
|
D3DXHANDLE ehTicks;
|
|
DWORD mode;
|
|
DWORD mode2;
|
|
bool Active;
|
|
|
|
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;
|
|
|
|
size_t ScriptShaders::Count() {
|
|
return shadersSize;
|
|
}
|
|
|
|
void __stdcall SetShaderMode(DWORD d, DWORD mode) {
|
|
if (d >= shadersSize || !shaders[d].Effect) return;
|
|
if (mode & 0x80000000) {
|
|
shaders[d].mode2 = mode ^ 0x80000000;
|
|
} else {
|
|
shaders[d].mode = mode;
|
|
}
|
|
}
|
|
|
|
int __stdcall LoadShader(const char* file) {
|
|
if (!Graphics::mode || strstr(file, "..") || strstr(file, ":")) return -1;
|
|
char buf[MAX_PATH];
|
|
sprintf_s(buf, "%s\\shaders\\%s", fo::var::master_db_handle->path, file); // fo::var::patches
|
|
for (DWORD d = 0; d < shadersSize; d++) {
|
|
if (!shaders[d].Effect) {
|
|
if (FAILED(D3DXCreateEffectFromFile(d3d9Device, buf, 0, 0, 0, 0, &shaders[d].Effect, 0))) {
|
|
return -1;
|
|
} else {
|
|
return d;
|
|
}
|
|
}
|
|
}
|
|
sShader shader = sShader();
|
|
if (FAILED(D3DXCreateEffectFromFile(d3d9Device, buf, 0, 0, 0, 0, &shader.Effect, 0))) return -1;
|
|
|
|
shader.Effect->SetFloatArray("rcpres", Graphics::rcpresGet(), 2);
|
|
|
|
for (int i = 1; i < 128; i++) {
|
|
const char* name;
|
|
IDirect3DTexture9* tex;
|
|
|
|
sprintf(buf, "texname%d", i);
|
|
if (FAILED(shader.Effect->GetString(buf, &name))) break;
|
|
sprintf_s(buf, "%s\\art\\stex\\%s", fo::var::master_db_handle->path, name); // fo::var::patches
|
|
if (FAILED(D3DXCreateTextureFromFileA(d3d9Device, buf, &tex))) continue;
|
|
sprintf(buf, "tex%d", i);
|
|
shader.Effect->SetTexture(buf, tex);
|
|
shaderTextures.push_back(tex);
|
|
}
|
|
|
|
shader.ehTicks = shader.Effect->GetParameterByName(0, "tickcount");
|
|
shaders.push_back(shader);
|
|
shadersSize = shaders.size();
|
|
return shadersSize - 1;
|
|
}
|
|
|
|
void ScriptShaders::LoadGlobalShader() {
|
|
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;
|
|
dlog_f("Global shader file %s is loaded.\n", DL_INIT, shader.gShaderFile.c_str());
|
|
} else {
|
|
shader.badShader = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void __stdcall ActivateShader(DWORD d) {
|
|
if (d < shadersSize && shaders[d].Effect) shaders[d].Active = true;
|
|
}
|
|
|
|
void __stdcall DeactivateShader(DWORD d) {
|
|
if (d < shadersSize) shaders[d].Active = false;
|
|
}
|
|
|
|
int __stdcall GetShaderTexture(DWORD d, DWORD id) {
|
|
if (id < 1 || id > 128 || d >= shadersSize || !shaders[d].Effect) return -1;
|
|
IDirect3DBaseTexture9* tex = 0;
|
|
char buf[8] = "tex";
|
|
_itoa_s(id, &buf[3], 4, 10);
|
|
if (FAILED(shaders[d].Effect->GetTexture(buf, &tex)) || !tex) return -1;
|
|
tex->Release();
|
|
for (DWORD i = 0; i < shaderTextures.size(); i++) {
|
|
if (shaderTextures[i] == tex) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void __stdcall FreeShader(DWORD d) {
|
|
if (d < shadersSize) {
|
|
SAFERELEASE(shaders[d].Effect);
|
|
shaders[d].Active = false;
|
|
}
|
|
}
|
|
|
|
void __stdcall SetShaderInt(DWORD d, const char* param, int value) {
|
|
if (d >= shadersSize || !shaders[d].Effect) return;
|
|
shaders[d].Effect->SetInt(param, value);
|
|
}
|
|
|
|
void __stdcall SetShaderFloat(DWORD d, const char* param, float value) {
|
|
if (d >= shadersSize || !shaders[d].Effect) return;
|
|
shaders[d].Effect->SetFloat(param, value);
|
|
}
|
|
|
|
void __stdcall SetShaderVector(DWORD d, const char* param, float f1, float f2, float f3, float f4) {
|
|
if (d >= shadersSize || !shaders[d].Effect) return;
|
|
shaders[d].Effect->SetFloatArray(param, &f1, 4);
|
|
}
|
|
|
|
void __stdcall SetShaderTexture(DWORD d, const char* param, DWORD value) {
|
|
if (d >= shadersSize || !shaders[d].Effect || value >= shaderTextures.size()) return;
|
|
shaders[d].Effect->SetTexture(param, shaderTextures[value]);
|
|
}
|
|
|
|
static void ResetShaders() {
|
|
for (DWORD d = 0; d < shadersSize; d++) SAFERELEASE(shaders[d].Effect);
|
|
shaders.clear();
|
|
shadersSize = 0;
|
|
ScriptShaders::LoadGlobalShader();
|
|
}
|
|
|
|
void ScriptShaders::Refresh(IDirect3DSurface9* sSurf1, IDirect3DSurface9* sSurf2, IDirect3DTexture9* sTex2) {
|
|
for (int i = shadersSize - 1; i >= 0; i--) {
|
|
if (!shaders[i].Effect || !shaders[i].Active) continue;
|
|
if (shaders[i].mode2 && !(shaders[i].mode2 & GetLoopFlags())) continue;
|
|
if (shaders[i].mode & GetLoopFlags()) continue;
|
|
|
|
if (shaders[i].ehTicks) shaders[i].Effect->SetInt(shaders[i].ehTicks, GetTickCount());
|
|
|
|
UINT passes;
|
|
shaders[i].Effect->Begin(&passes, 0);
|
|
for (DWORD pass = 0; pass < passes; pass++) {
|
|
shaders[i].Effect->BeginPass(pass);
|
|
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
|
shaders[i].Effect->EndPass();
|
|
|
|
d3d9Device->StretchRect(sSurf1, 0, sSurf2, 0, D3DTEXF_NONE); // copy sSurf1 to sSurf2
|
|
d3d9Device->SetTexture(0, sTex2);
|
|
}
|
|
shaders[i].Effect->End();
|
|
d3d9Device->SetTexture(0, sTex2);
|
|
}
|
|
}
|
|
|
|
void ScriptShaders::OnResetDevice() {
|
|
for (DWORD d = 0; d < shadersSize; d++) {
|
|
if (shaders[d].Effect) shaders[d].Effect->OnResetDevice();
|
|
}
|
|
}
|
|
|
|
void ScriptShaders::OnLostDevice() {
|
|
for (DWORD d = 0; d < shadersSize; d++) {
|
|
if (shaders[d].Effect) shaders[d].Effect->OnLostDevice();
|
|
}
|
|
}
|
|
|
|
void ScriptShaders::Release() {
|
|
globalShadersActive = false;
|
|
ResetShaders();
|
|
for (DWORD d = 0; d < shaderTextures.size(); d++) shaderTextures[d]->Release();
|
|
shaderTextures.clear();
|
|
}
|
|
|
|
void ScriptShaders::init() {
|
|
if (Graphics::mode) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|