I use the combined ReShade / SweetFX 2.0 setup, but it probably works in newer versions too.
- Create a new shader file in the shaders folder; for my example, this is "GameFolder/SweetFX/Shaders/Invert.h"
- In "GameFolder/SweetFX/SweetFX_settings.txt" add something like "#define USE_INVERT 1" in the choose effects section
- (Optional) Add a useful comment to it explaining what the shader does
- In "GameFolder/SweetFX/Shaders/Main.h" add the following:
#if (USE_INVERT == 1)
#include "SweetFX\Shaders\Invert.h"
#endif
#if (USE_INVERT == 1)
texture invertedTex < pooled = true; >
{
Width = 1920;
Height = 1080;
Format = RGBA8;
};
sampler inversionSampler
{
Texture = invertedTex;
AddressU = Clamp; AddressV = Clamp;
MipFilter = Linear; MinFilter = Linear; MagFilter = Linear;
SRGBTexture = false;
};
float4 p0PS(float4 position : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target
{
return float4(1.0, 1.0, 1.0, 0.0) - tex2D(s0, texcoord);
}
float4 p1PS(float4 position : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target
{
return tex2D(inversionSampler, texcoord) * float4(1.0, 0.0, 0.0, 1.0);
}
technique MultiPassInvert
{
pass p0
{
VertexShader = FullscreenTriangle;
PixelShader = p0PS;
RenderTarget = invertedTex;
}
pass p1
{
VertexShader = FullscreenTriangle;
PixelShader = p1PS;
}
}
#endif
Test it's worked by running the game!
I'll try to explain what's going on here... "technique" acts as the main entry point of the shader, kind of. It defines how the shader should operate. A technique must contain at least one "pass". A pass can contain a lot of information, see here: https://github.com/lordbean-git/HQAA/blob/main/HQAA.fx for an example, but for our purposes, we only need a Vertex Shader, a Pixel Shader, and a Render Target. The render target is the texture we are going to write the output of our pixel shader to. We define it at the top. Once our first pass has finished, there is information in that texture, so there is something there for us to sample when we sample it in our second pass. We could use the inversionSampler in the first pass, but it wouldn't give us anything useful since the texture it samples from would be uninitialised.
Something to note, I think the Vertex Shader "FullscreenTriangle" got replaced in later versions by "PostProcessVS".
Instead of hard-coding Width and Height, if you want them to match the window's resolution, you should use "BUFFER_WIDTH" and "BUFFER_HEIGHT" (without quotes).
âTo be quite honest, I'm surprised it worked. Here's what the shader does to Need For Speed: Underground 2: