Added shaders

This commit is contained in:
Boria138
2023-09-23 14:39:09 +06:00
parent 08a3b09c2f
commit 3e1ab5ddd3
120 changed files with 36866 additions and 9 deletions

View File

@ -0,0 +1,88 @@
[DEPTH]
DepthCopyAtClearIndex=0
DepthCopyBeforeClears=0
UseAspectRatioHeuristics=1
[GENERAL]
EffectSearchPaths=Z:\home\barry\.local\share\reshade\ReShade_shaders\Merged\Shaders
IntermediateCachePath=C:\users\steamuser\Temp
NoDebugInfo=1
NoEffectCache=0
NoReloadOnInit=0
NoReloadOnInitForNonVR=0
PerformanceMode=0
PreprocessorDefinitions=
PresetPath=.\.\ReShadePreset.ini
PresetShortcutKeys=
PresetShortcutPaths=
PresetTransitionDelay=1000
PresetTransitionDuration=1000
SkipLoadingDisabledEffects=0
StartupPresetPath=
TextureSearchPaths=Z:\home\barry\.local\share\reshade\ReShade_shaders\Merged\Textures
[INPUT]
ForceShortcutModifiers=1
InputProcessing=2
KeyEffects=0,0,0,0
KeyNextPreset=0,0,0,0
KeyOverlay=36,0,0,0
KeyPerformanceMode=0,0,0,0
KeyPreviousPreset=0,0,0,0
KeyReload=0,0,0,0
KeyScreenshot=44,0,0,0
[OVERLAY]
AutoSavePreset=1
ClockFormat=0
Docking=[Docking][Data],DockSpace ID=0x7E010B79 Window=0x995B0CF8 Pos=8,,8 Size=1904,,1064 Split=X, DockNode ID=0x00000001 Parent=0x7E010B79 SizeRef=671,,1080 Selected=0xAF9E06C0, DockNode ID=0x00000002 Parent=0x7E010B79 SizeRef=1247,,1080 CentralNode=1
FPSPosition=1
NoFontScaling=1
SaveWindowState=0
ShowClock=0
ShowForceLoadEffectsButton=1
ShowFPS=0
ShowFrameTime=0
ShowPresetTransitionMessage=1
ShowScreenshotMessage=1
TutorialProgress=4
VariableListHeight=300.000000
VariableListUseTabs=0
Window=[Window][Home],Pos=8,,8,Size=671,,1064,Collapsed=0,DockId=0x00000001,,0,[Window][Add-ons],Pos=8,,8,Size=671,,1064,Collapsed=0,DockId=0x00000001,,1,[Window][Settings],Pos=8,,8,Size=671,,1064,Collapsed=0,DockId=0x00000001,,2,[Window][Statistics],Pos=8,,8,Size=671,,1064,Collapsed=0,DockId=0x00000001,,3,[Window][Log],Pos=8,,8,Size=671,,1064,Collapsed=0,DockId=0x00000001,,4,[Window][About],Pos=8,,8,Size=671,,1064,Collapsed=0,DockId=0x00000001,,5,[Window][###editor],Collapsed=0,DockId=0x00000002,[Window][Viewport],Pos=0,,0,Size=1920,,1080,Collapsed=0,[Window][Debug##Default],Pos=60,,60,Size=400,,400,Collapsed=0
[SCREENSHOT]
ClearAlpha=1
FileFormat=1
FileNaming=%AppName% %Date% %Time%
FileNamingFormat=0
JPEGQuality=90
PostSaveCommand=
PostSaveCommandArguments="%TargetPath%"
PostSaveCommandNoWindow=0
PostSaveCommandWorkingDirectory=.\
SaveBeforeShot=0
SaveOverlayShot=0
SavePath=
SavePresetFile=0
SoundPath=
[STYLE]
Alpha=1.000000
ChildRounding=0.000000
ColFPSText=1.000000,1.000000,0.784314,1.000000
EditorFont=
EditorFontSize=13
EditorStyleIndex=0
Font=
FontSize=13
FPSScale=1.000000
FrameRounding=0.000000
GrabRounding=0.000000
HdrOverlayBrightness=203.000000
HdrOverlayOverwriteColorSpaceTo=0
PopupRounding=0.000000
ScrollbarRounding=0.000000
StyleIndex=2
TabRounding=4.000000
WindowRounding=0.000000

Binary file not shown.

View File

@ -0,0 +1,21 @@
{
"file_format_version": "1.0.0",
"layer": {
"name": "VK_LAYER_reshade",
"type": "GLOBAL",
"library_path": ".\\ReShade32.dll",
"api_version": "1.3.204",
"implementation_version": "1",
"description": "crosire's ReShade post-processing injector for 32-bit",
"device_extensions": [
{
"name": "VK_EXT_tooling_info",
"spec_version": "1",
"entrypoints": [ "vkGetPhysicalDeviceToolPropertiesEXT" ]
}
],
"disable_environment": {
"DISABLE_VK_LAYER_reshade_1": "1"
}
}
}

Binary file not shown.

View File

@ -0,0 +1,21 @@
{
"file_format_version": "1.0.0",
"layer": {
"name": "VK_LAYER_reshade",
"type": "GLOBAL",
"library_path": ".\\ReShade64.dll",
"api_version": "1.3.204",
"implementation_version": "1",
"description": "crosire's ReShade post-processing injector for 64-bit",
"device_extensions": [
{
"name": "VK_EXT_tooling_info",
"spec_version": "1",
"entrypoints": [ "vkGetPhysicalDeviceToolPropertiesEXT" ]
}
],
"disable_environment": {
"DISABLE_VK_LAYER_reshade_1": "1"
}
}
}

View File

@ -0,0 +1,530 @@
/*------------------.
| :: Description :: |
'-------------------/
Ascii (Version 0.9)
Author: CeeJay.dk
License: MIT
About:
Converts the image to ASCII characters using a greyscale algoritm,
cherrypicked characters and a custom bitmap font stored in a set of floats.
It has 17 gray levels but uses dithering to greatly increase that number.
Ideas for future improvement:
* Cleanup code
* Maybe find a better/faster pattern - possibly blur the pixels first with a 2 pass aproach
* Try using a font atlas for more fonts or perhaps more performance
* Try making an ordered dither rather than the random one. I think the random looks a bit too noisy.
* Calculate luma from linear colorspace
History:
(*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility
Version 0.7 by CeeJay.dk
* Added the 3x5 font
Version 0.8 by CeeJay.dk
+ Cleaned up settings UI for Reshade 3.x
Version 0.9 by CeeJay.dk
x Fixed an issue with the settings where the 3x5 could not be selected.
- Cleaned up and commented the code. More cleanup is still needed.
* Added the ability to toggle dithering on/off
x Removed temporal dither code due to incompatibility with humans - it was giving me headaches and I didn't want to cause anyones seizure
x Fixed an uneven distribution of the greyscale shades
*/
/*---------------.
| :: Includes :: |
'---------------*/
#include "ReShade.fxh"
/*------------------.
| :: UI Settings :: |
'------------------*/
#include "ReShadeUI.fxh"
/*
uniform float Version <
ui_label = "Version";
ui_min = 0.8;
ui_max = 0.8;
ui_step = 1.0;
ui_category = "Author : CeeJay.dk\n\n"
"To increase the size of the characters on screen simply lower your resolution in-game\n\n"
"Try using this together with Nostagia. It also looks best if you first increase the contrast with Curves.\n\n";
> = float(0.8);
*/
uniform int Ascii_spacing < __UNIFORM_SLIDER_INT1
ui_min = 0;
ui_max = 5;
ui_label = "Character Spacing";
ui_tooltip = "Determines the spacing between characters. I feel 1 to 3 looks best.";
ui_category = "Font style";
> = 1;
/*
uniform int Ascii_font <
ui_type = "drag";
ui_min = 1;
ui_max = 2;
ui_label = "Font Size";
ui_tooltip = "1 = 5x5 font, 2 = 3x5 font";
ui_category = "Font style";
> = 1;
*/
uniform int Ascii_font <
ui_type = "combo";
ui_label = "Font Size";
ui_tooltip = "Choose font size";
ui_category = "Font style";
ui_items =
"Smaller 3x5 font\0"
"Normal 5x5 font\0"
;
> = 1;
uniform int Ascii_font_color_mode < __UNIFORM_SLIDER_INT1
ui_min = 0;
ui_max = 2;
ui_label = "Font Color Mode";
ui_tooltip = "0 = Foreground color on background color, 1 = Colorized grayscale, 2 = Full color";
ui_category = "Color options";
> = 1;
uniform float3 Ascii_font_color < __UNIFORM_COLOR_FLOAT3
ui_label = "Font Color";
ui_tooltip = "Choose a font color";
ui_category = "Color options";
> = float3(1.0, 1.0, 1.0);
uniform float3 Ascii_background_color < __UNIFORM_COLOR_FLOAT3
ui_label = "Background Color";
ui_tooltip = "Choose a background color";
ui_category = "Color options";
> = float3(0.0, 0.0, 0.0);
uniform bool Ascii_swap_colors <
ui_label = "Swap Colors";
ui_tooltip = "Swaps the font and background color when you are too lazy to edit the settings above (I know I am)";
ui_category = "Color options";
> = 0;
uniform bool Ascii_invert_brightness <
ui_label = "Invert Brightness";
ui_category = "Color options";
> = 0;
uniform bool Ascii_dithering <
ui_label = "Dithering";
ui_category = "Dithering";
> = 1;
uniform float Ascii_dithering_intensity < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0;
ui_max = 4.0;
ui_label = "Dither shift intensity";
ui_tooltip = "For debugging purposes";
ui_category = "Debugging";
> = 2.0;
uniform bool Ascii_dithering_debug_gradient <
ui_label = "Dither debug gradient";
ui_category = "Debugging";
> = 0;
/*-------------------------.
| :: Sampler and timers :: |
'-------------------------*/
#define asciiSampler ReShade::BackBuffer
uniform float timer < source = "timer"; >;
uniform float framecount < source = "framecount"; >;
/*-------------.
| :: Effect :: |
'-------------*/
float3 AsciiPass( float2 tex )
{
/*-------------------------.
| :: Sample and average :: |
'-------------------------*/
//if (Ascii_font != 1)
float2 Ascii_font_size = float2(3.0,5.0); //3x5
float num_of_chars = 14. ;
if (Ascii_font == 1)
{
Ascii_font_size = float2(5.0,5.0); //5x5
num_of_chars = 17.;
}
float quant = 1.0/(num_of_chars-1.0); //value used for quantization
float2 Ascii_block = Ascii_font_size + float(Ascii_spacing);
float2 cursor_position = trunc((BUFFER_SCREEN_SIZE / Ascii_block) * tex) * (Ascii_block / BUFFER_SCREEN_SIZE);
//TODO Cleanup - and maybe find a better/faster pattern - possibly blur the pixels first with a 2 pass aproach
//-- Pattern 2 - Sample ALL the pixels! --
float3 color = tex2D(asciiSampler, cursor_position + float2( 1.5, 1.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 1.5, 3.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 1.5, 5.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 0.5, 6.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 3.5, 1.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 3.5, 3.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 3.5, 5.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 2.5, 6.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 5.5, 1.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 5.5, 3.5) * BUFFER_PIXEL_SIZE).rgb;
color += tex2D(asciiSampler, cursor_position + float2( 5.5, 5.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 4.5, 6.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 6.5, 0.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 6.5, 2.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 6.5, 4.5) * BUFFER_PIXEL_SIZE).rgb;
//color += tex2D(asciiSampler, cursor_position + float2( 6.5, 6.5) * BUFFER_PIXEL_SIZE).rgb;
color /= 9.0;
/*
//-- Pattern 3 - Just one --
float3 color = tex2D(asciiSampler, cursor_position + float2(4.0,4.0) * BUFFER_PIXEL_SIZE) .rgb; //this may be fast but it's not very temporally stable
*/
/*------------------------.
| :: Make it grayscale :: |
'------------------------*/
float luma = dot(color,float3(0.2126, 0.7152, 0.0722));
float gray = luma;
if (Ascii_invert_brightness)
gray = 1.0 - gray;
/*----------------.
| :: Debugging :: |
'----------------*/
if (Ascii_dithering_debug_gradient)
{
//gray = sqrt(dot(float2((cursor_position.x - 0.5)*1.778,cursor_position.y - 0.5),float2((cursor_position.x - 0.5)*1.778,cursor_position.y - 0.5))) * 1.1;
//gray = (cursor_position.x + cursor_position.y) * 0.5; //diagonal test gradient
//gray = smoothstep(0.0,1.0,gray); //increase contrast
gray = cursor_position.x; //horizontal test gradient
//gray = cursor_position.y; //vertical test gradient
}
/*-------------------.
| :: Get position :: |
'-------------------*/
float2 p = frac((BUFFER_SCREEN_SIZE / Ascii_block) * tex); //p is the position of the current pixel inside the character
p = trunc(p * Ascii_block);
//p = trunc(p * Ascii_block - float2(1.5,1.5)) ;
float x = (Ascii_font_size.x * p.y + p.x); //x is the number of the position in the bitfield
/*----------------.
| :: Dithering :: |
'----------------*/
//TODO : Try make an ordered dither rather than the random dither. Random looks a bit too noisy for my taste.
if (Ascii_dithering != 0)
{
//Pseudo Random Number Generator
// -- PRNG 1 - Reference --
float seed = dot(cursor_position, float2(12.9898,78.233)); //I could add more salt here if I wanted to
float sine = sin(seed); //cos also works well. Sincos too if you want 2D noise.
float noise = frac(sine * 43758.5453 + cursor_position.y);
float dither_shift = (quant * Ascii_dithering_intensity); // Using noise to determine shift.
float dither_shift_half = (dither_shift * 0.5); // The noise should vary between +- 0.5
dither_shift = dither_shift * noise - dither_shift_half; // MAD
//shift the color by dither_shift
gray += dither_shift; //apply dithering
}
/*---------------------------.
| :: Convert to character :: |
'---------------------------*/
float n = 0;
if (Ascii_font == 1)
{
// -- 5x5 bitmap font by CeeJay.dk --
// .:^"~cvo*wSO8Q0#
//17 characters including space which is handled as a special case
//The serial aproach to this would take 16 cycles, so I instead used an upside down binary tree to parallelize this to only 5 cycles
float n12 = (gray < (2. * quant)) ? 4194304. : 131200. ; // . or :
float n34 = (gray < (4. * quant)) ? 324. : 330. ; // ^ or "
float n56 = (gray < (6. * quant)) ? 283712. : 12650880.; // ~ or c
float n78 = (gray < (8. * quant)) ? 4532768. : 13191552.; // v or o
float n910 = (gray < (10. * quant)) ? 10648704. : 11195936.; // * or w
float n1112 = (gray < (12. * quant)) ? 15218734. : 15255086.; // S or O
float n1314 = (gray < (14. * quant)) ? 15252014. : 32294446.; // 8 or Q
float n1516 = (gray < (16. * quant)) ? 15324974. : 11512810.; // 0 or #
float n1234 = (gray < (3. * quant)) ? n12 : n34;
float n5678 = (gray < (7. * quant)) ? n56 : n78;
float n9101112 = (gray < (11. * quant)) ? n910 : n1112;
float n13141516 = (gray < (15. * quant)) ? n1314 : n1516;
float n12345678 = (gray < (5. * quant)) ? n1234 : n5678;
float n910111213141516 = (gray < (13. * quant)) ? n9101112 : n13141516;
n = (gray < (9. * quant)) ? n12345678 : n910111213141516;
}
else // Ascii_font == 0 , the 3x5 font
{
// -- 3x5 bitmap font by CeeJay.dk --
// .:;s*oSOXH0
//14 characters including space which is handled as a special case
/* Font reference :
//The plusses are "likes". I was rating how much I liked that character over other alternatives.
3 ^ 42.
3 - 448.
3 i (short) 9232.
3 ; 5136. ++
4 " 45.
4 i 9346.
4 s 5200. ++
5 + 1488.
5 * 2728. ++
6 c 25200.
6 o 11088. ++
7 v 11112.
7 S 14478. ++
8 O 11114. ++
9 F 5071.
9 5 (rounded) 14543.
9 X 23213. ++
10 A 23530.
10 D 15211. +
11 H 23533. +
11 5 (square) 31183.
11 2 (square) 29671. ++
5 (rounded) 14543.
*/
float n12 = (gray < (2. * quant)) ? 4096. : 1040. ; // . or :
float n34 = (gray < (4. * quant)) ? 5136. : 5200. ; // ; or s
float n56 = (gray < (6. * quant)) ? 2728. : 11088.; // * or o
float n78 = (gray < (8. * quant)) ? 14478. : 11114.; // S or O
float n910 = (gray < (10. * quant)) ? 23213. : 15211.; // X or D
float n1112 = (gray < (12. * quant)) ? 23533. : 31599.; // H or 0
float n13 = 31727.; // 8
float n1234 = (gray < (3. * quant)) ? n12 : n34;
float n5678 = (gray < (7. * quant)) ? n56 : n78;
float n9101112 = (gray < (11. * quant)) ? n910 : n1112;
float n12345678 = (gray < (5. * quant)) ? n1234 : n5678;
float n910111213 = (gray < (13. * quant)) ? n9101112 : n13;
n = (gray < (9. * quant)) ? n12345678 : n910111213;
}
/*--------------------------------.
| :: Decode character bitfield :: |
'--------------------------------*/
float character = 0.0;
//Test values
//n = -(exp2(24.)-1.0); //-(2^24-1) All bits set - a white 5x5 box
float lit = (gray <= (1. * quant)) //If black then set all pixels to black (the space character)
? 0.0 //That way I don't have to use a character bitfield for space
: 1.0 ; //I simply let it to decode to the second darkest "." and turn its pixels off
float signbit = (n < 0.0) //is n negative? (I would like to test for negative 0 here too but can't)
? lit
: 0.0 ;
signbit = (x > 23.5) //is this the first pixel in the character?
? signbit //if so set to the signbit (which may be on or off depending on if the number was negative)
: 0.0 ; //else make it black
//Tenary Multiply exp2
character = ( frac( abs( n*exp2(-x-1.0))) >= 0.5) ? lit : signbit; //If the bit for the right position is set, then light up the pixel
//UNLESS gray was dark enough, then keep the pixel dark to make a space
//If the bit for the right position was not set, then turn off the pixel
//UNLESS it's the first pixel in the character AND n is negative - if so light up the pixel.
//This way I can use all 24 bits in the mantissa as well as the signbit for characters.
if (clamp(p.x, 0.0, Ascii_font_size.x - 1.0) != p.x || clamp(p.y, 0.0, Ascii_font_size.y - 1.0) != p.y) //Is this the space around the character?
character = 0.0; //If so make the pixel black.
/*---------------.
| :: Colorize :: |
'---------------*/
if (Ascii_swap_colors)
{
if (Ascii_font_color_mode == 2)
{
color = (character) ? character * color : Ascii_font_color;
}
else if (Ascii_font_color_mode == 1)
{
color = (character) ? Ascii_background_color * gray : Ascii_font_color;
}
else // Ascii_font_color_mode == 0
{
color = (character) ? Ascii_background_color : Ascii_font_color;
}
}
else
{
if (Ascii_font_color_mode == 2)
{
color = (character) ? character * color : Ascii_background_color;
}
else if (Ascii_font_color_mode == 1)
{
color = (character) ? Ascii_font_color * gray : Ascii_background_color;
}
else // Ascii_font_color_mode == 0
{
color = (character) ? Ascii_font_color : Ascii_background_color;
}
}
/*-------------.
| :: Return :: |
'-------------*/
//color = gray;
return saturate(color);
}
float3 PS_Ascii(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float3 color = AsciiPass(texcoord);
return color.rgb;
}
technique ASCII
{
pass ASCII
{
VertexShader=PostProcessVS;
PixelShader=PS_Ascii;
}
}
/*
.---------------------.
| :: Character set :: |
'---------------------'
Here are some various chacters and gradients I created in my quest to get the best look
.'~:;!>+=icjtJY56SXDQKHNWM
.':!+ijY6XbKHNM
.:%oO$8@#M
.:+j6bHM
.:coCO8@
.:oO8@
.:oO8
:+#
.:^"~cso*wSO8Q0#
.:^"~csoCwSO8Q0#
.:^"~c?o*wSO8Q0#
n value // # of pixels // character
------------//----//-------------------
4194304. // 1 // . (bottom aligned) *
131200. // 2 // : (middle aligned) *
4198400. // 2 // : (bottom aligned)
132. // 2 // '
2228352. // 3 // ;
4325504. // 3 // i (short)
14336. // 3 // - (small)
324. // 3 // ^
4329476. // 4 // i (tall)
330. // 4 // "
31744. // 5 // - (larger)
283712. // 5 // ~
10627072. // 5 // x
145536. // 5 // * or + (small and centered)
6325440. // 6 // c (narrow - left aligned)
12650880. // 6 // c (narrow - center aligned)
9738240. // 6 // n (left aligned)
6557772. // 7 // s (tall)
8679696. // 7 // f
4532768. // 7 // v (1st)
4539936. // 7 // v (2nd)
4207118. // 7 // ?
-17895696. // 7 // %
6557958. // 7 // 3
6595776. // 8 // o (left aligned)
13191552. // 8 // o (right aligned)
14714304. // 8 // c (wide)
12806528. // 9 // e (right aligned)
332772. // 9 // * (top aligned)
10648704. // 9 // * (bottom aligned)
4357252. // 9 // +
-18157904. // 9 // X
11195936. // 10 // w
483548. // 10 // s (thick)
15218734. // 11 // S
31491134. // 11 // C
15238702. // 11 // C (rounded)
22730410. // 11 // M (more like a large m)
10648714. // 11 // * (larger)
4897444. // 11 // * (2nd larger)
14726438. // 11 // @ (also looks like a large e)
23385164. // 11 // &
15255086. // 12 // O
16267326. // 13 // S (slightly larger)
15252014. // 13 // 8
15259182. // 13 // 0 (O with dot in the middle)
15517230. // 13 // Q (1st)
-18405232. // 13 // M
-11196080. // 13 // W
32294446. // 14 // Q (2nd)
15521326. // 14 // Q (3rd)
32298542. // 15 // Q (4th)
15324974. // 15 // 0 or Ø
16398526. // 15 // $
11512810. // 16 // #
-33061950. // 17 // 5 or S (stylized)
-33193150. // 19 // $ (stylized)
-33150782. // 19 // 0 (stylized)
*/

View File

@ -0,0 +1,589 @@
/*------------------.
| :: Description :: |
'-------------------/
Blending Header (version 0.8)
Blending Algorithm Sources:
https://www.khronos.org/registry/OpenGL/extensions/NV/NV_blend_equation_advanced.txt
http://www.nathanm.com/photoshop-blending-math/
(Alt) https://github.com/cplotts/WPFSLBlendModeFx/blob/master/PhotoshopMathFP.hlsl
Header Authors: originalnicodr, prod80, uchu suzume, Marot Satil
About:
Provides a variety of blending methods for you to use as you wish. Just include this header.
History:
(*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility
Version 0.1 by Marot Satil & uchu suzume
* Added and improved upon multiple blending modes thanks to the work of uchu suzume, prod80, and originalnicodr.
Version 0.2 by uchu suzume & Marot Satil
* Added Addition, Subtract, Divide blending modes and improved code readability.
Version 0.3 by uchu suzume & Marot Satil
* Sorted blending modes in a more logical fashion, grouping by type.
Version 0.4 by uchu suzume
x Corrected Color Dodge blending behavior.
Version 0.5 by Marot Satil & uchu suzume
* Added preprocessor macros for uniform variable combo UI element & lerp.
Version 0.6 by Marot Satil & uchu suzume
* Added Divide (Alternative) and Divide (Photoshop) blending modes.
Version 0.7 by prod80
- Added original sources for blending algorithms.
x Corrected average luminosity values.
Version 0.8 by Marot Satil
* Added a new funciton to output blended data.
+ Moved all code into the BlendingH namespace, which is part of the ComHeaders common namespace meant to be used by other headers.
! Removed old preprocessor macro blending output.
.------------------.
| :: How To Use :: |
'------------------/
Blending two variables using this header in your own shaders is very straightforward.
Very basic example code using the "Darken" blending mode follows:
// First, include the header.
#include "Blending.fxh"
// You can use this preprocessor macro to generate an attractive and functional uniform int UI combo element containing the list of blending techniques:
// BLENDING_COMBO(variable_name, label, tooltip, category, category_closed, spacing, default_value)
BLENDING_COMBO(_BlendMode, "Blending Mode", "Select the blending mode applied to the layer.", "Blending Options", false, 0, 0)
// Inside of your function you can call this function to apply the blending option specified by an int (variable) to your float3 (input) via
// a lerp between your float3 (input), float3 (output), and a float (blending) for the alpha channel.
// ComHeaders::Blending::Blend(int variable, float3 input, float3 output, float blending)
outColor.rgb = ComHeaders::Blending::Blend(_BlendMode, inColor, outColor, outColor.a);
*/
// -------------------------------------
// Preprocessor Macros
// -------------------------------------
#undef BLENDING_COMBO
#define BLENDING_COMBO(variable, name_label, description, group, grp_closed, space, default_value) \
uniform int variable \
< \
ui_category = group; \
ui_category_closed = grp_closed; \
ui_items = \
"Normal\0" \
/* "Darken" */ \
"Darken\0" \
" Multiply\0" \
" Color Burn\0" \
" Linear Burn\0" \
/* "Lighten" */ \
"Lighten\0" \
" Screen\0" \
" Color Dodge\0" \
" Linear Dodge\0" \
" Addition\0" \
" Glow\0" \
/* "Contrast" */ \
"Overlay\0" \
" Soft Light\0" \
" Hard Light\0" \
" Vivid Light\0" \
" Linear Light\0" \
" Pin Light\0" \
" Hard Mix\0" \
/* "Inversion" */ \
"Difference\0" \
" Exclusion\0" \
/* "Cancelation" */ \
"Subtract\0" \
" Divide\0" \
" Divide (Alternative)\0" \
" Divide (Photoshop)\0" \
" Reflect\0" \
" Grain Extract\0" \
" Grain Merge\0" \
/* "Component" */ \
"Hue\0" \
" Saturation\0" \
" Color\0" \
" Luminosity\0"; \
ui_label = name_label; \
ui_tooltip = description; \
ui_type = "combo"; \
ui_spacing = space; \
> = default_value;
namespace ComHeaders
{
namespace Blending
{
// -------------------------------------
// Helper Functions
// -------------------------------------
float3 Aux(float3 a)
{
if (a.r <= 0.25 && a.g <= 0.25 && a.b <= 0.25)
return ((16.0 * a - 12.0) * a + 4) * a;
else
return sqrt(a);
}
float Lum(float3 a)
{
return (0.33333 * a.r + 0.33334 * a.g + 0.33333 * a.b);
}
float3 SetLum (float3 a, float b){
const float c = b - Lum(a);
return float3(a.r + c, a.g + c, a.b + c);
}
float min3 (float a, float b, float c)
{
return min(a, (min(b, c)));
}
float max3 (float a, float b, float c)
{
return max(a, max(b, c));
}
float3 SetSat(float3 a, float b){
float ar = a.r;
float ag = a.g;
float ab = a.b;
if (ar == max3(ar, ag, ab) && ab == min3(ar, ag, ab))
{
//caso r->max g->mid b->min
if (ar > ab)
{
ag = (((ag - ab) * b) / (ar - ab));
ar = b;
}
else
{
ag = 0.0;
ar = 0.0;
}
ab = 0.0;
}
else
{
if (ar == max3(ar, ag, ab) && ag == min3(ar, ag, ab))
{
//caso r->max b->mid g->min
if (ar > ag)
{
ab = (((ab - ag) * b) / (ar - ag));
ar = b;
}
else
{
ab = 0.0;
ar = 0.0;
}
ag = 0.0;
}
else
{
if (ag == max3(ar, ag, ab) && ab == min3(ar, ag, ab))
{
//caso g->max r->mid b->min
if (ag > ab)
{
ar = (((ar - ab) * b) / (ag - ab));
ag = b;
}
else
{
ar = 0.0;
ag = 0.0;
}
ab = 0.0;
}
else
{
if (ag == max3(ar, ag, ab) && ar == min3(ar, ag, ab))
{
//caso g->max b->mid r->min
if (ag > ar)
{
ab = (((ab - ar) * b) / (ag - ar));
ag = b;
}
else
{
ab = 0.0;
ag = 0.0;
}
ar = 0.0;
}
else
{
if (ab == max3(ar, ag, ab) && ag == min3(ar, ag, ab))
{
//caso b->max r->mid g->min
if (ab > ag)
{
ar = (((ar - ag) * b) / (ab - ag));
ab = b;
}
else
{
ar = 0.0;
ab = 0.0;
}
ag = 0.0;
}
else
{
if (ab == max3(ar, ag, ab) && ar == min3(ar, ag, ab))
{
//caso b->max g->mid r->min
if (ab > ar)
{
ag = (((ag - ar) * b) / (ab - ar));
ab = b;
}
else
{
ag = 0.0;
ab = 0.0;
}
ar = 0.0;
}
}
}
}
}
}
return float3(ar, ag, ab);
}
float Sat(float3 a)
{
return max3(a.r, a.g, a.b) - min3(a.r, a.g, a.b);
}
// -------------------------------------
// Blending Modes
// -------------------------------------
// Darken
float3 Darken(float3 a, float3 b)
{
return min(a, b);
}
// Multiply
float3 Multiply(float3 a, float3 b)
{
return a * b;
}
// Color Burn
float3 ColorBurn(float3 a, float3 b)
{
if (b.r > 0 && b.g > 0 && b.b > 0)
return 1.0 - min(1.0, (0.5 - a) / b);
else
return 0.0;
}
// Linear Burn
float3 LinearBurn(float3 a, float3 b)
{
return max(a + b - 1.0f, 0.0f);
}
// Lighten
float3 Lighten(float3 a, float3 b)
{
return max(a, b);
}
// Screen
float3 Screen(float3 a, float3 b)
{
return 1.0 - (1.0 - a) * (1.0 - b);
}
// Color Dodge
float3 ColorDodge(float3 a, float3 b)
{
if (b.r < 1 && b.g < 1 && b.b < 1)
return min(1.0, a / (1.0 - b));
else
return 1.0;
}
// Linear Dodge
float3 LinearDodge(float3 a, float3 b)
{
return min(a + b, 1.0f);
}
// Addition
float3 Addition(float3 a, float3 b)
{
return min((a + b), 1);
}
// Reflect
float3 Reflect(float3 a, float3 b)
{
if (b.r >= 0.999999 || b.g >= 0.999999 || b.b >= 0.999999)
return b;
else
return saturate(a * a / (1.0f - b));
}
// Glow
float3 Glow(float3 a, float3 b)
{
return Reflect(b, a);
}
// Overlay
float3 Overlay(float3 a, float3 b)
{
return lerp(2 * a * b, 1.0 - 2 * (1.0 - a) * (1.0 - b), step(0.5, a));
}
// Soft Light
float3 SoftLight(float3 a, float3 b)
{
if (b.r <= 0.5 && b.g <= 0.5 && b.b <= 0.5)
return clamp(a - (1.0 - 2 * b) * a * (1 - a), 0,1);
else
return clamp(a + (2 * b - 1.0) * (Aux(a) - a), 0, 1);
}
// Hard Light
float3 HardLight(float3 a, float3 b)
{
return lerp(2 * a * b, 1.0 - 2 * (1.0 - b) * (1.0 - a), step(0.5, b));
}
// Vivid Light
float3 VividLight(float3 a, float3 b)
{
return lerp(2 * a * b, b / (2 * (1.01 - a)), step(0.50, a));
}
// Linear Light
float3 LinearLight(float3 a, float3 b)
{
if (b.r < 0.5 || b.g < 0.5 || b.b < 0.5)
return LinearBurn(a, (2.0 * b));
else
return LinearDodge(a, (2.0 * (b - 0.5)));
}
// Pin Light
float3 PinLight(float3 a, float3 b)
{
if (b.r < 0.5 || b.g < 0.5 || b.b < 0.5)
return Darken(a, (2.0 * b));
else
return Lighten(a, (2.0 * (b - 0.5)));
}
// Hard Mix
float3 HardMix(float3 a, float3 b)
{
const float3 vl = VividLight(a, b);
if (vl.r < 0.5 || vl.g < 0.5 || vl.b < 0.5)
return 0.0;
else
return 1.0;
}
// Difference
float3 Difference(float3 a, float3 b)
{
return max(a - b, b - a);
}
// Exclusion
float3 Exclusion(float3 a, float3 b)
{
return a + b - 2 * a * b;
}
// Subtract
float3 Subtract(float3 a, float3 b)
{
return max((a - b), 0);
}
// Divide
float3 Divide(float3 a, float3 b)
{
return (saturate(a / (b + 0.01)));
}
// Divide (Alternative)
float3 DivideAlt(float3 a, float3 b)
{
return (saturate(1.0 / (a / b)));
}
// Divide (Photoshop)
float3 DividePS(float3 a, float3 b)
{
return (saturate(a / b));
}
// Grain Merge
float3 GrainMerge(float3 a, float3 b)
{
return saturate(b + a - 0.5);
}
// Grain Extract
float3 GrainExtract(float3 a, float3 b)
{
return saturate(a - b + 0.5);
}
// Hue
float3 Hue(float3 a, float3 b)
{
return SetLum(SetSat(b, Sat(a)), Lum(a));
}
// Saturation
float3 Saturation(float3 a, float3 b)
{
return SetLum(SetSat(a, Sat(b)), Lum(a));
}
// Color
float3 ColorB(float3 a, float3 b)
{
return SetLum(b, Lum(a));
}
// Luminousity
float3 Luminosity(float3 a, float3 b)
{
return SetLum(a, Lum(b));
}
// -------------------------------------
// Output Functions
// -------------------------------------
float3 Blend(int mode, float3 input, float3 output, float blending)
{
switch (mode)
{
// Normal
default:
return lerp(input.rgb, output.rgb, blending);
// Darken
case 1:
return lerp(input.rgb, Darken(input.rgb, output.rgb), blending);
// Multiply
case 2:
return lerp(input.rgb, Multiply(input.rgb, output.rgb), blending);
// Color Burn
case 3:
return lerp(input.rgb, ColorBurn(input.rgb, output.rgb), blending);
// Linear Burn
case 4:
return lerp(input.rgb, LinearBurn(input.rgb, output.rgb), blending);
// Lighten
case 5:
return lerp(input.rgb, Lighten(input.rgb, output.rgb), blending);
// Screen
case 6:
return lerp(input.rgb, Screen(input.rgb, output.rgb), blending);
// Color Dodge
case 7:
return lerp(input.rgb, ColorDodge(input.rgb, output.rgb), blending);
// Linear Dodge
case 8:
return lerp(input.rgb, LinearDodge(input.rgb, output.rgb), blending);
// Addition
case 9:
return lerp(input.rgb, Addition(input.rgb, output.rgb), blending);
// Glow
case 10:
return lerp(input.rgb, Glow(input.rgb, output.rgb), blending);
// Overlay
case 11:
return lerp(input.rgb, Overlay(input.rgb, output.rgb), blending);
// Soft Light
case 12:
return lerp(input.rgb, SoftLight(input.rgb, output.rgb), blending);
// Hard Light
case 13:
return lerp(input.rgb, HardLight(input.rgb, output.rgb), blending);
// Vivid Light
case 14:
return lerp(input.rgb, VividLight(input.rgb, output.rgb), blending);
// Linear Light
case 15:
return lerp(input.rgb, LinearLight(input.rgb, output.rgb), blending);
// Pin Light
case 16:
return lerp(input.rgb, PinLight(input.rgb, output.rgb), blending);
// Hard Mix
case 17:
return lerp(input.rgb, HardMix(input.rgb, output.rgb), blending);
// Difference
case 18:
return lerp(input.rgb, Difference(input.rgb, output.rgb), blending);
// Exclusion
case 19:
return lerp(input.rgb, Exclusion(input.rgb, output.rgb), blending);
// Subtract
case 20:
return lerp(input.rgb, Subtract(input.rgb, output.rgb), blending);
// Divide
case 21:
return lerp(input.rgb, Divide(input.rgb, output.rgb), blending);
// Divide (Alternative)
case 22:
return lerp(input.rgb, DivideAlt(input.rgb, output.rgb), blending);
// Divide (Photoshop)
case 23:
return lerp(input.rgb, DividePS(input.rgb, output.rgb), blending);
// Reflect
case 24:
return lerp(input.rgb, Reflect(input.rgb, output.rgb), blending);
// Grain Merge
case 25:
return lerp(input.rgb, GrainMerge(input.rgb, output.rgb), blending);
// Grain Extract
case 26:
return lerp(input.rgb, GrainExtract(input.rgb, output.rgb), blending);
// Hue
case 27:
return lerp(input.rgb, Hue(input.rgb, output.rgb), blending);
// Saturation
case 28:
return lerp(input.rgb, Saturation(input.rgb, output.rgb), blending);
// Color
case 29:
return lerp(input.rgb, ColorB(input.rgb, output.rgb), blending);
// Luminosity
case 30:
return lerp(input.rgb, Luminosity(input.rgb, output.rgb), blending);
}
}
}
}

View File

@ -0,0 +1,990 @@
////----------------//
///**Blooming HDR**///
//----------------////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// *//
//*For Reshade 3.0+ HDR Bloom
//*--------------------------
//* Blooming HDR
//*
//* Due Diligence
//* Eye Adaptation
//* https://knarkowicz.wordpress.com/2016/01/09/automatic-exposure/ Search Ref. Temporal Adaptation
//* Prods80 AKA ThatRedDot port of exposure.
//* Additional credits (exposure)
//* - Padraic Hennessy for the logic
//* https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/
//* - Padraic Hennessy for the logic
//* https://placeholderart.wordpress.com/2014/12/15/implementing-a-physically-based-camera-automatic-exposure/
//* - MJP and David Neubelt for the method
//* https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/Exposure.hlsl
//* License: MIT, Copyright (c) 2016 MJP
//* Reinhard by Tom Madams
//* http://imdoingitwrong.wordpress.com/2010/08/19/why-reinhard-desaturates-my-blacks-3/
//* Uncharted2 Tone Mapper by Hable John
//* https://www.slideshare.net/ozlael/hable-john-uncharted2-hdr-lighting
//* ACES Cinematic Tonemapping by Krzysztof Narkowicz and one by Stephen Hill
//* https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
//* https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
//* Timothy Lottes Tone mapper and information from this site.
//* https://bartwronski.com/2016/09/01/dynamic-range-and-evs/
//* https://www.shadertoy.com/view/XljBRK
//* Generate Gold Noise image Based on this implamentation
//* https://www.shadertoy.com/view/wtsSW4
//* Depth Bloom CeeJay.dk
//* His brain told me to do it...... I just added it.
//* Adyss Bloom used as Insperation for Bloom Rework. Miss you man. Hope you come back.
//*
//* Since it was already witten out nicely was ported from. FidelityFX LPM was it self was not ported.
//* https://github.com/GPUOpen-Effects/FidelityFX-LPM
//* Most of the code is LICENSED this way.
//* https://github.com/GPUOpen-Effects/FidelityFX-LPM/blob/4a1442bf7405d0f703f7cf9c0bfe47a7559cc69b/sample/src/DX12/LPMSample.h#L3-L18
//*
//* The rest of the code below is under it's own license.
//* If I missed any please tell me.
//*
//* LICENSE
//* ============
//* Blooming HDR is licenses under: Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format
//* for any purpose, even commercially.
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* ShareAlike <20> If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by-sa/4.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Shared Texture for Blooming HDR or any other shader that want's to use it.
#if exists "Flair.fx" //Flair Interceptor//
#define Flare_A 1
#else
#define Flare_A 0
#endif
#if exists "Flare.fx" //Flare Interceptor//
#define Flare_B 1
#else
#define Flare_B 0
#endif
// Change this to set enable SRGB mode.
#define SRGB 0
//Do not Use.
//Use for real HDR.
#define HDR_Toggle 0 //For HDR10 10:10:10:2 use maybe 0.18/25.0 to start. Should only work with Thimothy
//Do not Use.
#if !defined(__RESHADE__) || __RESHADE__ < 40000
#define Compatibility 1
#else
#define Compatibility 0
#endif
uniform int Auto_Bloom <
ui_type = "combo";
ui_label = "Auto Bloom";
ui_items = "Off\0Auto Intensity\0Auto Desaturation\0Auto Saturation\0Auto Intensity & Desaturation\0Auto Intensity & Saturation\0";
ui_tooltip = "Auto Intensity will enable the shader to adjust Bloom Intensity automaticly though Bloom Opacity above.\n"
"Auto Saturation will enable the shader to adjust Bloom Saturation automaticly though Bloom Saturation above.\n"
"Default is Off.";
ui_category = "Bloom Adjustments";
> = 0;
uniform float CBT_Adjust <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.0; ui_max = 1.0;
ui_label = "Extracting Bright Colors";
ui_tooltip = "Use this to set the color based brightness threshold for what is and what isn't allowed.\n"
"This is the most important setting, use Debug View to adjust this.\n"
"Default Number is 0.5.";
ui_category = "Bloom Adjustments";
> = 0.5;
uniform float2 Bloom_Intensity<
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.0; ui_max = 1.0;
ui_label = "Bloom Intensity & Bloom Opacity";
ui_tooltip = "Use this to set Primary & Secondary Bloom Intensity and Overall Bloom Opacity for your content.\n"
//"The 2nd Option only works when Bloom Intensity Isolation is set above.\n"
"Number 0.1 & 0.5 is default.";
ui_category = "Bloom Adjustments";
> = float2(0.1,0.5);
uniform float BloomSensitivity <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.1; ui_max = 5.0;
ui_label = "Bloom Sensitivity";
ui_tooltip = "A Curve that is applied to the bloom input.";
ui_category = "Bloom Adjustments";
> = 1.0;
uniform float BloomCurve <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.1; ui_max = 5.0;
ui_label = "Bloom Curve";
ui_tooltip = "Defines the way the bloom spreads.";
ui_category = "Bloom Adjustments";
> = 2.0;
uniform float2 Saturation <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.0; ui_max = 1.0;
ui_label = "Bloom Saturation & Auto Cutoff Point";
ui_tooltip = "Adjustment The amount to adjust the saturation of the Bloom.\n"
"Number 0.25 is default for both.";
ui_category = "Bloom Adjustments";
> = float2(0.25,0.25);
uniform float Bloom_Spread <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.5; ui_max = 5.0;
ui_label = "Bloom Spread";
ui_tooltip = "Adjust to spread out the primary Bloom.\n"
"This is used for spreading Bloom.\n"
"Number 1.0 is default.";
ui_category = "Bloom Adjustments";
> = 1.0;
uniform float Dither_Bloom <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Bloom Dither";
ui_tooltip = "Adjustment The amount Dither on bloom to reduce banding.\n"
"Number 0.25 is default.";
ui_category = "Bloom Adjustments";
> = 0.125;
uniform int Tonemappers <
ui_type = "combo";
ui_label = "Tonemappers";
ui_tooltip = "Changes how color get used for the other effects.\n";
ui_items = "Timothy\0ACESFitted\0";
ui_category = "Tonemapper Adjustments";
> = 0;
uniform float WP <
ui_type = "drag";
ui_min = 0.00; ui_max = 2.00;
ui_label = "Linear White Point Value";
ui_category = "Tonemapper Adjustments";
> = 1.0;
uniform float Exp <
ui_type = "drag";
ui_min = -4.0; ui_max = 4.00;
ui_label = "Exposure";
ui_category = "Tonemapper Adjustments";
> = 0.0;
uniform float GreyValue <
ui_type = "drag";
ui_min = 0.0; ui_max = 0.5;
ui_label = "Exposure 50% Greyvalue";
ui_tooltip = "Exposure 50% Greyvalue Set this Higher when using ACES Fitted and Lower when using Timoithy.";
ui_category = "Tonemapper Adjustments";
> = 0.128;
uniform float Gamma <
ui_type = "drag";
ui_min = 1.0; ui_max = 4.0;
ui_label = "Gamma value";
ui_tooltip = "Most monitors/images use a value of 2.2. Setting this to 1 disables the inital color space conversion from gamma to linear.";
ui_category = "Tonemapper Adjustments";
> = 2.2;
uniform float Contrast <
ui_type = "drag";
ui_min = 0.0; ui_max = 3.0;
ui_tooltip = "Contrast Adjustment.\n"
"Number 1.0 is default.";
ui_category = "Tonemapper Adjustments";
> = 1.0;
uniform float Saturate <
ui_type = "drag";
ui_min = 0.0; ui_max = 2.0;
ui_label = "Image Saturation";
ui_tooltip = "Adjustment The amount to adjust the saturation of the color in the image.\n"
"Number 1.0 is default.";
ui_category = "Tonemapper Adjustments";
> = 1.0;
uniform int Inv_Tonemappers <
ui_type = "combo";
ui_label = "Extract HDR Information";
ui_tooltip = "Changes how color get used for the other effects.\n"
"Turn this Off when the game has a good HDR implementation.";
ui_items = "Off\0Luma\0Color\0Max Color Brightness\0";
ui_category = "HDR";
> = 2;
uniform float HDR_BP <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "HDR Power";
ui_tooltip = "Use adjsut the HDR Power, You can override this value and set it to like 1.5 or something.\n"
"Number 0.5 is default.";
ui_category = "HDR";
> = 0.5;
uniform bool Bloom_BA_iToneMapper <
ui_label = "HDR Bloom Application";
ui_tooltip = "This will let you swap between Befor HDR ToneMapper and After.";
ui_category = "HDR";
> = 0;
uniform int Auto_Exposure <
ui_type = "combo";
ui_label = "Auto Exposure Type";
ui_items = "Off\0Auto Exposure & Eye Adaptation\0Auto Exposure & Eyelids Adaptation\0";
ui_tooltip = "This will enable the shader to adjust Exposure automaticly.\n"
"This will also turn on Eye Adaptation for this shader.\n"
"This is based off Prod80's Port of an Auto-Expo Algo.\n"
"Padraic Hennessy, MJP and David Neubelt.";
ui_category = "Adaptation";
> = 1;
uniform float Adapt_Adjust <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Eye Adapt Speed";
ui_tooltip = "Use this to Adjust Eye Adaptation Speed.\n"
"Set from Zero to One, Zero is the slowest.\n"
"Number 0.5 is default.";
ui_category = "Adaptation";
> = 0.5;
uniform float Adapt_Seek <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Eye Adapt Seeking";
ui_tooltip = "Use this to Adjust Eye Seeking Radius for Average Brightness.\n"
"Set from 0 to 1, 1 is Full-Screen Average Brightness.\n"
"Number 0.5 is default.";
ui_category = "Adaptation";
> = 0.5;
uniform int Debug_View <
ui_type = "combo";
ui_label = "Debug View";
ui_items = "Normal View\0Bloom View\0Heat Map\0";
ui_tooltip = "To view Shade & Blur effect on the game, movie piture & ect.";
ui_category = "Debugging";
> = 0;
/////////////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
//#define BloomSpread Bloom_Spread * rcp(Bloom_Max)
#define DBP lerp(0.0,1.0,NFCD.z)
#define Sat lerp(0,10,Saturation.x)
#define PHI 1.61803398874989484820459 * 00000.1 // Golden Ratio
#define PI 3.14159265358979323846264 * 00000.1 // PI
#define SQ2 1.41421356237309504880169 * 10000.0 // Square Root of Two
#define BloomSamples 8
uniform float timer < source = "timer"; >;
texture DepthBufferTex : DEPTH;
sampler DepthBuffer
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
#if SRGB
SRGBTexture = true;
#endif
};
texture texCurrColor { Width = BUFFER_WIDTH * 0.5; Height = BUFFER_HEIGHT * 0.5; Format = RGBA8; MipLevels = 8;};
sampler SamplerCurrBB
{
Texture = texCurrColor;
};
//Bloom Passes
texture2D BloomTexH_A { Width = BUFFER_WIDTH / 2; Height = BUFFER_HEIGHT / 2; Format = RGBA16F;};
sampler2D TextureBloomH_A { Texture = BloomTexH_A;};
texture2D BloomTexV_A { Width = BUFFER_WIDTH / 2; Height = BUFFER_HEIGHT / 2; Format = RGBA16F;};
sampler2D TextureBloomV_A { Texture = BloomTexV_A;};
texture2D BloomTexH_B { Width = BUFFER_WIDTH / 4; Height = BUFFER_HEIGHT / 4; Format = RGBA16F;};
sampler2D TextureBloomH_B { Texture = BloomTexH_B;};
texture2D BloomTexV_B { Width = BUFFER_WIDTH / 4; Height = BUFFER_HEIGHT / 4; Format = RGBA16F;};
sampler2D TextureBloomV_B { Texture = BloomTexV_B;};
texture2D BloomTexH_C { Width = BUFFER_WIDTH / 8; Height = BUFFER_HEIGHT / 8; Format = RGBA16F;};
sampler2D TextureBloomH_C { Texture = BloomTexH_C;};
texture2D BloomTexV_C { Width = BUFFER_WIDTH / 8; Height = BUFFER_HEIGHT / 8; Format = RGBA16F;};
sampler2D TextureBloomV_C { Texture = BloomTexV_C;};
texture2D BloomTex { Width = BUFFER_WIDTH / 2; Height = BUFFER_HEIGHT / 2; Format = RGBA16F;};
sampler2D TextureBloom { Texture = BloomTex;};
#if Flare_A
texture TexFlareShared { Width = BUFFER_WIDTH ; Height = BUFFER_HEIGHT; Format = RGBA16F;};
sampler SamplerFlare
{
Texture = TexFlareShared;
};
#endif
#if Flare_B
texture TexLensFlareShared { Width = BUFFER_WIDTH ; Height = BUFFER_HEIGHT; Format = RGBA16F;};
sampler SamplerLensFlare
{
Texture = TexLensFlareShared;
};
#endif
//Total amount of frames since the game started.
uniform float frametime < source = "frametime";>;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Luma(float3 C)
{
float3 Luma;
if (HDR_Toggle == 0)
{
Luma = float3(0.2126, 0.7152, 0.0722); // (HD video) https://en.wikipedia.org/wiki/Luma_(video)
}
else
{
Luma = float3(0.2627, 0.6780, 0.0593); // (HDR video) https://en.wikipedia.org/wiki/Rec._2100
}
return dot(C,Luma);
}
float3 ApplyPQ(float3 color)
{
// Apply ST2084 curve
float m1 = 2610.0 / 4096.0 / 4;
float m2 = 2523.0 / 4096.0 * 128;
float c1 = 3424.0 / 4096.0;
float c2 = 2413.0 / 4096.0 * 32;
float c3 = 2392.0 / 4096.0 * 32;
float3 cp = pow(abs(color.xyz), m1);
color.xyz = pow((c1 + c2 * cp) / (1 + c3 * cp), m2);
return color;
}
//float3 ApplyscRGBScale(float3 color, float minLuminancePerNits, float maxLuminancePerNits)
//{
// color.xyz = (color.xyz * (maxLuminancePerNits - minLuminancePerNits)) + float3(minLuminancePerNits, minLuminancePerNits, minLuminancePerNits);
// return color;
//}
float Log2Exposure( in float avgLuminance, in float GreyValue )
{
float exposure = 0.0f;
avgLuminance = max(avgLuminance, 0.000001f);
// GreyValue should be 0.148 based on https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/
float linExp = GreyValue / avgLuminance;
exposure = log2( linExp );
return exposure;
}
float CalcExposedColor(in float avgLuminance, in float offset, in float GreyValue )
{
float exposure = Log2Exposure( avgLuminance, GreyValue * 2.2 );
exposure += offset; //offset = exposure
return exp2( exposure );
}
/////////////////////////////////////////////////////////////////////////////////Adapted Luminance/////////////////////////////////////////////////////////////////////////////////
texture texDS {Width = 256; Height = 256; Format = RG16F; MipLevels = 9;}; //Sample at 256x256 map only has nine mip levels; 0-1-2-3-4-5-6-7-8 : 256,128,64,32,16,8,4,2, and 1 (1x1).
sampler SamplerDS
{
Texture = texDS;
};
texture texTA {Width = 64; Height = 64; Format = R16F; };
sampler SamplerTA
{
Texture = texTA;
};
texture texStored {Width = 64; Height = 64; Format = R16F; };
sampler SamplerStored
{
Texture = texStored;
};
float3 Downsample(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float2 texXY = texcoord;
float2 midHV = (Adapt_Seek-1) * float2(BUFFER_WIDTH * 0.5,BUFFER_HEIGHT * 0.5) * pix;
float2 TC = float2((texXY.x*Adapt_Seek)-midHV.x,(texXY.y*Adapt_Seek)-midHV.y);
return float3(Luma(tex2D(BackBuffer,TC).rgb),0,0);
}
float PS_Temporal_Adaptation(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{ //Temporal adaptation https://knarkowicz.wordpress.com/2016/01/09/automatic-exposure/
float TT = 32500,EA = (1-Adapt_Adjust)*1250, L = tex2Dlod(SamplerDS,float4(texcoord,0,11)).x, PL_A = tex2D(SamplerStored, float2(0.25,0.25)).x, PL_B = tex2D(SamplerStored, float2(0.25,0.75)).x;
EA = Auto_Exposure >= 1 ? PL_A + (L - PL_A) * (1.0 - exp(-frametime/EA)) : L;
TT = Auto_Exposure >= 1 ? PL_B + (L - PL_B) * (1.0 - exp(-frametime/TT)) : L;
float ITF= 1-(smoothstep(1,0,TT) < 0.85);// Is trigger Based on a Treshold... //smoothstep(1,0,tex2D(SamplerTA,0.0).y) < 0.85
float FT = 2500, PStoredfade = tex2D(SamplerStored, float2(0.75,0.25)).x;//Top Right
float TF = PStoredfade + (ITF - PStoredfade) * (1.0 - exp2(-frametime/FT)); //Fade Time
//float3(EA,TT,TF)
//EA = 0;//Top Left float2(0.25,0.25).x
//TT = 0;//Bottom Left float2(0.25,0.75).y
//TF = 0;//Top Right float2(0.75,0.25).z
return texcoord.x > 0.5 ? (texcoord.y > 0.5 ? 0 : TF) : (texcoord.y > 0.5 ? TT : EA);
}
//----------------------------------Inverse ToneMappers--------------------------------------------
float max3(float x, float y, float z)
{
return max(x, max(y, z));
}
float3 inv_Tonemapper(float4 color, int TM)
{
if(TM == 1)//Timothy Lottes fast_reversible
return color.rgb * rcp((1.0 + max(color.w,0.001)) - max3(color.r, color.g, color.b));
else if(TM == 2)//Reinhard
return color.rgb * rcp(max((1.0 + color.w) - color.rgb,0.001));
else//Luma Reinhard
return color.rgb * rcp(max((1.0 + lerp(-0.5,0,color.w) ) - Luma(color.rgb),0.001));
}
//---------------------------------------ToneMappers-----------------------------------------------
// General tonemapping operator, build 'b' term.
float ColToneB(float hdrMax, float contrast, float shoulder, float midIn, float midOut)
{
return
-((-pow(midIn, contrast) + (midOut*(pow(hdrMax, contrast*shoulder)*pow(midIn, contrast) -
pow(hdrMax, contrast)*pow(midIn, contrast*shoulder)*midOut)) /
(pow(hdrMax, contrast*shoulder)*midOut - pow(midIn, contrast*shoulder)*midOut)) /
(pow(midIn, contrast*shoulder)*midOut));
}
// General tonemapping operator, build 'c' term.
float ColToneC(float hdrMax, float contrast, float shoulder, float midIn, float midOut)
{
return (pow(hdrMax, contrast*shoulder)*pow(midIn, contrast) - pow(hdrMax, contrast)*pow(midIn, contrast*shoulder)*midOut) /
(pow(hdrMax, contrast*shoulder)*midOut - pow(midIn, contrast*shoulder)*midOut);
}
// General tonemapping operator, p := {contrast,shoulder,b,c}.
float ColTone(float x, float4 p)
{
float z = pow(x, p.r);
return z / (pow(z, p.g)*p.b + p.a);
}
float3 TimothyTonemapper(float3 color, float EX)
{
float hdrMax = HDR_Toggle ? 25.0 : 16.0; // How much HDR range before clipping. HDR modes likely need this pushed up to say 25.0.
float contrast = Contrast + 0.250; // Use as a baseline to tune the amount of contrast the tonemapper has.
static float shoulder = 1.0; // Likely don't need to mess with this factor, unless matching existing tonemapper is not working well..
static float midIn = 0.11; // most games will have a {0.0 to 1.0} range for LDR so midIn should be 0.18.But,I settled around 0.11
float midOut = HDR_Toggle ? 0.18/25.0 : 0.18; // Use for LDR. For HDR10 10:10:10:2 use maybe 0.18/25.0 to start. For scRGB, I forget what a good starting point is, need to re-calculate.
float b = ColToneB(hdrMax, contrast, shoulder, midIn, midOut);
float c = ColToneC(hdrMax, contrast, shoulder, midIn, midOut);
//Tone map all the things. But, first start with exposure.
color *= EX;
#define EPS 1e-6f
float peak = max(color.r, max(color.g, color.b));
peak = max(EPS, peak);
float3 ratio = color / peak;
peak = ColTone(peak, float4(contrast, shoulder, b, c) );
// then process ratio
// probably want send these pre-computed (so send over saturation/crossSaturation as a constant)
float crosstalk = 4.0; // controls amount of channel crosstalk
float saturation = contrast * Saturate; // full tonal range saturation control
float crossSaturation = contrast*16.0; // crosstalk saturation
float white = WP;
// wrap crosstalk in transform
ratio = pow(abs(ratio), saturation / crossSaturation);
ratio = lerp(ratio, white, pow(peak, crosstalk));
ratio = pow(abs(ratio), crossSaturation);
// then apply ratio to peak
color = peak * ratio;
return color;
}
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
static const float3x3 ACESInputMat =
float3x3( float3(0.59719, 0.35458, 0.04823),
float3(0.07600, 0.90834, 0.01566),
float3(0.02840, 0.13383, 0.83777));
// ODT_SAT => XYZ => D60_2_D65 => sRGB
static const float3x3 ACESOutputMat =
float3x3( float3( 1.60475, -0.53108, -0.07367),
float3(-0.10208, 1.10813, -0.00605),
float3(-0.00327, -0.07276, 1.07602));
float3 RRTAndODTFit(float3 v)
{
float3 a = v * (v + 0.0245786f) - 0.000090537f;
float3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
return a / b;
}
float3 ACESFitted( float3 color, float EX)
{
color *= EX + 0.5; //Was told this need to be pre adjusted exposure.
color = mul(ACESInputMat,color);
color = RRTAndODTFit(color);
color = mul(ACESOutputMat,color);
return color/WP;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float4 SimpleBlur(sampler2D InputTex, float2 Coord, float2 pixelsize)
{
float4 Blur = 0.0;
static const float2 Offsets[4]=
{
float2(1.0, 1.0),
float2(1.0, -1.0),
float2(-1.0, 1.0),
float2(-1.0, -1.0)
};
for (int i = 0; i < 4; i++)
{
Blur += tex2D(InputTex, Coord + Offsets[i] * pixelsize);
}
return Blur * 0.25;
}
struct BloomData
{
float4 Blur;
float2 Pixelsize;
float2 Coord;
float Offset;
float Weight;
float WeightSum;
};
float2 GetPixelSize(float texsize)
{
return pix * texsize;//(1 / texsize) * float2(1, BUFFER_WIDTH / BUFFER_HEIGHT);
}
float3 Auto_Luma()
{
return float3(saturate(smoothstep(0,1,1-tex2D(SamplerTA,float2(0.25,0.25)).x)), //Top Left float2(0.25,0.25).x
tex2D(SamplerTA,float2(0.25,0.25)).x, //Top Left float2(0.25,0.25).x
saturate(smoothstep(0,1,tex2D(SamplerTA,float2(0.75,0.25)).x))); //Top Right float2(0.75,0.25).z
}
float3 Color_GS(float4 BC)
{ // Luma Threshold Thank you Adyss
float GS = Luma(BC.rgb), Saturate_A = Sat, Saturate_B = saturate(Saturation.y), AL = Auto_Luma().x;//Luma and more
// Gamma Curve
BC.rgb = pow(abs(BC.rgb), BloomSensitivity);
BC.rgb /= max(GS, 0.001);
BC.a = max(0.0, GS - CBT_Adjust);
BC.rgb *= BC.a;
//Bloom Saturation
if(Auto_Bloom == 2 || Auto_Bloom == 4) //Desaturate
Saturate_A *= lerp(0.0 + Saturate_B,1,AL);
if(Auto_Bloom == 3 || Auto_Bloom == 5) //Saturate
Saturate_A *= lerp(2.0 - Saturate_B,1,AL);
BC.rgb = lerp(BC.a, BC.rgb, min(10,Saturate_A));
return saturate(BC.rgb);
}
void PS_CurrentInfo(float4 pos : SV_Position, float2 texcoords : TEXCOORD, out float4 Color : SV_Target0)
{ //float2 D = Depth_Info(texcoords);
Color = float4(Color_GS(tex2D(BackBuffer, texcoords)), 0);
}
//Bloom Fuction from Adyss Bloom Wanted a version of your code to live on Miss you man.
float4 Bloom(float2 Coord, float texsize, sampler2D InputTex, int Dir)
{
BloomData Bloom;
Bloom.Pixelsize = GetPixelSize(texsize);
Bloom.Offset = Bloom_Spread * 0.5 ;
for (int i = 1; i < BloomSamples; i++)
{
float2 D = Dir ? float2(Bloom.Offset * Bloom.Pixelsize.x, 0) : float2( 0, Bloom.Offset * Bloom.Pixelsize.y);
Bloom.Weight = pow(abs(BloomSamples - i), BloomCurve);
Bloom.Blur += tex2Dlod(InputTex, float4(Coord + D ,0,0)) * Bloom.Weight;
Bloom.Blur += tex2Dlod(InputTex, float4(Coord - D ,0,0)) * Bloom.Weight;
Bloom.Offset += Bloom_Spread ;
Bloom.WeightSum += Bloom.Weight;
}
return Bloom.Blur /= Bloom.WeightSum * 2;
}
float4 PS_BloomH_A(float4 pos : SV_Position, float2 Coord : TEXCOORD) : SV_Target
{ //Prepass
return Bloom(Coord, 2, SamplerCurrBB, 1);
}
float4 PS_BloomV_A(float4 pos : SV_Position, float2 Coord : TEXCOORD) : SV_Target
{
return Bloom(Coord, 2, TextureBloomH_A, 0);
}
float4 PS_BloomH_B(float4 pos : SV_Position, float2 Coord : TEXCOORD) : SV_Target
{
return Bloom(Coord, 8, TextureBloomV_A, 1);
}
float4 PS_BloomV_B(float4 pos : SV_Position, float2 Coord : TEXCOORD) : SV_Target
{
return Bloom(Coord, 8, TextureBloomH_B, 0);
}
float4 PS_BloomH_C(float4 pos : SV_Position, float2 Coord : TEXCOORD) : SV_Target
{
return Bloom(Coord, 16, TextureBloomV_B, 1);
}
float4 PS_BloomV_C(float4 pos : SV_Position, float2 Coord : TEXCOORD) : SV_Target
{
return Bloom(Coord, 16, TextureBloomH_C, 0);
}
float4 Final_Bloom(float4 pos : SV_Position, float2 texcoords : TEXCOORD) : SV_Target
{
float3 LP = tex2D(BackBuffer, texcoords).rgb;
float4 Bloom = SimpleBlur(TextureBloomH_A, texcoords, GetPixelSize(2)).rgba;
Bloom += SimpleBlur(TextureBloomV_A, texcoords, GetPixelSize(2)).rgba;
Bloom += SimpleBlur(TextureBloomH_B, texcoords, GetPixelSize(4)).rgba;
Bloom += SimpleBlur(TextureBloomV_B, texcoords, GetPixelSize(4)).rgba;
Bloom += SimpleBlur(TextureBloomH_C, texcoords, GetPixelSize(8)).rgba;
Bloom += SimpleBlur(TextureBloomV_C, texcoords, GetPixelSize(8)).rgba;
Bloom *= lerp(0,10,Bloom_Intensity.x) / 6; // Luma Preserving Blending Not used........
return float4(lerp(Bloom.rgb, max(Bloom.rgb - LP, 0.0), 0),0);
}
float3 Green_Blue( float interpolant )
{
if( interpolant < 0.5 )
return float3(0.0, 1.0, 2.0 * interpolant);
else
return float3(0.0, 2.0 - 2.0 * interpolant, 1.0 );
}
float3 Red_Green( float interpolant )
{
if( interpolant < 0.5 )
return float3(1.0, 2.0 * interpolant, 0.0);
else
return float3(2.0 - 2.0 * interpolant, 1.0, 0.0 );
}
float3 FHeat( float interpolant )
{
float invertedInterpolant = interpolant;
if( invertedInterpolant < 0.5 )
{
float remappedFirstHalf = 1.0 - 2.0 * invertedInterpolant;
return Green_Blue( remappedFirstHalf );
}
else
{
float remappedSecondHalf = 2.0 - 2.0 * invertedInterpolant;
return Red_Green( remappedSecondHalf );
}
}
float3 HeatMap( float interpolant )
{
if( interpolant < 1.0 / 6.0 )
{
float firstSegmentInterpolant = 6.0 * interpolant;
return ( 1.0 - firstSegmentInterpolant ) * float3(0.0, 0.0, 0.0) + firstSegmentInterpolant * float3(0.0, 0.0, 1.0);
}
else if( interpolant < 5.0 / 6.0 )
{
float midInterpolant = 0.25 * ( 6.0 * interpolant - 1.0 );
return FHeat( midInterpolant );
}
else
{
float lastSegmentInterpolant = 6.0 * interpolant - 5.0;
return ( 1.0 - lastSegmentInterpolant ) * float3(1.0, 0.0, 0.0) + lastSegmentInterpolant * float3(1.0, 1.0, 1.0);
}
}
float Scale(float val,float max,float min) //Scale to 0 - 1
{
return (val - min) / (max - min);
}
void GN(inout float Noise,float2 TC,float seed)
{
Noise = frac(tan(distance(TC*((seed+10)+PHI), float2(PHI, PI)))*SQ2);
}
float4 HDROut(float2 texcoords)
{ float4 Out, Bloom = SimpleBlur(TextureBloom, texcoords, GetPixelSize(1)).rgba;
float2 TC = 10 * texcoords.xy - 5;
float AL = Auto_Luma().y, Ex;
if(Auto_Exposure >= 1)
Ex = Exp;
else
Ex = lerp(0,2.5,Scale(Exp, 4, -4));
float NC = Bloom_Intensity.y;//BI_Brightness = lerp(1,0.01,Bloom_Intensity.y)
if(Auto_Bloom == 1 || Auto_Bloom == 4 || Auto_Bloom == 5)
NC *= max(0.25,Auto_Luma().x);
float3 Noise, iFast, iReinhard, iReinhardLuma, Color = tex2D(BackBuffer, texcoords).rgb;
// Goldern Noise RGB Dither
GN( Noise.r, TC, 1 );
GN( Noise.g, TC, 2 );
GN( Noise.b, TC, 3 );
float3 SS = smoothstep( 0.0, 0.1, Bloom.rgb );
SS *= lerp(0.0,0.1,saturate(Dither_Bloom));
Bloom.rgb = saturate( Bloom.rgb + Noise * SS );
//Bloom should be applied before Tonemapping as otherwise all high ranges will be lost. Also can used as "resolve." But, I allow for both.
Bloom.rgb = lerp( 0.0, Bloom.rgb, saturate(NC));
//Bloom_B = lerp( 0.0, (( Bloom.rgb - 0 ) / ( BI_Brightness - 0)), saturate(NC));
//Bloom.rgb = lerp(Bloom_A,Bloom_B,Bloom.w);
if(Tonemappers >= 1)
Color = lerp(Luma(Color),Color,Saturate);
// Do inital de-gamma of the game image to ensure we're operating in the correct colour range.
if( Gamma > 1. )
Color = pow(abs(Color),Gamma);
//Bloom Befor Inverse ToneMapper
if(!Bloom_BA_iToneMapper)
Color += Bloom.rgb;
//Evil bad Negitive colors be gone by the wind of dev....
Color = max(0,Color);
//HDR Map
if(Inv_Tonemappers == 1)
Color = inv_Tonemapper(float4(Color,1-HDR_BP), 0);
else if(Inv_Tonemappers == 2)
Color = inv_Tonemapper(float4(Color,1-HDR_BP), 2);
else if(Inv_Tonemappers == 3)
Color = inv_Tonemapper(float4(Color,1-HDR_BP), 1);
//Bloom After Inverse ToneMapper
if (Bloom_BA_iToneMapper)
Color += Bloom.rgb;
//Tone map all the things
if(Auto_Exposure >= 1)
Ex = CalcExposedColor(AL,Ex,GreyValue);
else //Using the optimized tonemapper by Jim Hejl and Richard Burgess-Dawson 0.148 for the GreyValue works for me. https://imgflip.com/i/oos2z But, I will alow for this to be adjusted.
Ex = Ex;
if(Tonemappers == 0)
Color = TimothyTonemapper(Color,Ex);
else if (Tonemappers == 1)
Color = ACESFitted(Color,Ex);
//removed for now because of bug.
#if Flare_A
//Color += tex2D(SamplerFlare, texcoords).rgb;
#endif
#if Flare_B
//Color += tex2D(SamplerLensFlare, texcoords).rgb;
#endif
#if HDR_Toggle
// Do ST2084 curve
Color = ApplyPQ(Color);
#else
// Do the post-tonemapping gamma correction
if( Gamma > 1. )
Color = pow(abs(Color),rcp(2.2));
#endif
//float2 D = Depth_Info(texcoords);
float MD = 0;
if(Tonemappers >= 1)
Color = (Color - 0.5) * (Contrast) + 0.5;
if (Debug_View == 0)
Out = float4(Color, 1.);
else if(Debug_View == 1)
Out = Bloom;
else if(Debug_View == 2)
Out = texcoords.y < 0.975 ? HeatMap(Luma( Color )): HeatMap(texcoords.x);
//else
//Out = lerp(D.y,float3(D.y,0.5,D.y),MD) ;
//May need to dither.......
texcoords.x = texcoords.x * 0.75 + 0.125;//* 0.5 + 0.25;
texcoords *= 1.0 - float2(texcoords.x,texcoords.y);
float vignette = texcoords.x * texcoords.y * 15.0, Mfactor = pow(smoothstep(0,1,vignette), Auto_Luma().y * 2.0);
if(Auto_Exposure > 1)
vignette = lerp(1,lerp(0,1,saturate(Mfactor)),Auto_Luma().z);
else
vignette = 1;
return float4(Out.rgb * vignette,1.0);
}
float PS_StoreInfo(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D(SamplerTA,texcoord).x;
}
////////////////////////////////////////////////////////Logo/////////////////////////////////////////////////////////////////////////
float4 Out(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float PosX = 0.9525f*BUFFER_WIDTH*pix.x,PosY = 0.975f*BUFFER_HEIGHT*pix.y;
float3 Color = HDROut(texcoord).rgb;
return float4(Color,1.0);
}
///////////////////////////////////////////////////////////ReShade.fxh/////////////////////////////////////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
//*Rendering passes*//
technique Blooming_HDR
{
pass Store_Info
{
VertexShader = PostProcessVS;
PixelShader = PS_StoreInfo;
RenderTarget = texStored;
}
pass Current_Info
{
VertexShader = PostProcessVS;
PixelShader = PS_CurrentInfo;
RenderTarget0 = texCurrColor;
}
pass BloomH_A
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomH_A;
RenderTarget = BloomTexH_A;
}
pass BloomV_A
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomV_A;
RenderTarget = BloomTexV_A;
}
pass BloomV_B
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomH_B;
RenderTarget = BloomTexH_B;
}
pass BloomV_B
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomV_B;
RenderTarget = BloomTexV_B;
}
pass BloomV_C
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomH_C;
RenderTarget = BloomTexH_C;
}
pass BloomV_C
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomV_C;
RenderTarget = BloomTexV_C;
}
pass Bloom
{
VertexShader = PostProcessVS;
PixelShader = Final_Bloom;
RenderTarget = BloomTex;
}
pass Downsampler
{
VertexShader = PostProcessVS;
PixelShader = Downsample;
RenderTarget = texDS;
}
pass Temporal_Adaptation
{
VertexShader = PostProcessVS;
PixelShader = PS_Temporal_Adaptation;
RenderTarget = texTA;
}
pass HDROut
{
VertexShader = PostProcessVS;
PixelShader = Out;
#if SRGB
SRGBWriteEnable = true;
#endif
}
}

View File

@ -0,0 +1,73 @@
/**
* Border version 1.4.1
*
* -- Version 1.0 by Oomek --
* Fixes light, one pixel thick border in some games when forcing MSAA like i.e. Dishonored
* -- Version 1.1 by CeeJay.dk --
* Optimized the shader. It still does the same but now it runs faster.
* -- Version 1.2 by CeeJay.dk --
* Added border_width and border_color features
* -- Version 1.3 by CeeJay.dk --
* Optimized the performance further
* -- Version 1.4 by CeeJay.dk --
* Added the border_ratio feature
* -- Version 1.4.1 by CeeJay.dk --
* Cleaned up setting for Reshade 3.x
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
/*
uniform float2 border_width <
ui_type = "input";
ui_label = "Size";
ui_tooltip = "Measured in pixels. If this is set to zero then the ratio will be used instead.";
> = float2(0.0, 0.0);
*/
uniform float2 border_width <
ui_type = "drag";
ui_label = "Size";
ui_tooltip = "Measured in pixels. If this is set to zero then the ratio will be used instead.";
ui_min = 0.0; ui_max = (BUFFER_WIDTH * 0.5);
ui_step = 1.0;
> = float2(0.0, 0.0);
uniform float border_ratio <
ui_type = "input";
ui_label = "Size Ratio";
ui_tooltip = "Set the desired ratio for the visible area.";
> = 2.35;
uniform float3 border_color <
ui_type = "color";
ui_label = "Border Color";
> = float3(0.0, 0.0, 0.0);
float3 BorderPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
// -- calculate the right border_width for a given border_ratio --
float2 border_width_variable = border_width;
if (border_width.x == -border_width.y) // If width is not used
if (BUFFER_ASPECT_RATIO < border_ratio)
border_width_variable = float2(0.0, (BUFFER_HEIGHT - (BUFFER_WIDTH / border_ratio)) * 0.5);
else
border_width_variable = float2((BUFFER_WIDTH - (BUFFER_HEIGHT * border_ratio)) * 0.5, 0.0);
float2 border = (BUFFER_PIXEL_SIZE * border_width_variable); // Translate integer pixel width to floating point
float2 within_border = saturate((-texcoord * texcoord + texcoord) - (-border * border + border)); // Becomes positive when inside the border and zero when outside
return all(within_border) ? color : border_color;
}
technique Border
{
pass
{
VertexShader = PostProcessVS;
PixelShader = BorderPass;
}
}

View File

@ -0,0 +1,178 @@
// LICENSE
// =======
// Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved.
// -------
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// -------
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
// Software.
// -------
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
//Initial port to ReShade: SLSNe https://gist.github.com/SLSNe/bbaf2d77db0b2a2a0755df581b3cf00c
//Optimizations by Marty McFly:
// vectorized math, even with scalar gcn hardware this should work
// out the same, order of operations has not changed
// For some reason, it went from 64 to 48 instructions, a lot of MOV gone
// Also modified the way the final window is calculated
//
// reordered min() and max() operations, from 11 down to 9 registers
//
// restructured final weighting, 49 -> 48 instructions
//
// delayed RCP to replace SQRT with RSQRT
//
// removed the saturate() from the control var as it is clamped
// by UI manager already, 48 -> 47 instructions
//
// replaced tex2D with tex2Doffset intrinsic (address offset by immediate integer)
// 47 -> 43 instructions
// 9 -> 8 registers
//Further modified by OopyDoopy and Lord of Lunacy:
// Changed wording in the UI for the existing variable and added a new variable and relevant code to adjust sharpening strength.
//Fix by Lord of Lunacy:
// Made the shader use a linear colorspace rather than sRGB, as recommended by the original AMD documentation from FidelityFX.
//Modified by CeeJay.dk:
// Included a label and tooltip description. I followed AMDs official naming guidelines for FidelityFX.
//
// Used gather trick to reduce the number of texture operations by one (9 -> 8). It's now 42 -> 51 instructions but still faster
// because of the texture operation that was optimized away.
//Fix by CeeJay.dk
// Fixed precision issues with the gather at super high resolutions
// Also tried to refactor the samples so more work can be done while they are being sampled, but it's not so easy and the gains
// I'm seeing are so small they might be statistical noise. So it MIGHT be faster - no promises.
uniform float Contrast <
ui_type = "drag";
ui_label = "Contrast Adaptation";
ui_tooltip = "Adjusts the range the shader adapts to high contrast (0 is not all the way off). Higher values = more high contrast sharpening.";
ui_min = 0.0; ui_max = 1.0;
> = 0.0;
uniform float Sharpening <
ui_type = "drag";
ui_label = "Sharpening intensity";
ui_tooltip = "Adjusts sharpening intensity by averaging the original pixels to the sharpened result. 1.0 is the unmodified default.";
ui_min = 0.0; ui_max = 1.0;
> = 1.0;
#include "ReShade.fxh"
#define pixel float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
texture TexColor : COLOR;
sampler sTexColor {Texture = TexColor; SRGBTexture = true;};
float3 CASPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
// fetch a 3x3 neighborhood around the pixel 'e',
// a b c
// d(e)f
// g h i
float3 b = tex2Doffset(sTexColor, texcoord, int2(0, -1)).rgb;
float3 d = tex2Doffset(sTexColor, texcoord, int2(-1, 0)).rgb;
#if __RENDERER__ >= 0xa000 // If DX10 or higher
float4 red_efhi = tex2DgatherR(sTexColor, texcoord + 0.5 * pixel);
float3 e = float3( red_efhi.w, red_efhi.w, red_efhi.w);
float3 f = float3( red_efhi.z, red_efhi.z, red_efhi.z);
float3 h = float3( red_efhi.x, red_efhi.x, red_efhi.x);
float3 i = float3( red_efhi.y, red_efhi.y, red_efhi.y);
float4 green_efhi = tex2DgatherG(sTexColor, texcoord + 0.5 * pixel);
e.g = green_efhi.w;
f.g = green_efhi.z;
h.g = green_efhi.x;
i.g = green_efhi.y;
float4 blue_efhi = tex2DgatherB(sTexColor, texcoord + 0.5 * pixel);
e.b = blue_efhi.w;
f.b = blue_efhi.z;
h.b = blue_efhi.x;
i.b = blue_efhi.y;
#else // If DX9
float3 e = tex2D(sTexColor, texcoord).rgb;
float3 f = tex2Doffset(sTexColor, texcoord, int2(1, 0)).rgb;
float3 h = tex2Doffset(sTexColor, texcoord, int2(0, 1)).rgb;
float3 i = tex2Doffset(sTexColor, texcoord, int2(1, 1)).rgb;
#endif
float3 g = tex2Doffset(sTexColor, texcoord, int2(-1, 1)).rgb;
float3 a = tex2Doffset(sTexColor, texcoord, int2(-1, -1)).rgb;
float3 c = tex2Doffset(sTexColor, texcoord, int2(1, -1)).rgb;
// Soft min and max.
// a b c b
// d e f * 0.5 + d e f * 0.5
// g h i h
// These are 2.0x bigger (factored out the extra multiply).
float3 mnRGB = min(min(min(d, e), min(f, b)), h);
float3 mnRGB2 = min(mnRGB, min(min(a, c), min(g, i)));
mnRGB += mnRGB2;
float3 mxRGB = max(max(max(d, e), max(f, b)), h);
float3 mxRGB2 = max(mxRGB, max(max(a, c), max(g, i)));
mxRGB += mxRGB2;
// Smooth minimum distance to signal limit divided by smooth max.
float3 rcpMRGB = rcp(mxRGB);
float3 ampRGB = saturate(min(mnRGB, 2.0 - mxRGB) * rcpMRGB);
// Shaping amount of sharpening.
ampRGB = rsqrt(ampRGB);
float peak = -3.0 * Contrast + 8.0;
float3 wRGB = -rcp(ampRGB * peak);
float3 rcpWeightRGB = rcp(4.0 * wRGB + 1.0);
// 0 w 0
// Filter shape: w 1 w
// 0 w 0
float3 window = (b + d) + (f + h);
float3 outColor = saturate((window * wRGB + e) * rcpWeightRGB);
return lerp(e, outColor, Sharpening);
}
technique ContrastAdaptiveSharpen
<
ui_label = "AMD FidelityFX Contrast Adaptive Sharpening";
ui_tooltip =
"CAS is a low overhead adaptive sharpening algorithm that AMD includes with their drivers.\n"
"This port to Reshade works with all cards from all vendors,\n"
"but cannot do the optional scaling that CAS is normally also capable of when activated in the AMD drivers.\n"
"\n"
"The algorithm adjusts the amount of sharpening per pixel to target an even level of sharpness across the image.\n"
"Areas of the input image that are already sharp are sharpened less, while areas that lack detail are sharpened more.\n"
"This allows for higher overall natural visual sharpness with fewer artifacts.";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = CASPass;
SRGBWriteEnable = true;
}
}

View File

@ -0,0 +1,312 @@
// CRT shader
//
// Copyright (C) 2010-2012 cgwg, Themaister and DOLLS
//
// 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 2 of the License, or (at your option)
// any later version.
// Comment the next line to disable interpolation in linear gamma (and gain speed).
//#define LINEAR_PROCESSING
#include "ReShadeUI.fxh"
uniform float Amount < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Amount of CRT effect you want";
> = 1.00;
uniform float Resolution < __UNIFORM_SLIDER_FLOAT1
ui_min = 1.0; ui_max = 8.0;
ui_tooltip = "Input size coefficient (low values gives the 'low - res retro look').";
> = 1.15;
uniform float Gamma < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 4.0;
ui_tooltip = "Gamma of simulated CRT";
> = 2.4;
uniform float MonitorGamma < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 4.0;
ui_tooltip = "Gamma of display monitor";
> = 2.2;
uniform float Brightness < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 3.0;
ui_tooltip = "Used to boost brightness a little.";
> = 0.9;
uniform int ScanlineIntensity < __UNIFORM_SLIDER_INT1
ui_min = 2; ui_max = 4;
ui_label = "Scanline Intensity";
> = 2;
uniform bool ScanlineGaussian <
ui_label = "Scanline Bloom Effect";
ui_tooltip = "Use the new nongaussian scanlines bloom effect.";
> = true;
uniform bool Curvature <
ui_tooltip = "Barrel effect";
> = false;
uniform float CurvatureRadius < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 2.0;
ui_label = "Curvature Radius";
> = 1.5;
uniform float CornerSize < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.00; ui_max = 0.02; ui_step = 0.001;
ui_label = "Corner Size";
ui_tooltip = "Higher values => more rounded corner";
> = 0.0100;
uniform float ViewerDistance < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 4.0;
ui_Label = "Viewer Distance";
ui_tooltip = "Simulated distance from viewer to monitor";
> = 2.00;
uniform float2 Angle < __UNIFORM_SLIDER_FLOAT2
ui_min = -0.2; ui_max = 0.2;
ui_tooltip = "Tilt angle in radians";
> = 0.00;
uniform float Overscan < __UNIFORM_SLIDER_FLOAT1
ui_min = 1.0; ui_max = 1.10; ui_step = 0.01;
ui_tooltip = "Overscan (e.g. 1.02 for 2% overscan).";
> = 1.01;
uniform bool Oversample <
ui_tooltip = "Enable 3x oversampling of the beam profile (warning : performance hit)";
> = true;
#include "ReShade.fxh"
#define CeeJay_aspect float2(1.0, 0.75)
// A bunch of useful values we'll need in the fragment shader.
#define sinangle sin(Angle)
#define cosangle cos(Angle)
#define stretch maxscale()
// Macros.
#define FIX(c) max(abs(c), 1e-5);
#ifndef PI
#define PI 3.1415927
#endif
// The size of one texel, in texture-coordinates.
#define coone 1.0 / rubyTextureSize
#define mod_factor tex.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x
#ifdef LINEAR_PROCESSING
#define TEX2D(c) pow(tex2D(ReShade::BackBuffer, (c)), Gamma)
#else
#define TEX2D(c) tex2D(ReShade::BackBuffer, (c))
#endif
float intersect(float2 xy)
{
float A = dot(xy,xy) + (ViewerDistance * ViewerDistance);
float B = 2.0 * (CurvatureRadius * (dot(xy, sinangle) - ViewerDistance * cosangle.x * cosangle.y) - ViewerDistance * ViewerDistance);
float C = ViewerDistance * ViewerDistance + 2.0 * CurvatureRadius * ViewerDistance * cosangle.x * cosangle.y; //all constants
return (-B - sqrt(B * B -4.0 * A * C)) / (2.0 * A);
}
float2 bkwtrans(float2 xy)
{
float c = intersect(xy);
float2 _point = float2(c, c) * xy;
_point -= float2(-CurvatureRadius, -CurvatureRadius) * sinangle;
_point /= float2(CurvatureRadius, CurvatureRadius);
float2 tang = sinangle / cosangle;
float2 poc = _point / cosangle;
float A = dot(tang, tang) + 1.0;
float B = -2.0 * dot(poc, tang);
float C = dot(poc, poc) - 1.0;
float a = (-B + sqrt(B * B -4.0 * A * C)) / (2.0 * A);
float2 uv = (_point - a * sinangle) / cosangle;
float r = CurvatureRadius * acos(a);
return uv * r / sin(r / CurvatureRadius);
}
float2 fwtrans(float2 uv)
{
float r = FIX(sqrt(dot(uv, uv)));
uv *= sin(r / CurvatureRadius) / r;
float x = 1.0 - cos(r / CurvatureRadius);
float D = ViewerDistance / CurvatureRadius + x * cosangle.x * cosangle.y + dot(uv, sinangle);
return ViewerDistance * (uv * cosangle - x * sinangle) / D;
}
float3 maxscale()
{
float2 c = bkwtrans(-CurvatureRadius * sinangle / (1.0 + CurvatureRadius / ViewerDistance * cosangle.x * cosangle.y));
float2 a = float2(0.5, 0.5) * CeeJay_aspect;
float2 lo = float2(fwtrans(float2(-a.x, c.y)).x, fwtrans(float2(c.x,-a.y)).y) / CeeJay_aspect;
float2 hi = float2(fwtrans(float2(+a.x, c.y)).x, fwtrans(float2(c.x, +a.y)).y) / CeeJay_aspect;
return float3((hi + lo) * CeeJay_aspect * 0.5, max(hi.x - lo.x, hi.y - lo.y));
}
float2 transform(float2 coord, float2 textureSize, float2 inputSize)
{
coord *= textureSize / inputSize;
coord = (coord - 0.5) * CeeJay_aspect * stretch.z + stretch.xy;
return (bkwtrans(coord) / float2(Overscan, Overscan) / CeeJay_aspect + 0.5) * inputSize / textureSize;
}
float corner(float2 coord, float2 textureSize, float2 inputSize)
{
coord *= textureSize / inputSize;
coord = (coord - 0.5) * float2(Overscan, Overscan) + 0.5;
coord = min(coord, 1.0 - coord) * CeeJay_aspect;
float2 cdist = float2(CornerSize, CornerSize);
coord = (cdist - min(coord, cdist));
float dist = sqrt(dot(coord, coord));
return clamp((cdist.x-dist) * 1000.0, 0.0, 1.0);
}
// Calculate the influence of a scanline on the current pixel.
//
// 'distance' is the distance in texture coordinates from the current
// pixel to the scanline in question.
// 'color' is the colour of the scanline at the horizontal location of
// the current pixel.
float4 scanlineWeights(float distance, float4 color)
{
// "wid" controls the width of the scanline beam, for each RGB channel
// The "weights" lines basically specify the formula that gives
// you the profile of the beam, i.e. the intensity as
// a function of distance from the vertical center of the
// scanline. In this case, it is gaussian if width=2, and
// becomes nongaussian for larger widths. Ideally this should
// be normalized so that the integral across the beam is
// independent of its width. That is, for a narrower beam
// "weights" should have a higher peak at the center of the
// scanline than for a wider beam.
if (!ScanlineGaussian)
{
float4 wid = 0.3 + 0.1 * pow(abs(color), 3.0);
float4 weights = float4(distance / wid);
return 0.4 * exp(-weights * weights) / wid;
}
else
{
float4 wid = 2.0 * pow(abs(color), 4.0) + 2.0;
float4 weights = (distance / 0.3).xxxx;
return 1.4 * exp(-pow(abs(weights * rsqrt(0.5 * wid)), abs(wid))) / (0.2 * wid + 0.6);
}
}
float3 AdvancedCRTPass(float4 position : SV_Position, float2 tex : TEXCOORD) : SV_Target
{
// Here's a helpful diagram to keep in mind while trying to
// understand the code:
//
// | | | | |
// -------------------------------
// | | | | |
// | 01 | 11 | 21 | 31 | <-- current scanline
// | | @ | | |
// -------------------------------
// | | | | |
// | 02 | 12 | 22 | 32 | <-- next scanline
// | | | | |
// -------------------------------
// | | | | |
//
// Each character-cell represents a pixel on the output
// surface, "@" represents the current pixel (always somewhere
// in the bottom half of the current scan-line, or the top-half
// of the next scanline). The grid of lines represents the
// edges of the texels of the underlying texture.
float Input_ratio = ceil(256 * Resolution);
float2 Resolution = float2(Input_ratio, Input_ratio);
float2 rubyTextureSize = Resolution;
float2 rubyInputSize = Resolution;
float2 rubyOutputSize = BUFFER_SCREEN_SIZE;
float2 orig_xy = Curvature ? transform(tex, rubyTextureSize, rubyInputSize) : tex;
float cval = corner(orig_xy, rubyTextureSize, rubyInputSize);
// Of all the pixels that are mapped onto the texel we are
// currently rendering, which pixel are we currently rendering?
float2 ratio_scale = orig_xy * rubyTextureSize - 0.5;
float filter = fwidth(ratio_scale.y);
float2 uv_ratio = frac(ratio_scale);
// Snap to the center of the underlying texel.
float2 xy = (floor(ratio_scale) + 0.5) / rubyTextureSize;
// Calculate Lanczos scaling coefficients describing the effect
// of various neighbour texels in a scanline on the current
// pixel.
float4 coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
// Prevent division by zero.
coeffs = FIX(coeffs);
// Lanczos2 kernel.
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
// Normalize.
coeffs /= dot(coeffs, 1.0);
// Calculate the effective colour of the current and next
// scanlines at the horizontal location of the current pixel,
// using the Lanczos coefficients above.
float4 col = clamp(mul(coeffs, float4x4(
TEX2D(xy + float2(-coone.x, 0.0)),
TEX2D(xy),
TEX2D(xy + float2(coone.x, 0.0)),
TEX2D(xy + float2(2.0 * coone.x, 0.0)))),
0.0, 1.0);
float4 col2 = clamp(mul(coeffs, float4x4(
TEX2D(xy + float2(-coone.x, coone.y)),
TEX2D(xy + float2(0.0, coone.y)),
TEX2D(xy + coone),
TEX2D(xy + float2(2.0 * coone.x, coone.y)))),
0.0, 1.0);
#ifndef LINEAR_PROCESSING
col = pow(abs(col) , Gamma);
col2 = pow(abs(col2), Gamma);
#endif
// Calculate the influence of the current and next scanlines on
// the current pixel.
float4 weights = scanlineWeights(uv_ratio.y, col);
float4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
#if __RENDERER__ < 0xa000 && !__RESHADE_PERFORMANCE_MODE__
[flatten]
#endif
if (Oversample)
{
uv_ratio.y = uv_ratio.y + 1.0 / 3.0 * filter;
weights = (weights + scanlineWeights(uv_ratio.y, col)) / 3.0;
weights2 = (weights2 + scanlineWeights(abs(1.0 - uv_ratio.y), col2)) / 3.0;
uv_ratio.y = uv_ratio.y - 2.0 / 3.0 * filter;
weights = weights + scanlineWeights(abs(uv_ratio.y), col) / 3.0;
weights2 = weights2 + scanlineWeights(abs(1.0 - uv_ratio.y), col2) / 3.0;
}
float3 mul_res = (col * weights + col2 * weights2).rgb * cval.xxx;
// dot-mask emulation:
// Output pixels are alternately tinted green and magenta.
float3 dotMaskWeights = lerp(float3(1.0, 0.7, 1.0), float3(0.7, 1.0, 0.7), floor(mod_factor % ScanlineIntensity));
mul_res *= dotMaskWeights * float3(0.83, 0.83, 1.0) * Brightness;
// Convert the image gamma for display on our output device.
mul_res = pow(abs(mul_res), 1.0 / MonitorGamma);
float3 color = TEX2D(orig_xy).rgb * cval.xxx;
color = lerp(color, mul_res, Amount);
return saturate(color);
}
technique AdvancedCRT
{
pass
{
VertexShader = PostProcessVS;
PixelShader = AdvancedCRTPass;
}
}

View File

@ -0,0 +1,42 @@
/**
* Cartoon
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*/
#include "ReShadeUI.fxh"
uniform float Power < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.1; ui_max = 10.0;
ui_tooltip = "Amount of effect you want.";
> = 1.5;
uniform float EdgeSlope < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.1; ui_max = 6.0;
ui_label = "Edge Slope";
ui_tooltip = "Raise this to filter out fainter edges. You might need to increase the power to compensate. Whole numbers are faster.";
> = 1.5;
#include "ReShade.fxh"
float3 CartoonPass(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
const float3 coefLuma = float3(0.2126, 0.7152, 0.0722);
float diff1 = dot(coefLuma, tex2D(ReShade::BackBuffer, texcoord + BUFFER_PIXEL_SIZE).rgb);
diff1 = dot(float4(coefLuma, -1.0), float4(tex2D(ReShade::BackBuffer, texcoord - BUFFER_PIXEL_SIZE).rgb , diff1));
float diff2 = dot(coefLuma, tex2D(ReShade::BackBuffer, texcoord + BUFFER_PIXEL_SIZE * float2(1, -1)).rgb);
diff2 = dot(float4(coefLuma, -1.0), float4(tex2D(ReShade::BackBuffer, texcoord + BUFFER_PIXEL_SIZE * float2(-1, 1)).rgb , diff2));
float edge = dot(float2(diff1, diff2), float2(diff1, diff2));
return saturate(pow(abs(edge), EdgeSlope) * -Power + color);
}
technique Cartoon
{
pass
{
VertexShader = PostProcessVS;
PixelShader = CartoonPass;
}
}

View File

@ -0,0 +1,39 @@
/**
* Chromatic Aberration
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Distorts the image by shifting each color component, which creates color artifacts similar to those in a very cheap lens or a cheap sensor.
*/
#include "ReShadeUI.fxh"
uniform float2 Shift < __UNIFORM_SLIDER_FLOAT2
ui_min = -10; ui_max = 10;
ui_tooltip = "Distance (X,Y) in pixels to shift the color components. For a slightly blurred look try fractional values (.5) between two pixels.";
> = float2(2.5, -0.5);
uniform float Strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
> = 0.5;
#include "ReShade.fxh"
float3 ChromaticAberrationPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color, colorInput = tex2D(ReShade::BackBuffer, texcoord).rgb;
// Sample the color components
color.r = tex2D(ReShade::BackBuffer, texcoord + (BUFFER_PIXEL_SIZE * Shift)).r;
color.g = colorInput.g;
color.b = tex2D(ReShade::BackBuffer, texcoord - (BUFFER_PIXEL_SIZE * Shift)).b;
// Adjust the strength of the effect
return lerp(colorInput, color, Strength);
}
technique CA
{
pass
{
VertexShader = PostProcessVS;
PixelShader = ChromaticAberrationPass;
}
}

View File

@ -0,0 +1,553 @@
//Clarity by Ioxa
//Version 1.5 for ReShade 3.0
//>Clarity Settings<\\
//#include "ReShadeUI.fxh" Removed when porting over to Astray.fx Repo.
//Notes:
//The goal here is port and store this shader since the main repo is going away.
//I am taking over a few shaders I feel should be saved and don't have textures.
//The rest of the shaders will be moved to a other repo. That Ceejay.dk tells me.
//Any changes done to the shaders for now will be for compatablity. Other then that,
//I don't see any licenceing so I am worried about this since here is no due diligence.
//Anyways I think it should be fine and thank you Ioxa for a shader staple in ReShade.
//Also to anyone else if you see issues in the shader please report them to the AtrayFX repo.
//Thank you.
uniform int ClarityRadius
< ui_type = "slider";
ui_min = 0; ui_max = 4;
ui_tooltip = "[0|1|2|3|4] Higher values will increase the radius of the effect.";
ui_step = 1.00;
> = 3;
uniform float ClarityOffset
< ui_type = "slider";
ui_min = 1.00; ui_max = 5.00;
ui_tooltip = "Additional adjustment for the blur radius. Increasing the value will increase the radius.";
ui_step = 1.00;
> = 2.00;
uniform int ClarityBlendMode
<
ui_type = "combo";
ui_items = "\Soft Light\0Overlay\0Hard Light\0Multiply\0Vivid Light\0Linear Light\0Addition";
ui_tooltip = "Blend modes determine how the clarity mask is applied to the original image";
> = 2;
uniform int ClarityBlendIfDark
< ui_type = "slider";
ui_min = 0; ui_max = 255;
ui_tooltip = "Any pixels below this value will be excluded from the effect. Set to 50 to target mid-tones.";
ui_step = 5;
> = 50;
uniform int ClarityBlendIfLight
< ui_type = "slider";
ui_min = 0; ui_max = 255;
ui_tooltip = "Any pixels above this value will be excluded from the effect. Set to 205 to target mid-tones.";
ui_step = 5;
> = 205;
uniform bool ClarityViewBlendIfMask
<
ui_tooltip = "The mask used for BlendIf settings. The effect will not be applied to areas covered in black";
> = false;
uniform float ClarityStrength
< ui_type = "slider";
ui_min = 0.00; ui_max = 1.00;
ui_tooltip = "Adjusts the strength of the effect";
> = 0.400;
uniform float ClarityDarkIntensity
< ui_type = "slider";
ui_min = 0.00; ui_max = 1.00;
ui_tooltip = "Adjusts the strength of dark halos.";
> = 0.400;
uniform float ClarityLightIntensity
< ui_type = "slider";
ui_min = 0.00; ui_max = 1.00;
ui_tooltip = "Adjusts the strength of light halos.";
> = 0.000;
uniform bool ClarityViewMask
<
ui_tooltip = "The mask is what creates the effect. View it when making adjustments to get a better idea of how your changes will affect the image.";
> = false;
//#include "ReShade.fxh" //Devorced from this header file.
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
texture BackBufferTex : COLOR;
sampler BackBuffer { Texture = BackBufferTex; };
texture ClarityTex < pooled = true; > { Width = BUFFER_WIDTH * 0.5; Height = BUFFER_HEIGHT * 0.5; Format = R8; };
texture ClarityTex2 { Width = BUFFER_WIDTH * 0.5; Height = BUFFER_HEIGHT * 0.5; Format = R8; };
texture ClarityTex3 < pooled = true; > { Width = BUFFER_WIDTH * 0.25; Height = BUFFER_HEIGHT * 0.25; Format = R8; };
sampler ClaritySampler { Texture = ClarityTex;};
sampler ClaritySampler2 { Texture = ClarityTex2;};
sampler ClaritySampler3 { Texture = ClarityTex3;};
float3 ClarityFinal(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
float color = tex2Dlod(ClaritySampler3, float4(texcoord,0,1)).r;
if(ClarityRadius == 0)
{
float offset[4] = { 0.0, 1.1824255238, 3.0293122308, 5.0040701377 };
float weight[4] = { 0.39894, 0.2959599993, 0.0045656525, 0.00000149278686458842 };
color *= weight[0];
[loop]
for(int i = 1; i < 4; ++i)
{
color += tex2Dlod(ClaritySampler3, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
color += tex2Dlod(ClaritySampler3, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
}
}
if(ClarityRadius == 1)
{
float offset[6] = { 0.0, 1.4584295168, 3.40398480678, 5.3518057801, 7.302940716, 9.2581597095 };
float weight[6] = { 0.13298, 0.23227575, 0.1353261595, 0.0511557427, 0.01253922, 0.0019913644 };
color *= weight[0];
[loop]
for(int i = 1; i < 6; ++i)
{
color += tex2Dlod(ClaritySampler3, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
color += tex2Dlod(ClaritySampler3, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
}
}
if(ClarityRadius == 2)
{
float offset[11] = { 0.0, 1.4895848401, 3.4757135714, 5.4618796741, 7.4481042327, 9.4344079746, 11.420811147, 13.4073334, 15.3939936778, 17.3808101174, 19.3677999584 };
float weight[11] = { 0.06649, 0.1284697563, 0.111918249, 0.0873132676, 0.0610011113, 0.0381655709, 0.0213835661, 0.0107290241, 0.0048206869, 0.0019396469, 0.0006988718 };
color *= weight[0];
[loop]
for(int i = 1; i < 11; ++i)
{
color += tex2Dlod(ClaritySampler3, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
color += tex2Dlod(ClaritySampler3, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
}
}
if(ClarityRadius == 3)
{
float offset[15] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4401038149, 21.43402885, 23.4279736431, 25.4219399344, 27.4159294386 };
float weight[15] = { 0.0443266667, 0.0872994708, 0.0820892038, 0.0734818355, 0.0626171681, 0.0507956191, 0.0392263968, 0.0288369812, 0.0201808877, 0.0134446557, 0.0085266392, 0.0051478359, 0.0029586248, 0.0016187257, 0.0008430913 };
color *= weight[0];
[loop]
for(int i = 1; i < 15; ++i)
{
color += tex2Dlod(ClaritySampler3, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
color += tex2Dlod(ClaritySampler3, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
}
}
if(ClarityRadius == 4)
{
float offset[18] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4661974725, 21.4627427973, 23.4592916956, 25.455844494, 27.4524015179, 29.4489630909, 31.445529535, 33.4421011704 };
float weight[18] = { 0.033245, 0.0659162217, 0.0636705814, 0.0598194658, 0.0546642566, 0.0485871646, 0.0420045997, 0.0353207015, 0.0288880982, 0.0229808311, 0.0177815511, 0.013382297, 0.0097960001, 0.0069746748, 0.0048301008, 0.0032534598, 0.0021315311, 0.0013582974 };
color *= weight[0];
[loop]
for(int i = 1; i < 18; ++i)
{
color += tex2Dlod(ClaritySampler3, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
color += tex2Dlod(ClaritySampler3, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r * weight[i];
}
}
float3 orig = tex2Dlod(BackBuffer, float4(texcoord,0,0)).rgb; //Original Image
float luma = dot(orig.rgb,float3(0.32786885,0.655737705,0.0163934436));
float3 chroma = orig.rgb/luma;
float sharp = 1-color;
sharp = (luma+sharp)*0.5;
float sharpMin = lerp(0.0,1.0,smoothstep(0.0,1.0,sharp));
float sharpMax = sharpMin;
sharpMin = lerp(sharp,sharpMin,ClarityDarkIntensity);
sharpMax = lerp(sharp,sharpMax,ClarityLightIntensity);
sharp = lerp(sharpMin,sharpMax,step(0.5,sharp));
if(ClarityViewMask)
{
orig.rgb = sharp;
luma = sharp;
chroma = 1.0;
}
else
{
if(ClarityBlendMode == 0)
{
//softlight
sharp = lerp(2*luma*sharp + luma*luma*(1.0-2*sharp), 2*luma*(1.0-sharp)+pow(luma,0.5)*(2*sharp-1.0), step(0.49,sharp));
}
if(ClarityBlendMode == 1)
{
//overlay
sharp = lerp(2*luma*sharp, 1.0 - 2*(1.0-luma)*(1.0-sharp), step(0.50,luma));
}
if(ClarityBlendMode == 2)
{
//Hardlight
sharp = lerp(2*luma*sharp, 1.0 - 2*(1.0-luma)*(1.0-sharp), step(0.50,sharp));
}
if(ClarityBlendMode == 3)
{
//Multiply
sharp = saturate(2 * luma * sharp);
}
if(ClarityBlendMode == 4)
{
//vivid light
sharp = lerp(2*luma*sharp, luma/(2*(1-sharp)), step(0.5,sharp));
}
if(ClarityBlendMode == 5)
{
//Linear Light
sharp = luma + 2.0*sharp-1.0;
}
if(ClarityBlendMode == 6)
{
//Addition
sharp = saturate(luma + (sharp - 0.5));
}
}
if( ClarityBlendIfDark > 0 || ClarityBlendIfLight < 255 || ClarityViewBlendIfMask)
{
float ClarityBlendIfD = (ClarityBlendIfDark/255.0)+0.0001;
float ClarityBlendIfL = (ClarityBlendIfLight/255.0)-0.0001;
float mix = dot(orig.rgb, 0.333333);
float mask = 1.0;
if(ClarityBlendIfDark > 0)
{
mask = lerp(0.0,1.0,smoothstep(ClarityBlendIfD-(ClarityBlendIfD*0.2),ClarityBlendIfD+(ClarityBlendIfD*0.2),mix));
}
if(ClarityBlendIfLight < 255)
{
mask = lerp(mask,0.0,smoothstep(ClarityBlendIfL-(ClarityBlendIfL*0.2),ClarityBlendIfL+(ClarityBlendIfL*0.2),mix));
}
sharp = lerp(luma,sharp,mask);
if (ClarityViewBlendIfMask)
{
sharp = mask;
luma = mask;
chroma = 1.0;
}
}
orig.rgb = lerp(luma, sharp, ClarityStrength);
orig.rgb *= chroma;
return saturate(orig);
}
float Clarity1(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
float3 color = tex2Dlod(BackBuffer, float4(texcoord,0,0)).rgb;
if(ClarityRadius == 0)
{
float offset[4] = { 0.0, 1.1824255238, 3.0293122308, 5.0040701377 };
float weight[4] = { 0.39894, 0.2959599993, 0.0045656525, 0.00000149278686458842 };
color *= weight[0];
[loop]
for(int i = 1; i < 4; ++i)
{
color += tex2Dlod(BackBuffer, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
color += tex2Dlod(BackBuffer, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
}
}
if(ClarityRadius == 1)
{
float offset[6] = { 0.0, 1.4584295168, 3.40398480678, 5.3518057801, 7.302940716, 9.2581597095 };
float weight[6] = { 0.13298, 0.23227575, 0.1353261595, 0.0511557427, 0.01253922, 0.0019913644 };
color *= weight[0];
[loop]
for(int i = 1; i < 6; ++i)
{
color += tex2Dlod(BackBuffer, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
color += tex2Dlod(BackBuffer, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
}
}
if(ClarityRadius == 2)
{
float offset[11] = { 0.0, 1.4895848401, 3.4757135714, 5.4618796741, 7.4481042327, 9.4344079746, 11.420811147, 13.4073334, 15.3939936778, 17.3808101174, 19.3677999584 };
float weight[11] = { 0.06649, 0.1284697563, 0.111918249, 0.0873132676, 0.0610011113, 0.0381655709, 0.0213835661, 0.0107290241, 0.0048206869, 0.0019396469, 0.0006988718 };
color *= weight[0];
[loop]
for(int i = 1; i < 11; ++i)
{
color += tex2Dlod(BackBuffer, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
color += tex2Dlod(BackBuffer, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
}
}
if(ClarityRadius == 3)
{
float offset[15] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4401038149, 21.43402885, 23.4279736431, 25.4219399344, 27.4159294386 };
float weight[15] = { 0.0443266667, 0.0872994708, 0.0820892038, 0.0734818355, 0.0626171681, 0.0507956191, 0.0392263968, 0.0288369812, 0.0201808877, 0.0134446557, 0.0085266392, 0.0051478359, 0.0029586248, 0.0016187257, 0.0008430913 };
color *= weight[0];
[loop]
for(int i = 1; i < 15; ++i)
{
color += tex2Dlod(BackBuffer, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
color += tex2Dlod(BackBuffer, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
}
}
if(ClarityRadius == 4)
{
float offset[18] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4661974725, 21.4627427973, 23.4592916956, 25.455844494, 27.4524015179, 29.4489630909, 31.445529535, 33.4421011704 };
float weight[18] = { 0.033245, 0.0659162217, 0.0636705814, 0.0598194658, 0.0546642566, 0.0485871646, 0.0420045997, 0.0353207015, 0.0288880982, 0.0229808311, 0.0177815511, 0.013382297, 0.0097960001, 0.0069746748, 0.0048301008, 0.0032534598, 0.0021315311, 0.0013582974 };
color *= weight[0];
[loop]
for(int i = 1; i < 18; ++i)
{
color += tex2Dlod(BackBuffer, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
color += tex2Dlod(BackBuffer, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).rgb * weight[i];
}
}
return dot(color.rgb,float3(0.32786885,0.655737705,0.0163934436));
}
float Clarity2(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
float color = tex2Dlod(ClaritySampler, float4(texcoord,0,0)).r;
if(ClarityRadius == 0)
{
float offset[4] = { 0.0, 1.1824255238, 3.0293122308, 5.0040701377 };
float weight[4] = { 0.39894, 0.2959599993, 0.0045656525, 0.00000149278686458842 };
color *= weight[0];
[loop]
for(int i = 1; i < 4; ++i)
{
color += tex2Dlod(ClaritySampler, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 1)
{
float offset[6] = { 0.0, 1.4584295168, 3.40398480678, 5.3518057801, 7.302940716, 9.2581597095 };
float weight[6] = { 0.13298, 0.23227575, 0.1353261595, 0.0511557427, 0.01253922, 0.0019913644 };
color *= weight[0];
[loop]
for(int i = 1; i < 6; ++i)
{
color += tex2Dlod(ClaritySampler, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 2)
{
float offset[11] = { 0.0, 1.4895848401, 3.4757135714, 5.4618796741, 7.4481042327, 9.4344079746, 11.420811147, 13.4073334, 15.3939936778, 17.3808101174, 19.3677999584 };
float weight[11] = { 0.06649, 0.1284697563, 0.111918249, 0.0873132676, 0.0610011113, 0.0381655709, 0.0213835661, 0.0107290241, 0.0048206869, 0.0019396469, 0.0006988718 };
color *= weight[0];
[loop]
for(int i = 1; i < 11; ++i)
{
color += tex2Dlod(ClaritySampler, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 3)
{
float offset[15] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4401038149, 21.43402885, 23.4279736431, 25.4219399344, 27.4159294386 };
float weight[15] = { 0.0443266667, 0.0872994708, 0.0820892038, 0.0734818355, 0.0626171681, 0.0507956191, 0.0392263968, 0.0288369812, 0.0201808877, 0.0134446557, 0.0085266392, 0.0051478359, 0.0029586248, 0.0016187257, 0.0008430913 };
color *= weight[0];
[loop]
for(int i = 1; i < 15; ++i)
{
color += tex2Dlod(ClaritySampler, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 4)
{
float offset[18] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4661974725, 21.4627427973, 23.4592916956, 25.455844494, 27.4524015179, 29.4489630909, 31.445529535, 33.4421011704 };
float weight[18] = { 0.033245, 0.0659162217, 0.0636705814, 0.0598194658, 0.0546642566, 0.0485871646, 0.0420045997, 0.0353207015, 0.0288880982, 0.0229808311, 0.0177815511, 0.013382297, 0.0097960001, 0.0069746748, 0.0048301008, 0.0032534598, 0.0021315311, 0.0013582974 };
color *= weight[0];
[loop]
for(int i = 1; i < 18; ++i)
{
color += tex2Dlod(ClaritySampler, float4(texcoord + float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler, float4(texcoord - float2(0.0, offset[i] * pix.y) * ClarityOffset,0,0)).r* weight[i];
}
}
return color;
}
float Clarity3(in float4 pos : SV_Position, in float2 texcoord : TEXCOORD) : COLOR
{
float color = tex2Dlod(ClaritySampler2, float4(texcoord,0,0)).r;
if(ClarityRadius == 0)
{
float offset[4] = { 0.0, 1.1824255238, 3.0293122308, 5.0040701377 };
float weight[4] = { 0.39894, 0.2959599993, 0.0045656525, 0.00000149278686458842 };
color *= weight[0];
[loop]
for(int i = 1; i < 4; ++i)
{
color += tex2Dlod(ClaritySampler2, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler2, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 1)
{
float offset[6] = { 0.0, 1.4584295168, 3.40398480678, 5.3518057801, 7.302940716, 9.2581597095 };
float weight[6] = { 0.13298, 0.23227575, 0.1353261595, 0.0511557427, 0.01253922, 0.0019913644 };
color *= weight[0];
[loop]
for(int i = 1; i < 6; ++i)
{
color += tex2Dlod(ClaritySampler2, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler2, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 2)
{
float offset[11] = { 0.0, 1.4895848401, 3.4757135714, 5.4618796741, 7.4481042327, 9.4344079746, 11.420811147, 13.4073334, 15.3939936778, 17.3808101174, 19.3677999584 };
float weight[11] = { 0.06649, 0.1284697563, 0.111918249, 0.0873132676, 0.0610011113, 0.0381655709, 0.0213835661, 0.0107290241, 0.0048206869, 0.0019396469, 0.0006988718 };
color *= weight[0];
[loop]
for(int i = 1; i < 11; ++i)
{
color += tex2Dlod(ClaritySampler2, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler2, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 3)
{
float offset[15] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4401038149, 21.43402885, 23.4279736431, 25.4219399344, 27.4159294386 };
float weight[15] = { 0.0443266667, 0.0872994708, 0.0820892038, 0.0734818355, 0.0626171681, 0.0507956191, 0.0392263968, 0.0288369812, 0.0201808877, 0.0134446557, 0.0085266392, 0.0051478359, 0.0029586248, 0.0016187257, 0.0008430913 };
color *= weight[0];
[loop]
for(int i = 1; i < 15; ++i)
{
color += tex2Dlod(ClaritySampler2, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler2, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
}
}
if(ClarityRadius == 4)
{
float offset[18] = { 0.0, 1.4953705027, 3.4891992113, 5.4830312105, 7.4768683759, 9.4707125766, 11.4645656736, 13.4584295168, 15.4523059431, 17.4461967743, 19.4661974725, 21.4627427973, 23.4592916956, 25.455844494, 27.4524015179, 29.4489630909, 31.445529535, 33.4421011704 };
float weight[18] = { 0.033245, 0.0659162217, 0.0636705814, 0.0598194658, 0.0546642566, 0.0485871646, 0.0420045997, 0.0353207015, 0.0288880982, 0.0229808311, 0.0177815511, 0.013382297, 0.0097960001, 0.0069746748, 0.0048301008, 0.0032534598, 0.0021315311, 0.0013582974 };
color *= weight[0];
[loop]
for(int i = 1; i < 18; ++i)
{
color += tex2Dlod(ClaritySampler2, float4(texcoord + float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
color += tex2Dlod(ClaritySampler2, float4(texcoord - float2(offset[i] * pix.x, 0.0) * ClarityOffset,0,0)).r* weight[i];
}
}
return color;
}
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
technique Clarity
{
pass Clarity1
{
VertexShader = PostProcessVS;
PixelShader = Clarity1;
RenderTarget = ClarityTex;
}
pass Clarity2
{
VertexShader = PostProcessVS;
PixelShader = Clarity2;
RenderTarget = ClarityTex2;
}
pass Clarity3
{
VertexShader = PostProcessVS;
PixelShader = Clarity3;
RenderTarget = ClarityTex3;
}
pass ClarityFinal
{
VertexShader = PostProcessVS;
PixelShader = ClarityFinal;
}
}

View File

@ -0,0 +1,50 @@
/**
* Color Matrix version 1.0
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* ColorMatrix allow the user to transform the colors using a color matrix
*/
#include "ReShadeUI.fxh"
uniform float3 ColorMatrix_Red < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.0; ui_max = 1.0;
ui_label = "Matrix Red";
ui_tooltip = "How much of a red, green and blue tint the new red value should contain. Should sum to 1.0 if you don't wish to change the brightness.";
> = float3(0.817, 0.183, 0.000);
uniform float3 ColorMatrix_Green < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.0; ui_max = 1.0;
ui_label = "Matrix Green";
ui_tooltip = "How much of a red, green and blue tint the new green value should contain. Should sum to 1.0 if you don't wish to change the brightness.";
> = float3(0.333, 0.667, 0.000);
uniform float3 ColorMatrix_Blue < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.0; ui_max = 1.0;
ui_label = "Matrix Blue";
ui_tooltip = "How much of a red, green and blue tint the new blue value should contain. Should sum to 1.0 if you don't wish to change the brightness.";
> = float3(0.000, 0.125, 0.875);
uniform float Strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Adjust the strength of the effect.";
> = 1.0;
#include "ReShade.fxh"
float3 ColorMatrixPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
const float3x3 ColorMatrix = float3x3(ColorMatrix_Red, ColorMatrix_Green, ColorMatrix_Blue);
color = lerp(color, mul(ColorMatrix, color), Strength);
return saturate(color);
}
technique ColorMatrix
{
pass
{
VertexShader = PostProcessVS;
PixelShader = ColorMatrixPass;
}
}

View File

@ -0,0 +1,199 @@
/**
* Curves
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Curves, uses S-curves to increase contrast, without clipping highlights and shadows.
*/
#include "ReShadeUI.fxh"
uniform int Mode <
ui_type = "combo";
ui_items = "Luma\0Chroma\0Both Luma and Chroma\0";
ui_tooltip = "Choose what to apply contrast to.";
> = 0;
uniform int Formula <
ui_type = "combo";
ui_items = "Sine\0Abs split\0Smoothstep\0Exp formula\0Simplified Catmull-Rom (0,0,1,1)\0Perlins Smootherstep\0Abs add\0Techicolor Cinestyle\0Parabola\0Half-circles\0Polynomial split\0";
ui_tooltip = "The contrast s-curve you want to use. Note that Technicolor Cinestyle is practically identical to Sine, but runs slower. In fact I think the difference might only be due to rounding errors. I prefer 2 myself, but 3 is a nice alternative with a little more effect (but harsher on the highlight and shadows) and it's the fastest formula.";
> = 4;
uniform float Contrast < __UNIFORM_SLIDER_FLOAT1
ui_min = -1.0; ui_max = 1.0;
ui_tooltip = "The amount of contrast you want.";
> = 0.65;
#include "ReShade.fxh"
float4 CurvesPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float4 colorInput = tex2D(ReShade::BackBuffer, texcoord);
float3 lumCoeff = float3(0.2126, 0.7152, 0.0722); //Values to calculate luma with
float Contrast_blend = Contrast;
const float PI = 3.1415927;
/*-----------------------------------------------------------.
/ Separation of Luma and Chroma /
'-----------------------------------------------------------*/
// -- Calculate Luma and Chroma if needed --
//calculate luma (grey)
float luma = dot(lumCoeff, colorInput.rgb);
//calculate chroma
float3 chroma = colorInput.rgb - luma;
// -- Which value to put through the contrast formula? --
// I name it x because makes it easier to copy-paste to Graphtoy or Wolfram Alpha or another graphing program
float3 x;
if (Mode == 0)
x = luma; //if the curve should be applied to Luma
else if (Mode == 1)
x = chroma, //if the curve should be applied to Chroma
x = x * 0.5 + 0.5; //adjust range of Chroma from -1 -> 1 to 0 -> 1
else
x = colorInput.rgb; //if the curve should be applied to both Luma and Chroma
/*-----------------------------------------------------------.
/ Contrast formulas /
'-----------------------------------------------------------*/
// -- Curve 1 --
if (Formula == 0)
{
x = sin(PI * 0.5 * x); // Sin - 721 amd fps, +vign 536 nv
x *= x;
//x = 0.5 - 0.5*cos(PI*x);
//x = 0.5 * -sin(PI * -x + (PI*0.5)) + 0.5;
}
// -- Curve 2 --
if (Formula == 1)
{
x = x - 0.5;
x = (x / (0.5 + abs(x))) + 0.5;
//x = ( (x - 0.5) / (0.5 + abs(x-0.5)) ) + 0.5;
}
// -- Curve 3 --
if (Formula == 2)
{
//x = smoothstep(0.0,1.0,x); //smoothstep
x = x*x*(3.0 - 2.0*x); //faster smoothstep alternative - 776 amd fps, +vign 536 nv
//x = x - 2.0 * (x - 1.0) * x* (x- 0.5); //2.0 is contrast. Range is 0.0 to 2.0
}
// -- Curve 4 --
if (Formula == 3)
{
x = (1.0524 * exp(6.0 * x) - 1.05248) / (exp(6.0 * x) + 20.0855); //exp formula
}
// -- Curve 5 --
if (Formula == 4)
{
//x = 0.5 * (x + 3.0 * x * x - 2.0 * x * x * x); //a simplified catmull-rom (0,0,1,1) - btw smoothstep can also be expressed as a simplified catmull-rom using (1,0,1,0)
//x = (0.5 * x) + (1.5 -x) * x*x; //estrin form - faster version
x = x * (x * (1.5 - x) + 0.5); //horner form - fastest version
Contrast_blend = Contrast * 2.0; //I multiply by two to give it a strength closer to the other curves.
}
// -- Curve 6 --
if (Formula == 5)
{
x = x*x*x*(x*(x*6.0 - 15.0) + 10.0); //Perlins smootherstep
}
// -- Curve 7 --
if (Formula == 6)
{
//x = ((x-0.5) / ((0.5/(4.0/3.0)) + abs((x-0.5)*1.25))) + 0.5;
x = x - 0.5;
x = x / ((abs(x)*1.25) + 0.375) + 0.5;
//x = ( (x-0.5) / ((abs(x-0.5)*1.25) + (0.5/(4.0/3.0))) ) + 0.5;
}
// -- Curve 8 --
if (Formula == 7)
{
x = (x * (x * (x * (x * (x * (x * (1.6 * x - 7.2) + 10.8) - 4.2) - 3.6) + 2.7) - 1.8) + 2.7) * x * x; //Techicolor Cinestyle - almost identical to curve 1
}
// -- Curve 9 --
if (Formula == 8)
{
x = -0.5 * (x*2.0 - 1.0) * (abs(x*2.0 - 1.0) - 2.0) + 0.5; //parabola
}
// -- Curve 10 --
if (Formula == 9)
{
float3 xstep = step(x, 0.5); //tenary might be faster here
float3 xstep_shift = (xstep - 0.5);
float3 shifted_x = x + xstep_shift;
x = abs(xstep - sqrt(-shifted_x * shifted_x + shifted_x)) - xstep_shift;
//x = abs(step(x,0.5)-sqrt(-(x+step(x,0.5)-0.5)*(x+step(x,0.5)-0.5)+(x+step(x,0.5)-0.5)))-(step(x,0.5)-0.5); //single line version of the above
//x = 0.5 + (sign(x-0.5)) * sqrt(0.25-(x-trunc(x*2))*(x-trunc(x*2))); //worse
/* // if/else - even worse
if (x-0.5)
x = 0.5-sqrt(0.25-x*x);
else
x = 0.5+sqrt(0.25-(x-1)*(x-1));
*/
//x = (abs(step(0.5,x)-clamp( 1-sqrt(1-abs(step(0.5,x)- frac(x*2%1)) * abs(step(0.5,x)- frac(x*2%1))),0 ,1))+ step(0.5,x) )*0.5; //worst so far
//TODO: Check if I could use an abs split instead of step. It might be more efficient
Contrast_blend = Contrast * 0.5; //I divide by two to give it a strength closer to the other curves.
}
// -- Curve 11 --
if (Formula == 10)
{
float3 a = float3(0.0, 0.0, 0.0);
float3 b = float3(0.0, 0.0, 0.0);
a = x * x * 2.0;
b = (2.0 * -x + 4.0) * x - 1.0;
x = (x < 0.5) ? a : b;
}
/*-----------------------------------------------------------.
/ Joining of Luma and Chroma /
'-----------------------------------------------------------*/
if (Mode == 0) // Only Luma
{
x = lerp(luma, x, Contrast_blend); //Blend by Contrast
colorInput.rgb = x + chroma; //Luma + Chroma
}
else if (Mode == 1) // Only Chroma
{
x = x * 2.0 - 1.0; //adjust the Chroma range back to -1 -> 1
float3 color = luma + x; //Luma + Chroma
colorInput.rgb = lerp(colorInput.rgb, color, Contrast_blend); //Blend by Contrast
}
else // Both Luma and Chroma
{
float3 color = x; //if the curve should be applied to both Luma and Chroma
colorInput.rgb = lerp(colorInput.rgb, color, Contrast_blend); //Blend by Contrast
}
return colorInput;
}
technique Curves
{
pass
{
VertexShader = PostProcessVS;
PixelShader = CurvesPass;
}
}

View File

@ -0,0 +1,643 @@
////-------------//
///**DLAA Plus**///
//-------------////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Directionally Localized Antialiasing Plus.
//* For ReShade 3.0+
//* ---------------------------------
//* DLAA+
//* Due Diligence
//* Directionally Localized Anti-Aliasing (DLAA)
//* Original method by Dmitry Andreev
//* http://and.intercon.ru/releases/talks/dlaagdc2011/
//*
//* LICENSE
//* ============
//* Directionally Localized Anti-Aliasing Plus is licenses under: Attribution-NoDerivatives 4.0 International
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format
//* for any purpose, even commercially.
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* NoDerivatives - If you remix, transform, or build upon the material, you may not distribute the modified material.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by-nd/4.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//*
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uniform float Short_Edge_Mask <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Short Edge AA";
ui_tooltip = "Use this to adjust the Short Edge AA.\n"
"Default is 0.25";
ui_category = "DLAA";
> = 0.25;
/*
uniform float Long_Edge_Mask <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Long Edge AA";
ui_tooltip = "Use this to adjust the Long Edge AA.\n"
"Default is 0.5";
ui_category = "DLAA";
> = 0.5;
*/
uniform float Long_Edge_Mask_H <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Long Edge H+";
ui_tooltip = "Use this to adjust the Super Long Edge AA.\n"
"Default is 1.0";
ui_category = "DLAA Expanded";
> = 0.0;
uniform float Long_Edge_Mask_V <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Long Edge V+";
ui_tooltip = "Use this to adjust the Super Long Edge AA.\n"
"Default is 1.0";
ui_category = "DLAA Expanded";
> = 0.0;
uniform float De_Artifact <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "De-Artifacting";
ui_tooltip = "Use this to adjust de-artifacting power.\n"
"Default is 0.5";
ui_category = "DLAA Debuging";
> = 0.5;
uniform float Text_Preservation <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Text Preservation";
ui_tooltip = "Use this to adjust Text Preservation Power.\n"
"Default is 0.5";
ui_category = "DLAA Debuging";
> = 0.5;
uniform int View_Mode <
ui_type = "combo";
ui_items = "DLAA\0DLAA Text Preservation\0Blue Short H/V AA Mask\0Red H & Green V Long Edge Mask\0Text Preservation Mask\0";
ui_label = "View Mode";
ui_tooltip = "This is used to select the normal view output or debug view.";
ui_category = "DLAA Debuging";
> = 0;
//Total amount of frames since the game started.
uniform uint framecount < source = "framecount"; >;
////////////////////////////////////////////////////////////DLAA////////////////////////////////////////////////////////////////////
#define Alternate framecount % 2 == 0
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define lambda lerp(0,10,Short_Edge_Mask)
#define epsilon 0.0 //lerp(0,0.5,Error_Clamping)
#define DA lerp(0,16,De_Artifact)
#define Hoiz lerp(1,10,Long_Edge_Mask_H)
#define Vert lerp(1,10,Long_Edge_Mask_V)
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
};
texture DLAAtex_S {Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler SamplerDLAA_S
{
Texture = DLAAtex_S;
};
texture SLPtex_H {Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler SamplerLoadedPixel_H
{
Texture = SLPtex_H;
};
texture TexDLAA_H {Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler SamplerDLAA_H
{
Texture = TexDLAA_H;
};
texture SLPtex_V {Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler SamplerLoadedPixel_V
{
Texture = SLPtex_V;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Luminosity Intensity
float LI(in float3 value)
{
//Luminosity Controll from 0.1 to 1.0
//If GGG value of 0.333, 0.333, 0.333 is about right for Green channel.
//Slide 51 talk more about this.
return dot(value.rgb,float3(0.299, 0.587, 0.114));
}
//WIP
float Text_Detection(float2 texcoord)
{
float4 BC = tex2D(BackBuffer, texcoord);
//BC += tex2D(BackBuffer, texcoord + float2( TEST, TEST) * pix.xy);
//BC += tex2D(BackBuffer, texcoord + float2( TEST,-TEST) * pix.xy);
//BC += tex2D(BackBuffer, texcoord + float2(-TEST, TEST) * pix.xy);
//BC += tex2D(BackBuffer, texcoord + float2(-TEST, -TEST) * pix.xy);
//BC /= 4;
// Luma Threshold Thank you Adyss
BC.a = LI(BC.rgb);//Luma
BC.rgb /= max(BC.a, 0.001);
BC.a = max(0.0, BC.a - Text_Preservation);
BC.rgb *= BC.a;
return 1-dot(BC.rgb,BC.rgb);
}
float4 SLP(float2 tc,float dx, float dy) //Load Pixel
{
float4 BB = tex2D(BackBuffer, tc + float2(dx, dy) * pix.xy);
return BB;
}
float4 DLAA_Short( float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float t, l, r, d, n, MA = 1;
float2 UV = texcoord.xy, SW = MA; // But, I don't think it's really needed.
float4 NFAA; // The Edge Seeking code can be adjusted to look for longer edges.
// Find Edges
t = LI(SLP(texcoord, 0 ,-1).rgb);
d = LI(SLP(texcoord, 0 , 1).rgb);
l = LI(SLP(texcoord,-1 , 0).rgb);
r = LI(SLP(texcoord, 1 , 0).rgb);
n = length(float2(t - d,-(r - l)));
//Short Edge Filter http://and.intercon.ru/releases/talks/dlaagdc2011/slides/#slide43
float4 DLAA; //DLAA is the completed AA Result.
//5 bi-linear samples cross
float4 Center = SLP(texcoord, 0 , 0);
float4 Left = SLP(texcoord,-1.25 , 0.0);
float4 Right = SLP(texcoord, 1.25 , 0.0);
float4 Up = SLP(texcoord, 0.0 ,-1.25);
float4 Down = SLP(texcoord, 0.0 , 1.25);
//Combine horizontal and vertical blurs together
float4 combH = 2.0 * ( Up + Down );
float4 combV = 2.0 * ( Left + Right );
//Bi-directional anti-aliasing using HORIZONTAL & VERTICAL blur and horizontal edge detection
//Slide information triped me up here. Read slide 43.
//Edge detection
float4 CenterDiffH = abs( combH - 4.0 * Center ) / 4.0;
float4 CenterDiffV = abs( combV - 4.0 * Center ) / 4.0;
//Blur
float4 blurredH = (combH + 2.0 * Center) / 6.0;
float4 blurredV = (combV + 2.0 * Center) / 6.0;
//Edge detection
float LumH = LI( CenterDiffH.rgb );
float LumV = LI( CenterDiffV.rgb );
float LumHB = LI(blurredH.xyz);
float LumVB = LI(blurredV.xyz);
//t
float satAmountH = saturate( ( lambda * LumH - epsilon ) / LumVB );
float satAmountV = saturate( ( lambda * LumV - epsilon ) / LumHB );
//color = lerp(color,blur,sat(Edge/blur)
//Re-blend Short Edge Done
DLAA = lerp( Center, blurredH, saturate(lerp(satAmountV ,1,-1)) );//* 1.1
DLAA = lerp( DLAA, blurredV, saturate(lerp(satAmountH ,1,-1)) );// * 0.5
// Lets make that mask for a sharper image.
float Mask = n * 5.0;
if (Mask > 0)
Mask = 1-Mask;
else
Mask = 1;
// Super Evil Magic Number.
Mask = saturate(lerp(Mask,1,-1));
Mask += 1-saturate(lerp(satAmountV + satAmountH,1,-1));
return float4(DLAA.rgb,(satAmountV + satAmountH) * 0.5);
}
float4 LP_H(float2 tc,float dx, float dy) //Load Pixel
{
float4 BB = tex2D(BackBuffer, tc + float2(dx, dy) * pix.xy);
return BB;
}
float4 PreFilter_H(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target //Loaded Pixel
{
float4 center = LP_H(texcoord, 0, 0);
float4 left = LP_H(texcoord,-1.0, 0);
float4 right = LP_H(texcoord, 1.0, 0);
float4 top = LP_H(texcoord, 0,-1.0);
float4 bottom = LP_H(texcoord, 0, 1.0);
float4 edges = 4.0 * abs((left + right + top + bottom) - 4.0 * center);
float edgesLum = LI(edges.rgb);
return float4(center.rgb, edgesLum);
}
float4 SLP_H(float2 tc,float dx, float dy) //Load Pixel
{
float4 BB = tex2D(SamplerLoadedPixel_H, tc + float2(dx, dy) * pix.xy);
return BB;
}
//Information on Slide 44 says to run the edge processing jointly short and Large.
float4 DLAA_H(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target //Loaded Pixel
{
//Short Edge Filter http://and.intercon.ru/releases/talks/dlaagdc2011/slides/#slide43
float4 DLAA, H, V, UDLR; //DLAA is the completed AA Result.
float SLE_H = 2 * Hoiz;
//Center sample
float4 Center = SLP_H(texcoord, 0 , 0);
DLAA = tex2D(SamplerDLAA_S,texcoord);
float4 HNeg, HNegA, HNegB, HNegC, HNegD, HNegE,
HPos, HPosA, HPosB, HPosC, HPosD, HPosE,
VNeg, VNegA, VNegB, VNegC,
VPos, VPosA, VPosB, VPosC;
// Long Edges
//16 bi-linear samples cross, added extra bi-linear samples in each direction.
HNeg = SLP_H( texcoord, -1.5 , 0.0 );
HNegA = SLP_H( texcoord, -3.5 , 0.0 );
HNegB = SLP_H( texcoord, -5.5 , 0.0 );
HNegC = SLP_H( texcoord, -7.0 , 0.0 );
HPos = SLP_H( texcoord, 1.5 , 0.0 );
HPosA = SLP_H( texcoord, 3.5 , 0.0 );
HPosB = SLP_H( texcoord, 5.5 , 0.0 );
HPosC = SLP_H( texcoord, 7.0 , 0.0 );
VNeg = SLP_H( texcoord, 0.0,-1.5 );
VNegA = SLP_H( texcoord, 0.0,-3.5 );
VNegB = SLP_H( texcoord, 0.0,-5.5 );
VNegC = SLP_H( texcoord, 0.0,-7.0 );
VPos = SLP_H( texcoord, 0.0, 1.5 );
VPosA = SLP_H( texcoord, 0.0, 3.5 );
VPosB = SLP_H( texcoord, 0.0, 5.5 );
VPosC = SLP_H( texcoord, 0.0, 7.0 );
//Long Edge detection H & V
float4 AvgBlurH = ( HNeg + HNegA + HNegB + HNegC + HPos + HPosA + HPosB + HPosC ) / 8;
float4 AvgBlurV = ( VNeg + VNegA + VNegB + VNegC + VPos + VPosA + VPosB + VPosC ) / 8;
float EAH = saturate( AvgBlurH.a * SLE_H - 1.0 );
float EAV = saturate( AvgBlurV.a * 2.0 - 1.0 );
float longEdge_H = abs( EAH - EAV );
float Mask_H = longEdge_H > 0;
if ( Mask_H )
{
float4 up = LP_H(texcoord, 0 ,-1);
float4 down = LP_H(texcoord, 0 , 1);
//Merge for BlurSamples.
//Long Blur H
float LongBlurLumH = LI( AvgBlurH.rgb);//8 samples
float centerLI = LI( Center.rgb);
float upLI = LI( up.rgb );
float downLI = LI( down.rgb );
float blurUp = saturate( 0.0 + ( LongBlurLumH - upLI ) / (centerLI - upLI ) );
float blurDown = saturate( 1.0 + ( LongBlurLumH - centerLI) / (centerLI - downLI) );
UDLR = float4( 1, 1, blurUp, blurDown );
UDLR = UDLR == float4(0.0, 0.0, 0.0, 0.0) ? float4(1.0, 1.0, 1.0, 1.0) : UDLR;
H = lerp( up , Center, UDLR.z );
H = lerp( down , H , UDLR.w );
DLAA = lerp( DLAA , H , EAH);
}
return float4(DLAA.rgb,EAH);
}
float4 LP_V(float2 tc,float dx, float dy) //Load Pixel
{
float4 BB = tex2D(SamplerDLAA_H, tc + float2(dx, dy) * pix.xy);
return BB;
}
float4 PreFilter_V(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target //Loaded Pixel
{
float4 center = LP_V(texcoord, 0, 0);
float4 left = LP_V(texcoord, -1.0, 0);
float4 right = LP_V(texcoord, 1.0, 0);
float4 top = LP_V(texcoord, 0, -1.0);
float4 bottom = LP_V(texcoord, 0, 1.0);
float4 edges = 4.0 * abs((left + right + top + bottom) - 4.0 * center);
float edgesLum = LI(edges.rgb);
return float4(center.rgb, edgesLum);
}
float4 SLP_V(float2 tc,float dx, float dy) //Load Pixel
{
float4 BB = tex2D(SamplerLoadedPixel_V, tc + float2(dx, dy) * pix.xy);
return BB;
}
float4 DLAA_V(float2 texcoord)
{
//Short Edge Filter http://and.intercon.ru/releases/talks/dlaagdc2011/slides/#slide43
float4 DLAA, H, V, UDLR; //DLAA is the completed AA Result.
float SLE_V = 2 * Vert;
//Center sample
float4 Center = SLP_V(texcoord, 0 , 0);
//Reuse Long Horizontal AA
DLAA = Center;
float4 HNeg, HNegA, HNegB, HNegC, HNegD, HNegE,
HPos, HPosA, HPosB, HPosC, HPosD, HPosE,
VNeg, VNegA, VNegB, VNegC,
VPos, VPosA, VPosB, VPosC;
// Long Edges
//16 bi-linear samples cross, added extra bi-linear samples in each direction.
HNeg = SLP_V( texcoord, -1.5 , 0.0 );
HNegA = SLP_V( texcoord, -3.5 , 0.0 );
HNegB = SLP_V( texcoord, -5.5 , 0.0 );
HNegC = SLP_V( texcoord, -7.0 , 0.0 );
HPos = SLP_V( texcoord, 1.5 , 0.0 );
HPosA = SLP_V( texcoord, 3.5 , 0.0 );
HPosB = SLP_V( texcoord, 5.5 , 0.0 );
HPosC = SLP_V( texcoord, 7.0 , 0.0 );
VNeg = SLP_V( texcoord, 0.0,-1.5 );
VNegA = SLP_V( texcoord, 0.0,-3.5 );
VNegB = SLP_V( texcoord, 0.0,-5.5 );
VNegC = SLP_V( texcoord, 0.0,-7.0 );
VPos = SLP_V( texcoord, 0.0, 1.5 );
VPosA = SLP_V( texcoord, 0.0, 3.5 );
VPosB = SLP_V( texcoord, 0.0, 5.5 );
VPosC = SLP_V( texcoord, 0.0, 7.0 );
//Long Edge detection H & V
float4 AvgBlurH = ( HNeg + HNegA + HNegB + HNegC + HPos + HPosA + HPosB + HPosC ) / 8;
float4 AvgBlurV = ( VNeg + VNegA + VNegB + VNegC + VPos + VPosA + VPosB + VPosC ) / 8;
float EAH = saturate( AvgBlurH.a * 2.0 - 1.0 );
float EAV = saturate( AvgBlurV.a * SLE_V - 1.0 );
float longEdge_V = abs( EAV - EAH );
float Mask_V = longEdge_V > 0;
if ( Mask_V )
{
float4 left = LP_V(texcoord,-1 , 0);
float4 right = LP_V(texcoord, 1 , 0);
//Merge for BlurSamples.
//Long Blur V
float LongBlurLumV = LI( AvgBlurV.rgb );//8 samples
float centerLI = LI( Center.rgb);
float leftLI = LI( left.rgb );
float rightLI = LI( right.rgb );
float blurLeft = saturate( 0.0 + ( LongBlurLumV - leftLI ) / (centerLI - leftLI ) );
float blurRight = saturate( 1.0 + ( LongBlurLumV - centerLI) / (centerLI - rightLI) );
UDLR = float4( blurLeft, blurRight, 1, 1 );
UDLR = UDLR == float4(0.0, 0.0, 0.0, 0.0) ? float4(1.0, 1.0, 1.0, 1.0) : UDLR;
V = lerp( left , Center, UDLR.x );
V = lerp( right, V , UDLR.y );
//Reuse short samples and DLAA Long Edge Out.
DLAA = lerp( DLAA , V , EAV);
}
return float4(DLAA.rgb,EAV);
}
float4 DLAA(float2 texcoord)
{
float t, l, r, d;
float2 UV = texcoord.xy, SW = pix, n; // But, I don't think it's really needed.
float4 D_A;
// Find Edges
t = LI(DLAA_V( float2( UV.x , UV.y - SW.y ) ).rgb);
d = LI(DLAA_V( float2( UV.x , UV.y + SW.y ) ).rgb);
l = LI(DLAA_V( float2( UV.x - SW.x , UV.y ) ).rgb);
r = LI(DLAA_V( float2( UV.x + SW.x , UV.y ) ).rgb);
n = float2(t - d,-(r - l));
float nl = length(n), Rep = rcp(DA);
if (nl < Rep)
D_A = DLAA_V(UV);
else
{
n *= pix / nl;
float4 o = DLAA_V( UV ),
t0 = DLAA_V( UV + float2(n.x, -n.y) * 0.5) * 0.9,
t1 = DLAA_V( UV - float2(n.x, -n.y) * 0.5) * 0.9,
t2 = DLAA_V( UV + n * 0.9) * 0.75,
t3 = DLAA_V( UV - n * 0.9) * 0.75;
D_A = (o + t0 + t1 + t2 + t3) / 4.3;
}
//NFAA = tex2D(SamplerDLAA_S,UV);
float4 DLAA = D_A;
if(View_Mode == 1)
{
DLAA = lerp(tex2D(BackBuffer, texcoord),DLAA,Text_Detection(texcoord));
}
else if (View_Mode == 2)
{
DLAA = lerp(DLAA,1,float4(0,0,tex2D(SamplerDLAA_S,UV).w,1));
}
else if (View_Mode == 3)
{
DLAA = lerp(DLAA,1,float4(tex2D(SamplerDLAA_H,texcoord).w,DLAA_V(texcoord).w,0,1));
}
else if (View_Mode == 4)
{
DLAA = lerp(float4(1,1,0,1),DLAA,Text_Detection(texcoord));
}
return DLAA;
}
uniform float timer < source = "timer"; >; //Please do not remove.
////////////////////////////////////////////////////////Logo/////////////////////////////////////////////////////////////////////////
float4 Out(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float PosX = 0.9525f*BUFFER_WIDTH*pix.x,PosY = 0.975f*BUFFER_HEIGHT*pix.y;
float3 Color = DLAA(texcoord).rgb,D,E,P,T,H,Three,DD,Dot,I,N,F,O;
[branch] if(timer <= 12500)
{
//DEPTH
//D
float PosXD = -0.035+PosX, offsetD = 0.001;
float3 OneD = all( abs(float2( texcoord.x -PosXD, texcoord.y-PosY)) < float2(0.0025,0.009));
float3 TwoD = all( abs(float2( texcoord.x -PosXD-offsetD, texcoord.y-PosY)) < float2(0.0025,0.007));
D = OneD-TwoD;
//E
float PosXE = -0.028+PosX, offsetE = 0.0005;
float3 OneE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.009));
float3 TwoE = all( abs(float2( texcoord.x -PosXE-offsetE, texcoord.y-PosY)) < float2(0.0025,0.007));
float3 ThreeE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.001));
E = (OneE-TwoE)+ThreeE;
//P
float PosXP = -0.0215+PosX, PosYP = -0.0025+PosY, offsetP = 0.001, offsetP1 = 0.002;
float3 OneP = all( abs(float2( texcoord.x -PosXP, texcoord.y-PosYP)) < float2(0.0025,0.009*0.775));
float3 TwoP = all( abs(float2( texcoord.x -PosXP-offsetP, texcoord.y-PosYP)) < float2(0.0025,0.007*0.680));
float3 ThreeP = all( abs(float2( texcoord.x -PosXP+offsetP1, texcoord.y-PosY)) < float2(0.0005,0.009));
P = (OneP-TwoP) + ThreeP;
//T
float PosXT = -0.014+PosX, PosYT = -0.008+PosY;
float3 OneT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosYT)) < float2(0.003,0.001));
float3 TwoT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosY)) < float2(0.000625,0.009));
T = OneT+TwoT;
//H
float PosXH = -0.0072+PosX;
float3 OneH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.001));
float3 TwoH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.009));
float3 ThreeH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.00325,0.009));
H = (OneH-TwoH)+ThreeH;
//Three
float offsetFive = 0.001, PosX3 = -0.001+PosX;
float3 OneThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.009));
float3 TwoThree = all( abs(float2( texcoord.x -PosX3 - offsetFive, texcoord.y-PosY)) < float2(0.003,0.007));
float3 ThreeThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.001));
Three = (OneThree-TwoThree)+ThreeThree;
//DD
float PosXDD = 0.006+PosX, offsetDD = 0.001;
float3 OneDD = all( abs(float2( texcoord.x -PosXDD, texcoord.y-PosY)) < float2(0.0025,0.009));
float3 TwoDD = all( abs(float2( texcoord.x -PosXDD-offsetDD, texcoord.y-PosY)) < float2(0.0025,0.007));
DD = OneDD-TwoDD;
//Dot
float PosXDot = 0.011+PosX, PosYDot = 0.008+PosY;
float3 OneDot = all( abs(float2( texcoord.x -PosXDot, texcoord.y-PosYDot)) < float2(0.00075,0.0015));
Dot = OneDot;
//INFO
//I
float PosXI = 0.0155+PosX, PosYI = 0.004+PosY, PosYII = 0.008+PosY;
float3 OneI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosY)) < float2(0.003,0.001));
float3 TwoI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYI)) < float2(0.000625,0.005));
float3 ThreeI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYII)) < float2(0.003,0.001));
I = OneI+TwoI+ThreeI;
//N
float PosXN = 0.0225+PosX, PosYN = 0.005+PosY,offsetN = -0.001;
float3 OneN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN)) < float2(0.002,0.004));
float3 TwoN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN - offsetN)) < float2(0.003,0.005));
N = OneN-TwoN;
//F
float PosXF = 0.029+PosX, PosYF = 0.004+PosY, offsetF = 0.0005, offsetF1 = 0.001;
float3 OneF = all( abs(float2( texcoord.x -PosXF-offsetF, texcoord.y-PosYF-offsetF1)) < float2(0.002,0.004));
float3 TwoF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0025,0.005));
float3 ThreeF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0015,0.00075));
F = (OneF-TwoF)+ThreeF;
//O
float PosXO = 0.035+PosX, PosYO = 0.004+PosY;
float3 OneO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.003,0.005));
float3 TwoO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.002,0.003));
O = OneO-TwoO;
//Website
return float4(D+E+P+T+H+Three+DD+Dot+I+N+F+O,1.) ? 1-texcoord.y*50.0+48.35f : float4(Color,1.);
}
else
return float4(Color,1.);
}
///////////////ReShade.fxh/////////////////////////////////////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
//*Rendering passes*//
technique Directionally_Localized_Anti_Aliasing_Plus
{
pass Short_Edge_AA
{
VertexShader = PostProcessVS;
PixelShader = DLAA_Short;
RenderTarget = DLAAtex_S;
}
pass Pre_Filter_Hoizontal
{
VertexShader = PostProcessVS;
PixelShader = PreFilter_H;
RenderTarget = SLPtex_H;
}
pass Pre_Filter_Vertical
{
VertexShader = PostProcessVS;
PixelShader = DLAA_H;
RenderTarget = TexDLAA_H;
}
pass Pre_Filter_Vertical
{
VertexShader = PostProcessVS;
PixelShader = PreFilter_V;
RenderTarget = SLPtex_V;
}
pass DLAA
{
VertexShader = PostProcessVS;
PixelShader = Out;
}
}

View File

@ -0,0 +1,73 @@
/**
* DPX/Cineon shader by Loadus
*/
#include "ReShadeUI.fxh"
uniform float3 RGB_Curve < __UNIFORM_SLIDER_FLOAT3
ui_min = 1.0; ui_max = 15.0;
ui_label = "RGB Curve";
> = float3(8.0, 8.0, 8.0);
uniform float3 RGB_C < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.2; ui_max = 0.5;
ui_label = "RGB C";
> = float3(0.36, 0.36, 0.34);
uniform float Contrast < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
> = 0.1;
uniform float Saturation < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 8.0;
> = 3.0;
uniform float Colorfulness < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.1; ui_max = 2.5;
> = 2.5;
uniform float Strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Adjust the strength of the effect.";
> = 0.20;
#include "ReShade.fxh"
static const float3x3 RGB = float3x3(
2.6714711726599600, -1.2672360578624100, -0.4109956021722270,
-1.0251070293466400, 1.9840911624108900, 0.0439502493584124,
0.0610009456429445, -0.2236707508128630, 1.1590210416706100
);
static const float3x3 XYZ = float3x3(
0.5003033835433160, 0.3380975732227390, 0.1645897795458570,
0.2579688942747580, 0.6761952591447060, 0.0658358459823868,
0.0234517888692628, 0.1126992737203000, 0.8668396731242010
);
float3 DPXPass(float4 vois : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 input = tex2D(ReShade::BackBuffer, texcoord).rgb;
float3 B = input;
B = B * (1.0 - Contrast) + (0.5 * Contrast);
float3 Btemp = (1.0 / (1.0 + exp(RGB_Curve / 2.0)));
B = ((1.0 / (1.0 + exp(-RGB_Curve * (B - RGB_C)))) / (-2.0 * Btemp + 1.0)) + (-Btemp / (-2.0 * Btemp + 1.0));
float value = max(max(B.r, B.g), B.b);
float3 color = B / value;
color = pow(abs(color), 1.0 / Colorfulness);
float3 c0 = color * value;
c0 = mul(XYZ, c0);
float luma = dot(c0, float3(0.30, 0.59, 0.11));
c0 = (1.0 - Saturation) * luma + Saturation * c0;
c0 = mul(RGB, c0);
return lerp(input, c0, Strength);
}
technique DPX
{
pass
{
VertexShader = PostProcessVS;
PixelShader = DPXPass;
}
}

View File

@ -0,0 +1,73 @@
/**
* Daltonization algorithm by daltonize.org
* http://www.daltonize.org/2010/05/lms-daltonization-algorithm.html
* Originally ported to ReShade by IDDQD, modified for ReShade 3.0 by crosire
*/
uniform int Type <
ui_type = "combo";
ui_items = "Protanopia\0Deuteranopia\0Tritanopia\0";
> = 0;
#include "ReShade.fxh"
float3 PS_DaltonizeFXmain(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 input = tex2D(ReShade::BackBuffer, texcoord).rgb;
// RGB to LMS matrix conversion
float OnizeL = (17.8824f * input.r) + (43.5161f * input.g) + (4.11935f * input.b);
float OnizeM = (3.45565f * input.r) + (27.1554f * input.g) + (3.86714f * input.b);
float OnizeS = (0.0299566f * input.r) + (0.184309f * input.g) + (1.46709f * input.b);
// Simulate color blindness
float Daltl, Daltm, Dalts;
if (Type == 0) // Protanopia - reds are greatly reduced (1% men)
{
Daltl = 0.0f * OnizeL + 2.02344f * OnizeM + -2.52581f * OnizeS;
Daltm = 0.0f * OnizeL + 1.0f * OnizeM + 0.0f * OnizeS;
Dalts = 0.0f * OnizeL + 0.0f * OnizeM + 1.0f * OnizeS;
}
else if (Type == 1) // Deuteranopia - greens are greatly reduced (1% men)
{
Daltl = 1.0f * OnizeL + 0.0f * OnizeM + 0.0f * OnizeS;
Daltm = 0.494207f * OnizeL + 0.0f * OnizeM + 1.24827f * OnizeS;
Dalts = 0.0f * OnizeL + 0.0f * OnizeM + 1.0f * OnizeS;
}
else if (Type == 2) // Tritanopia - blues are greatly reduced (0.003% population)
{
Daltl = 1.0f * OnizeL + 0.0f * OnizeM + 0.0f * OnizeS;
Daltm = 0.0f * OnizeL + 1.0f * OnizeM + 0.0f * OnizeS;
Dalts = -0.395913f * OnizeL + 0.801109f * OnizeM + 0.0f * OnizeS;
}
// LMS to RGB matrix conversion
float3 error;
error.r = (0.0809444479f * Daltl) + (-0.130504409f * Daltm) + (0.116721066f * Dalts);
error.g = (-0.0102485335f * Daltl) + (0.0540193266f * Daltm) + (-0.113614708f * Dalts);
error.b = (-0.000365296938f * Daltl) + (-0.00412161469f * Daltm) + (0.693511405f * Dalts);
// Isolate invisible colors to color vision deficiency (calculate error matrix)
error = (input - error);
// Shift colors towards visible spectrum (apply error modifications)
float3 correction;
correction.r = 0; // (error.r * 0.0) + (error.g * 0.0) + (error.b * 0.0);
correction.g = (error.r * 0.7) + (error.g * 1.0); // + (error.b * 0.0);
correction.b = (error.r * 0.7) + (error.b * 1.0); // + (error.g * 0.0);
// Add compensation to original values
correction = input + correction;
return correction;
}
technique Daltonize
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_DaltonizeFXmain;
}
}

View File

@ -0,0 +1,252 @@
/**
* Deband shader by haasn
* https://github.com/haasn/gentoo-conf/blob/xor/home/nand/.mpv/shaders/deband-pre.glsl
*
* Copyright (c) 2015 Niklas Haas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Modified and optimized for ReShade by JPulowski
* https://reshade.me/forum/shader-presentation/768-deband
*
* Do not distribute without giving credit to the original author(s).
*
* 1.0 - Initial release
* 1.1 - Replaced the algorithm with the one from MPV
* 1.1a - Minor optimizations
* - Removed unnecessary lines and replaced them with ReShadeFX intrinsic counterparts
* 2.0 - Replaced "grain" with CeeJay.dk's ordered dithering algorithm and enabled it by default
* - The configuration is now more simpler and straightforward
* - Some minor code changes and optimizations
* - Improved the algorithm and made it more robust by adding some of the madshi's
* improvements to flash3kyuu_deband which should cause an increase in quality. Higher
* iterations/ranges should now yield higher quality debanding without too much decrease
* in quality.
* - Changed licensing text and original source code URL
* 3.0 - Replaced the entire banding detection algorithm with modified standard deviation and
* Weber ratio analyses which give more accurate and error-free results compared to the
* previous algorithm
* - Added banding map debug view
* - Added and redefined UI categories
* - Added depth detection (credits to spiro) which should be useful when banding only
* occurs in the sky texture for example
* - Fixed a bug in random number generation which was causing artifacts on the upper left
* side of the screen
* - Dithering is now applied only when debanding a pixel as it should be which should
* reduce the overall noise in the final texture
* - Minor code optimizations
* 3.1 - Switched to chroma-based analysis from luma-based analysis which was causing artifacts
* under some scenarios
* - Changed parts of the code which was causing compatibility issues on some renderers
*/
#include "ReShadeUI.fxh"
#include "ReShade.fxh"
uniform bool enable_weber <
ui_category = "Banding analysis";
ui_label = "Weber ratio";
ui_tooltip = "Weber ratio analysis that calculates the ratio of the each local pixel's intensity to average background intensity of all the local pixels.";
ui_type = "radio";
> = true;
uniform bool enable_sdeviation <
ui_category = "Banding analysis";
ui_label = "Standard deviation";
ui_tooltip = "Modified standard deviation analysis that calculates nearby pixels' intensity deviation from the current pixel instead of the mean.";
ui_type = "radio";
> = true;
uniform bool enable_depthbuffer <
ui_category = "Banding analysis";
ui_label = "Depth detection";
ui_tooltip = "Allows depth information to be used when analysing banding, pixels will only be analysed if they are in a certain depth. (e.g. debanding only the sky)";
ui_type = "radio";
> = false;
uniform float t1 <
ui_category = "Banding analysis";
ui_label = "Standard deviation threshold";
ui_max = 0.5;
ui_min = 0.0;
ui_step = 0.001;
ui_tooltip = "Standard deviations lower than this threshold will be flagged as flat regions with potential banding.";
ui_type = "slider";
> = 0.007;
uniform float t2 <
ui_category = "Banding analysis";
ui_label = "Weber ratio threshold";
ui_max = 2.0;
ui_min = 0.0;
ui_step = 0.01;
ui_tooltip = "Weber ratios lower than this threshold will be flagged as flat regions with potential banding.";
ui_type = "slider";
> = 0.04;
uniform float banding_depth <
ui_category = "Banding analysis";
ui_label = "Banding depth";
ui_max = 1.0;
ui_min = 0.0;
ui_step = 0.001;
ui_tooltip = "Pixels under this depth threshold will not be processed and returned as they are.";
ui_type = "slider";
> = 1.0;
uniform float range <
ui_category = "Banding detection & removal";
ui_label = "Radius";
ui_max = 32.0;
ui_min = 1.0;
ui_step = 1.0;
ui_tooltip = "The radius increases linearly for each iteration. A higher radius will find more gradients, but a lower radius will smooth more aggressively.";
ui_type = "slider";
> = 24.0;
uniform int iterations <
ui_category = "Banding detection & removal";
ui_label = "Iterations";
ui_max = 4;
ui_min = 1;
ui_tooltip = "The number of debanding steps to perform per sample. Each step reduces a bit more banding, but takes time to compute.";
ui_type = "slider";
> = 1;
uniform int debug_output <
ui_category = "Debug";
ui_items = "None\0Blurred (LPF) image\0Banding map\0";
ui_label = "Debug view";
ui_tooltip = "Blurred (LPF) image: Useful when tweaking radius and iterations to make sure all banding regions are blurred enough.\nBanding map: Useful when tweaking analysis parameters, continuous green regions indicate flat (i.e. banding) regions.";
ui_type = "combo";
> = 0;
// Reshade uses C rand for random, max cannot be larger than 2^15-1
uniform int drandom < source = "random"; min = 0; max = 32767; >;
float rand(float x)
{
return frac(x / 41.0);
}
float permute(float x)
{
return ((34.0 * x + 1.0) * x) % 289.0;
}
float3 PS_Deband(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 ori = tex2Dlod(ReShade::BackBuffer, float4(texcoord, 0.0, 0.0)).rgb;
if (enable_depthbuffer && (ReShade::GetLinearizedDepth(texcoord) < banding_depth))
return ori;
// Initialize the PRNG by hashing the position + a random uniform
float3 m = float3(texcoord + 1.0, (drandom / 32767.0) + 1.0);
float h = permute(permute(permute(m.x) + m.y) + m.z);
// Compute a random angle
float dir = rand(permute(h)) * 6.2831853;
float2 o;
sincos(dir, o.y, o.x);
// Distance calculations
float2 pt;
float dist;
for (int i = 1; i <= iterations; ++i) {
dist = rand(h) * range * i;
pt = dist * BUFFER_PIXEL_SIZE;
h = permute(h);
}
// Sample at quarter-turn intervals around the source pixel
float3 ref[4] = {
tex2Dlod(ReShade::BackBuffer, float4(mad(pt, o, texcoord), 0.0, 0.0)).rgb, // SE
tex2Dlod(ReShade::BackBuffer, float4(mad(pt, -o, texcoord), 0.0, 0.0)).rgb, // NW
tex2Dlod(ReShade::BackBuffer, float4(mad(pt, float2(-o.y, o.x), texcoord), 0.0, 0.0)).rgb, // NE
tex2Dlod(ReShade::BackBuffer, float4(mad(pt, float2( o.y, -o.x), texcoord), 0.0, 0.0)).rgb // SW
};
// Calculate weber ratio
float3 mean = (ori + ref[0] + ref[1] + ref[2] + ref[3]) * 0.2;
float3 k = abs(ori - mean);
for (int j = 0; j < 4; ++j) {
k += abs(ref[j] - mean);
}
k = k * 0.2 / mean;
// Calculate std. deviation
float3 sd = 0.0;
for (int j = 0; j < 4; ++j) {
sd += pow(ref[j] - ori, 2);
}
sd = sqrt(sd * 0.25);
// Generate final output
float3 output;
if (debug_output == 2)
output = float3(0.0, 1.0, 0.0);
else
output = (ref[0] + ref[1] + ref[2] + ref[3]) * 0.25;
// Generate a binary banding map
bool3 banding_map = true;
if (debug_output != 1) {
if (enable_weber)
banding_map = banding_map && k <= t2 * iterations;
if (enable_sdeviation)
banding_map = banding_map && sd <= t1 * iterations;
}
/*------------------------.
| :: Ordered Dithering :: |
'------------------------*/
//Calculate grid position
float grid_position = frac(dot(texcoord, (BUFFER_SCREEN_SIZE * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
//Calculate how big the shift should be
float dither_shift = 0.25 * (1.0 / (pow(2, BUFFER_COLOR_BIT_DEPTH) - 1.0));
//Shift the individual colors differently, thus making it even harder to see the dithering pattern
float3 dither_shift_RGB = float3(dither_shift, -dither_shift, dither_shift); //subpixel dithering
//modify shift acording to grid position.
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position.
return banding_map ? output + dither_shift_RGB : ori;
}
technique Deband <
ui_tooltip = "Alleviates color banding by trying to approximate original color values.";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_Deband;
}
}

View File

@ -0,0 +1,425 @@
////---------------//
///**Depth Cues**///
//---------------////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Depth Based Unsharp Mask haloing
// For Reshade 3.0+
// ---------------------------------
// Depth Cues
// Extra Information for where I got the Idea for Depth Cues.
// https://www.uni-konstanz.de/mmsp/pubsys/publishedFiles/LuCoDe06.pdf
//
// LICENSE
// ============
// Overwatch & Depth Cues is licenses under: Attribution-NoDerivatives 4.0 International
//
// You are free to:
// Share - copy and redistribute the material in any medium or format
// for any purpose, even commercially.
// The licensor cannot revoke these freedoms as long as you follow the license terms.
// Under the following terms:
// Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
// You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//
// NoDerivatives - If you remix, transform, or build upon the material, you may not distribute the modified material.
//
// No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//
// https://creativecommons.org/licenses/by-nd/4.0/
//
// Have fun,
// Jose Negrete AKA BlueSkyDefender
//
// https://github.com/BlueSkyDefender/Depth3D
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if exists "Overwatch.fxh" //Overwatch Intercepter//
#include "Overwatch.fxh"
#else //DA_W Depth_Linearization | DB_X Depth_Flip
static const float DA_W = 0.0, DB_X = 0;
#define NC 0
#define NP 0
#endif
//Automatic Blur Adjustment based on Resolutionsup to 8k considered.
#if (BUFFER_HEIGHT <= 720)
#define Multi 0.5
#elif (BUFFER_HEIGHT <= 1080)
#define Multi 1.0
#elif (BUFFER_HEIGHT <= 1440)
#define Multi 1.5
#elif (BUFFER_HEIGHT <= 2160)
#define Multi 2
#else
#define Quality 2.5
#endif
// It is best to run Smart Sharp after tonemapping.
#if !defined(__RESHADE__) || __RESHADE__ < 40000
#define Compatibility 1
#else
#define Compatibility 0
#endif
uniform int Depth_Map <
ui_type = "combo";
ui_items = "Normal\0Reverse\0";
ui_label = "Custom Depth Map";
ui_tooltip = "Pick your Depth Map.";
ui_category = "Depth Buffer";
> = DA_W;
uniform float Depth_Map_Adjust <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 1.0; ui_max = 1000.0; ui_step = 0.125;
ui_label = "Depth Map Adjustment";
ui_tooltip = "Adjust the depth map and sharpness distance.";
ui_category = "Depth Buffer";
> = 250.0;
uniform bool Depth_Map_Flip <
ui_label = "Depth Map Flip";
ui_tooltip = "Flip the depth map if it is upside down.";
ui_category = "Depth Buffer";
> = DB_X;
uniform bool DEPTH_DEBUG <
ui_label = "View Depth";
ui_tooltip = "Shows depth, you want close objects to be black and far objects to be white for things to work properly.";
ui_category = "Depth Buffer";
> = false;
uniform bool No_Depth_Map <
ui_label = "No Depth Map";
ui_tooltip = "If you have No Depth Buffer turn this On.";
ui_category = "Depth Buffer";
> = true;
uniform float Shade_Power <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.25; ui_max = 1.0;
ui_label = "Shade Power";
ui_tooltip = "Adjust the Shade Power This improves AO, Shadows, & Darker Areas in game.\n"
"Number 0.5 is default.";
ui_category = "Depth Cues";
> = 0.5;
uniform float Blur_Cues <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.0; ui_max = 1.0;
ui_label = "Blur Shade";
ui_tooltip = "Adjust the to make Shade Softer in the Image.\n"
"Number 0.5 is default.";
ui_category = "Depth Cues";
> = 0.5;
uniform float Spread <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 1.0; ui_max = 25.0; ui_step = 0.25;
ui_label = "Shade Fill";
ui_tooltip = "Adjust This to have the shade effect to fill in areas gives fakeAO effect.\n"
"This is used for gap filling.\n"
"Number 10.0 is default.";
ui_category = "Depth Cues";
> = 10.0;
uniform bool Debug_View <
ui_label = "Depth Cues Debug";
ui_tooltip = "Depth Cues Debug output the shadeded output.";
ui_category = "Depth Cues";
> = false;
//uniform bool Fake_AO <
// ui_label = "Fake AO";
// ui_tooltip = "Fake AO only works when you Have Depth Buffer Access.";
// ui_category = "Fake AO";
//> = false;
/////////////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define BlurSamples 10 //BlurSamples = # * 2
//#define Fake_AO_Adjust 0.001
#define S_Power Spread * Multi
#define M_Power Blur_Cues * Multi
uniform float timer < source = "timer"; >;
texture DepthBufferTex : DEPTH;
sampler DepthBuffer_DC
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer_DC
{
Texture = BackBufferTex;
};
texture texHB_DC { Width = BUFFER_WIDTH * 0.5 ; Height = BUFFER_HEIGHT * 0.5 ; Format = R8; MipLevels = 1;};
sampler SamplerHB_DC
{
Texture = texHB_DC;
};
texture texDC { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R8; MipLevels = 3;};
sampler SamplerDC
{
Texture = texDC;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Depth_DC(in float2 texcoord : TEXCOORD0)
{
if (Depth_Map_Flip)
texcoord.y = 1 - texcoord.y;
float zBuffer = tex2D(DepthBuffer_DC, texcoord).x; //Depth Buffer
//Conversions to linear space.....
//Near & Far Adjustment
float Far = 1.0, Near = 0.125/Depth_Map_Adjust; //Division Depth Map Adjust - Near
float2 Z = float2( zBuffer, 1-zBuffer );
if (Depth_Map == 0)//DM0. Normal
zBuffer = Far * Near / (Far + Z.x * (Near - Far));
else if (Depth_Map == 1)//DM1. Reverse
zBuffer = Far * Near / (Far + Z.y * (Near - Far));
return saturate(zBuffer);
}
float lum(float3 RGB)
{
return dot(RGB, float3(0.2126, 0.7152, 0.0722) );
}
float BB(in float2 texcoord, float2 AD)
{
//if(Fake_AO)
// return lerp(1-(1 - Fake_AO_Adjust/Depth_DC(texcoord + AD).x) , lum(tex2Dlod(BackBuffer_DC, float4(texcoord + AD,0,0)).rgb) , 0.125);
//else
return lum(tex2Dlod(BackBuffer_DC, float4(texcoord + AD,0,0)).rgb);
}
float H_Blur_DC(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float S = S_Power * 0.125;
float sum = BB(texcoord,0) * BlurSamples;
float total = BlurSamples;
for ( int j = -BlurSamples; j <= BlurSamples; ++j)
{
float W = BlurSamples;
sum += BB(texcoord , + float2(pix.x * S,0) * j ) * W;
total += W;
}
return saturate(sum / total); // Get it Total sum..... :D
}
// Spread the blur a bit more.
float DepthCues(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float2 S = S_Power * 0.75f * pix;
float M_Cues = 1, result = tex2Dlod(SamplerHB_DC,float4(texcoord,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2( 1, 0) * S ,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2( 0, 1) * S ,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2(-1, 0) * S ,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2( 0,-1) * S ,0,M_Cues)).x;
S *= 0.5;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2( 1, 0) * S ,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2( 0, 1) * S ,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2(-1, 0) * S ,0,M_Cues)).x;
result += tex2Dlod(SamplerHB_DC,float4(texcoord + float2( 0,-1) * S ,0,M_Cues)).x;
result *= rcp(9);
// Formula for Image Pop = Original + (Original / Blurred).
//float DC = BB(texcoord,0) / result;
return saturate(lerp(1.0f,BB(texcoord,0) / result,Shade_Power));
}
float3 ShaderOut_DC(float2 texcoord : TEXCOORD0)
{
float DCB = tex2Dlod(SamplerDC,float4(texcoord,0,M_Power)).x,DB = Depth_DC(texcoord).x;
float3 Out, BBN = tex2D(BackBuffer_DC,texcoord).rgb;
if(No_Depth_Map)
DB = 0.0;
Out.rgb = BBN * lerp(DCB,1., DB);
if (Debug_View)
Out = lerp(DCB,1., DB);
if (DEPTH_DEBUG)
Out = DB;
return Out;
}
////////////////////////////////////////////////////////Logo/////////////////////////////////////////////////////////////////////////
float3 Out_DC(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{ //Overwatch integration
float PosX = 0.9525f*BUFFER_WIDTH*pix.x,PosY = 0.975f*BUFFER_HEIGHT*pix.y, Text_Timer = 12500, BT = smoothstep(0,1,sin(timer*(3.75/1000)));
float D,E,P,T,H,Three,DD,Dot,I,N,F,O,R,EE,A,DDD,HH,EEE,L,PP,NN,PPP,C,Not,No;
float3 Color = ShaderOut_DC(texcoord).rgb;
if(NC || NP)
Text_Timer = 18750;
[branch] if(timer <= Text_Timer)
{
//DEPTH
//D
float PosXD = -0.035+PosX, offsetD = 0.001;
float OneD = all( abs(float2( texcoord.x -PosXD, texcoord.y-PosY)) < float2(0.0025,0.009));
float TwoD = all( abs(float2( texcoord.x -PosXD-offsetD, texcoord.y-PosY)) < float2(0.0025,0.007));
D = OneD-TwoD;
//E
float PosXE = -0.028+PosX, offsetE = 0.0005;
float OneE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.009));
float TwoE = all( abs(float2( texcoord.x -PosXE-offsetE, texcoord.y-PosY)) < float2(0.0025,0.007));
float ThreeE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.001));
E = (OneE-TwoE)+ThreeE;
//P
float PosXP = -0.0215+PosX, PosYP = -0.0025+PosY, offsetP = 0.001, offsetP1 = 0.002;
float OneP = all( abs(float2( texcoord.x -PosXP, texcoord.y-PosYP)) < float2(0.0025,0.009*0.775));
float TwoP = all( abs(float2( texcoord.x -PosXP-offsetP, texcoord.y-PosYP)) < float2(0.0025,0.007*0.680));
float ThreeP = all( abs(float2( texcoord.x -PosXP+offsetP1, texcoord.y-PosY)) < float2(0.0005,0.009));
P = (OneP-TwoP) + ThreeP;
//T
float PosXT = -0.014+PosX, PosYT = -0.008+PosY;
float OneT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosYT)) < float2(0.003,0.001));
float TwoT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosY)) < float2(0.000625,0.009));
T = OneT+TwoT;
//H
float PosXH = -0.0072+PosX;
float OneH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.001));
float TwoH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.009));
float ThreeH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.00325,0.009));
H = (OneH-TwoH)+ThreeH;
//Three
float offsetFive = 0.001, PosX3 = -0.001+PosX;
float OneThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.009));
float TwoThree = all( abs(float2( texcoord.x -PosX3 - offsetFive, texcoord.y-PosY)) < float2(0.003,0.007));
float ThreeThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.001));
Three = (OneThree-TwoThree)+ThreeThree;
//DD
float PosXDD = 0.006+PosX, offsetDD = 0.001;
float OneDD = all( abs(float2( texcoord.x -PosXDD, texcoord.y-PosY)) < float2(0.0025,0.009));
float TwoDD = all( abs(float2( texcoord.x -PosXDD-offsetDD, texcoord.y-PosY)) < float2(0.0025,0.007));
DD = OneDD-TwoDD;
//Dot
float PosXDot = 0.011+PosX, PosYDot = 0.008+PosY;
float OneDot = all( abs(float2( texcoord.x -PosXDot, texcoord.y-PosYDot)) < float2(0.00075,0.0015));
Dot = OneDot;
//INFO
//I
float PosXI = 0.0155+PosX, PosYI = 0.004+PosY, PosYII = 0.008+PosY;
float OneI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosY)) < float2(0.003,0.001));
float TwoI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYI)) < float2(0.000625,0.005));
float ThreeI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYII)) < float2(0.003,0.001));
I = OneI+TwoI+ThreeI;
//N
float PosXN = 0.0225+PosX, PosYN = 0.005+PosY,offsetN = -0.001;
float OneN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN)) < float2(0.002,0.004));
float TwoN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN - offsetN)) < float2(0.003,0.005));
N = OneN-TwoN;
//F
float PosXF = 0.029+PosX, PosYF = 0.004+PosY, offsetF = 0.0005, offsetF1 = 0.001;
float OneF = all( abs(float2( texcoord.x -PosXF-offsetF, texcoord.y-PosYF-offsetF1)) < float2(0.002,0.004));
float TwoF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0025,0.005));
float ThreeF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0015,0.00075));
F = (OneF-TwoF)+ThreeF;
//O
float PosXO = 0.035+PosX, PosYO = 0.004+PosY;
float OneO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.003,0.005));
float TwoO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.002,0.003));
O = OneO-TwoO;
//Text Warnings: No Profile / Not Compatible
//PosY += 0.953;
PosX -= 0.483;
float PosXNN = -0.458+PosX, offsetNN = 0.0015;
float OneNN = all( abs(float2( texcoord.x -PosXNN, texcoord.y-PosY)) < float2(0.00325,0.009));
float TwoNN = all( abs(float2( texcoord.x -PosXNN, texcoord.y-PosY-offsetNN)) < float2(0.002,0.008));
NN = OneNN-TwoNN;
//PPP
float PosXPPP = -0.451+PosX, PosYPPP = -0.0025+PosY, offsetPPP = 0.001, offsetPPP1 = 0.002;
float OnePPP = all( abs(float2( texcoord.x -PosXPPP, texcoord.y-PosYPPP)) < float2(0.0025,0.009*0.775));
float TwoPPP = all( abs(float2( texcoord.x -PosXPPP-offsetPPP, texcoord.y-PosYPPP)) < float2(0.0025,0.007*0.680));
float ThreePPP = all( abs(float2( texcoord.x -PosXPPP+offsetPPP1, texcoord.y-PosY)) < float2(0.0005,0.009));
PPP = (OnePPP-TwoPPP) + ThreePPP;
//C
float PosXC = -0.450+PosX, offsetC = 0.001;
float OneC = all( abs(float2( texcoord.x -PosXC, texcoord.y-PosY)) < float2(0.0035,0.009));
float TwoC = all( abs(float2( texcoord.x -PosXC-offsetC, texcoord.y-PosY)) < float2(0.0025,0.007));
C = OneC-TwoC;
if(NP)
No = (NN + PPP) * BT; //Blinking Text
if(NC)
Not = (NN + C) * BT; //Blinking Text
//Website
return D+E+P+T+H+Three+DD+Dot+I+N+F+O+No+Not ? (1-texcoord.y*50.0+48.85)*texcoord.y-0.500: Color;
}
else
return Color;
}
///////////////////////////////////////////////////////////ReShade.fxh/////////////////////////////////////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
//*Rendering passes*//
technique Monocular_Cues
{
pass Blur
{
VertexShader = PostProcessVS;
PixelShader = H_Blur_DC;
RenderTarget = texHB_DC;
}
pass BlurDC
{
VertexShader = PostProcessVS;
PixelShader = DepthCues;
RenderTarget = texDC;
}
pass UnsharpMask
{
VertexShader = PostProcessVS;
PixelShader = Out_DC;
}
}

View File

@ -0,0 +1,258 @@
/*
DisplayDepth by CeeJay.dk (with many updates and additions by the Reshade community)
Visualizes the depth buffer. The distance of pixels determine their brightness.
Close objects are dark. Far away objects are bright.
Use this to configure the depth input preprocessor definitions (RESHADE_DEPTH_INPUT_*).
*/
#include "ReShade.fxh"
uniform int iUIPresentType <
ui_type = "combo";
ui_label = "Present type";
ui_items = "Depth map\0"
"Normal map\0"
"Show both (Vertical 50/50)\0";
> = 2;
// -- Basic options --
#if __RESHADE__ >= 40500 // If Reshade version is above or equal to 4.5
#if RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
#define UPSIDE_DOWN_HELP_TEXT "RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN is currently set to 1.\n"\
"If the Depth map is shown upside down set it to 0."
#define iUIUpsideDown 1
#else
#define UPSIDE_DOWN_HELP_TEXT "RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN is currently set to 0.\n"\
"If the Depth map is shown upside down set it to 1."
#define iUIUpsideDown 0
#endif
#if RESHADE_DEPTH_INPUT_IS_REVERSED
#define REVERSED_HELP_TEXT "RESHADE_DEPTH_INPUT_IS_REVERSED is currently set to 1.\n"\
"If close objects in the Depth map are bright and far ones are dark set it to 0.\n"\
"Also try this if you can see the normals, but the depth view is all black."
#define iUIReversed 1
#else
#define REVERSED_HELP_TEXT "RESHADE_DEPTH_INPUT_IS_REVERSED is currently set to 0.\n"\
"If close objects in the Depth map are bright and far ones are dark set it to 1.\n"\
"Also try this if you can see the normals, but the depth view is all black."
#define iUIReversed 0
#endif
#if RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
#define LOGARITHMIC_HELP_TEXT "RESHADE_DEPTH_INPUT_IS_LOGARITHMIC is currently set to 1.\n"\
"If the Normal map has banding artifacts (extra stripes) set it to 0."
#define iUILogarithmic 1
#else
#define LOGARITHMIC_HELP_TEXT "RESHADE_DEPTH_INPUT_IS_LOGARITHMIC is currently set to 0.\n"\
"If the Normal map has banding artifacts (extra stripes) set it to 1."
#define iUILogarithmic 0
#endif
uniform int Depth_help <
ui_type = "radio"; ui_label = " ";
ui_text =
"\nThe right settings need to be set in the dialog that opens after clicking the \"Edit global preprocessor definitions\" button above.\n"
"\n"
UPSIDE_DOWN_HELP_TEXT "\n"
"\n"
REVERSED_HELP_TEXT "\n"
"\n"
LOGARITHMIC_HELP_TEXT;
>;
#else // "ui_text" was introduced in ReShade 4.5, so cannot show instructions in older versions
uniform bool bUIUseLivePreview <
ui_label = "Show live preview";
ui_tooltip = "Enable this to show use the preview settings below rather than the saved preprocessor settings.";
> = true;
uniform int iUIUpsideDown <
ui_type = "combo";
ui_label = "Upside Down (Preview)";
ui_items = "RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN=0\0"
"RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN=1\0";
> = RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN;
uniform int iUIReversed <
ui_type = "combo";
ui_label = "Reversed (Preview)";
ui_items = "RESHADE_DEPTH_INPUT_IS_REVERSED=0\0"
"RESHADE_DEPTH_INPUT_IS_REVERSED=1\0";
> = RESHADE_DEPTH_INPUT_IS_REVERSED;
uniform int iUILogarithmic <
ui_type = "combo";
ui_label = "Logarithmic (Preview)";
ui_items = "RESHADE_DEPTH_INPUT_IS_LOGARITHMIC=0\0"
"RESHADE_DEPTH_INPUT_IS_LOGARITHMIC=1\0";
ui_tooltip = "Change this setting if the displayed surface normals have stripes in them.";
> = RESHADE_DEPTH_INPUT_IS_LOGARITHMIC;
#endif
// -- Advanced options --
#if __RESHADE__ >= 40500
uniform int Advanced_help <
ui_category = "Advanced settings";
ui_category_closed = true;
ui_type = "radio"; ui_label = " ";
ui_text =
"\nThe following settings also need to be set using \"Edit global preprocessor definitions\" above in order to take effect.\n"
"You can preview how they will affect the Depth map using the controls below.\n\n"
"It is rarely necessary to change these though, as their defaults fit almost all games.";
>;
uniform bool bUIUseLivePreview <
ui_category = "Advanced settings";
ui_label = "Show live preview";
ui_tooltip = "Enable this to show use the preview settings below rather than the saved preprocessor settings.";
> = true;
#endif
uniform float2 fUIScale <
ui_category = "Advanced settings";
ui_type = "drag";
ui_label = "Scale (Preview)";
ui_tooltip = "Best use 'Present type'->'Depth map' and enable 'Offset' in the options below to set the scale.\n"
"Use these values for:\nRESHADE_DEPTH_INPUT_X_SCALE=<left value>\nRESHADE_DEPTH_INPUT_Y_SCALE=<right value>\n"
"\n"
"If you know the right resolution of the games depth buffer then this scale value is simply the ratio\n"
"between the correct resolution and the resolution Reshade thinks it is.\n"
"For example:\n"
"If it thinks the resolution is 1920 x 1080, but it's really 1280 x 720 then the right scale is (1.5 , 1.5)\n"
"because 1920 / 1280 is 1.5 and 1080 / 720 is also 1.5, so 1.5 is the right scale for both the x and the y";
ui_min = 0.0; ui_max = 2.0;
ui_step = 0.001;
> = float2(RESHADE_DEPTH_INPUT_X_SCALE, RESHADE_DEPTH_INPUT_Y_SCALE);
uniform int2 iUIOffset <
ui_category = "Advanced settings";
ui_type = "drag";
ui_label = "Offset (Preview)";
ui_tooltip = "Best use 'Present type'->'Depth map' and enable 'Offset' in the options below to set the offset in pixels.\n"
"Use these values for:\nRESHADE_DEPTH_INPUT_X_PIXEL_OFFSET=<left value>\nRESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET=<right value>";
ui_step = 1;
> = int2(RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET, RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET);
uniform bool bUIShowOffset <
ui_category = "Advanced settings";
ui_label = "Blend Depth map into the image (to help with finding the right offset)";
> = false;
uniform float fUIFarPlane <
ui_category = "Advanced settings";
ui_type = "drag";
ui_label = "Far Plane (Preview)";
ui_tooltip = "RESHADE_DEPTH_LINEARIZATION_FAR_PLANE=<value>\n"
"Changing this value is not necessary in most cases.";
ui_min = 0.0; ui_max = 1000.0;
ui_step = 0.1;
> = RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
uniform float fUIDepthMultiplier <
ui_category = "Advanced settings";
ui_type = "drag";
ui_label = "Multiplier (Preview)";
ui_tooltip = "RESHADE_DEPTH_MULTIPLIER=<value>";
ui_min = 0.0; ui_max = 1000.0;
ui_step = 0.001;
> = RESHADE_DEPTH_MULTIPLIER;
float GetLinearizedDepth(float2 texcoord)
{
if (!bUIUseLivePreview)
{
return ReShade::GetLinearizedDepth(texcoord);
}
else
{
if (iUIUpsideDown) // RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
texcoord.y = 1.0 - texcoord.y;
texcoord.x /= fUIScale.x; // RESHADE_DEPTH_INPUT_X_SCALE
texcoord.y /= fUIScale.y; // RESHADE_DEPTH_INPUT_Y_SCALE
texcoord.x -= iUIOffset.x * BUFFER_RCP_WIDTH; // RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET
texcoord.y += iUIOffset.y * BUFFER_RCP_HEIGHT; // RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET
float depth = tex2Dlod(ReShade::DepthBuffer, float4(texcoord, 0, 0)).x * fUIDepthMultiplier;
const float C = 0.01;
if (iUILogarithmic) // RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
depth = (exp(depth * log(C + 1.0)) - 1.0) / C;
if (iUIReversed) // RESHADE_DEPTH_INPUT_IS_REVERSED
depth = 1.0 - depth;
const float N = 1.0;
depth /= fUIFarPlane - depth * (fUIFarPlane - N);
return depth;
}
}
float3 GetScreenSpaceNormal(float2 texcoord)
{
float3 offset = float3(BUFFER_PIXEL_SIZE, 0.0);
float2 posCenter = texcoord.xy;
float2 posNorth = posCenter - offset.zy;
float2 posEast = posCenter + offset.xz;
float3 vertCenter = float3(posCenter - 0.5, 1) * GetLinearizedDepth(posCenter);
float3 vertNorth = float3(posNorth - 0.5, 1) * GetLinearizedDepth(posNorth);
float3 vertEast = float3(posEast - 0.5, 1) * GetLinearizedDepth(posEast);
return normalize(cross(vertCenter - vertNorth, vertCenter - vertEast)) * 0.5 + 0.5;
}
void PS_DisplayDepth(in float4 position : SV_Position, in float2 texcoord : TEXCOORD, out float3 color : SV_Target)
{
float3 depth = GetLinearizedDepth(texcoord).xxx;
float3 normal = GetScreenSpaceNormal(texcoord);
// Ordered dithering
#if 1
const float dither_bit = 8.0; // Number of bits per channel. Should be 8 for most monitors.
// Calculate grid position
float grid_position = frac(dot(texcoord, (BUFFER_SCREEN_SIZE * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
// Calculate how big the shift should be
float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0));
// Shift the individual colors differently, thus making it even harder to see the dithering pattern
float3 dither_shift_RGB = float3(dither_shift, -dither_shift, dither_shift); // Subpixel dithering
// Modify shift acording to grid position.
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position);
depth += dither_shift_RGB;
#endif
color = depth;
if (iUIPresentType == 1)
color = normal;
if (iUIPresentType == 2)
color = lerp(normal, depth, step(BUFFER_WIDTH * 0.5, position.x));
if (bUIShowOffset)
{
float3 color_orig = tex2D(ReShade::BackBuffer, texcoord).rgb;
// Blend depth and back buffer color with 'overlay' so the offset is more noticeable
color = lerp(2 * color * color_orig, 1.0 - 2.0 * (1.0 - color) * (1.0 - color_orig), max(color.r, max(color.g, color.b)) < 0.5 ? 0.0 : 1.0);
}
}
technique DisplayDepth <
ui_tooltip = "This shader helps you set the right preprocessor settings for depth input.\n"
"To set the settings click on 'Edit global preprocessor definitions' and set them there - not in this shader.\n"
"The settings will then take effect for all shaders, including this one.\n"
"\n"
"By default calculated normals and depth are shown side by side.\n"
"Normals (on the left) should look smooth and the ground should be greenish when looking at the horizon.\n"
"Depth (on the right) should show close objects as dark and use gradually brighter shades the further away objects are.\n";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_DisplayDepth;
}
}

View File

@ -0,0 +1,228 @@
#ifndef _DRAWTEXT_H_
#define _DRAWTEXT_H_
#define _DRAWTEXT_GRID_X 14.0
#define _DRAWTEXT_GRID_Y 7.0
///////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// DrawText.fxh by kingreic1992 ( update: Sep.28.2019 ) //
// //
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
// //
// Available functions: //
// DrawText_String( offset, text size, xy ratio, input coord, string array, array size, output) //
// float2 offset = top left corner of string, screen hight pixel unit. //
// float text size = text size, screen hight pixel unit. //
// float xy ratio = xy ratio of text. //
// float2 input coord = current texture coord. //
// int string array = string data in float2 array format, ex: "Demo Text" //
// int String0[9] = { __D, __e, __m, __o, __Space, __T, __e, __x, __t}; //
// int string size = size of the string array. //
// float output = output. //
// //
// DrawText_Digit( offset, text size, xy ratio, input coord, precision after dot, data, output) //
// float2 offset = same as DrawText_String. //
// float text size = same as DrawText_String. //
// float xy ratio = same as DrawText_String. //
// float2 input coord = same as DrawText_String. //
// int precision = digits after dot. //
// float data = input float. //
// float output = output. //
// //
// float2 DrawText_Shift(offset, shift, text size, xy ratio) //
// float2 offset = same as DrawText_String. //
// float2 shift = shift line(y) and column. //
// float text size = same as DrawText_String. //
// float xy ratio = same as DrawText_String. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////////////
//Sample Usage
/*
#include "DrawText.fxh"
float4 main_fragment( float4 position : POSITION,
float2 txcoord : TEXCOORD) : COLOR {
float res = 0.0;
int line0[9] = { __D, __e, __m, __o, __Space, __T, __e, __x, __t }; //Demo Text
int line1[15] = { __b, __y, __Space, __k, __i, __n, __g, __e, __r, __i, __c, __1, __9, __9, __2 }; //by kingeric1992
int line2[6] = { __S, __i, __z, __e, __Colon, __Space }; // Size: %d.
DrawText_String(float2(100.0 , 100.0), 32, 1, txcoord, line0, 9, res);
DrawText_String(float2(100.0 , 134.0), textSize, 1, txcoord, line1, 15, res);
DrawText_String(DrawText_Shift(float2(100.0 , 134.0), int2(0, 1), textSize, 1), 18, 1, txcoord, line2, 6, res);
DrawText_Digit(DrawText_Shift(DrawText_Shift(float2(100.0 , 134.0), int2(0, 1), textSize, 1), int2(8, 0), 18, 1),
18, 1, txcoord, 0, textSize, res);
return res;
}
*/
//Text display
//Character indexing
#define __Space 0 // (space)
#define __Exclam 1 // !
#define __Quote 2 // "
#define __Pound 3 // #
#define __Dollar 4 // $
#define __Percent 5 // %
#define __And 6 // &
#define __sQuote 7 // '
#define __rBrac_O 8 // (
#define __rBrac_C 9 // )
#define __Asterisk 10 // *
#define __Plus 11 // +
#define __Comma 12 // ,
#define __Minus 13 // -
#define __Dot 14 // .
#define __Slash 15 // /
#define __0 16 // 0
#define __1 17 // 1
#define __2 18 // 2
#define __3 19 // 3
#define __4 20 // 4
#define __5 21 // 5
#define __6 22 // 6
#define __7 23 // 7
#define __8 24 // 8
#define __9 25 // 9
#define __Colon 26 // :
#define __sColon 27 // ;
#define __Less 28 // <
#define __Equals 29 // =
#define __Greater 30 // >
#define __Question 31 // ?
#define __at 32 // @
#define __A 33 // A
#define __B 34 // B
#define __C 35 // C
#define __D 36 // D
#define __E 37 // E
#define __F 38 // F
#define __G 39 // G
#define __H 40 // H
#define __I 41 // I
#define __J 42 // J
#define __K 43 // K
#define __L 44 // L
#define __M 45 // M
#define __N 46 // N
#define __O 47 // O
#define __P 48 // P
#define __Q 49 // Q
#define __R 50 // R
#define __S 51 // S
#define __T 52 // T
#define __U 53 // U
#define __V 54 // V
#define __W 55 // W
#define __X 56 // X
#define __Y 57 // Y
#define __Z 58 // Z
#define __sBrac_O 59 // [
#define __Backslash 60 // \..
#define __sBrac_C 61 // ]
#define __Caret 62 // ^
#define __Underscore 63 // _
#define __Punc 64 // `
#define __a 65 // a
#define __b 66 // b
#define __c 67 // c
#define __d 68 // d
#define __e 69 // e
#define __f 70 // f
#define __g 71 // g
#define __h 72 // h
#define __i 73 // i
#define __j 74 // j
#define __k 75 // k
#define __l 76 // l
#define __m 77 // m
#define __n 78 // n
#define __o 79 // o
#define __p 80 // p
#define __q 81 // q
#define __r 82 // r
#define __s 83 // s
#define __t 84 // t
#define __u 85 // u
#define __v 86 // v
#define __w 87 // w
#define __x 88 // x
#define __y 89 // y
#define __z 90 // z
#define __cBrac_O 91 // {
#define __vBar 92 // |
#define __cBrac_C 93 // }
#define __Tilde 94 // ~
#define __tridot 95 // (...)
#define __empty0 96 // (null)
#define __empty1 97 // (null)
//Character indexing ends
texture Texttex < source = "FontAtlas.png"; > {
Width = 512;
Height = 512;
};
sampler samplerText {
Texture = Texttex;
};
//accomodate for undef array size.
#define DrawText_String( pos, size, ratio, tex, array, arrSize, output ) \
{ float text = 0.0; \
float2 uv = (tex * float2(BUFFER_WIDTH, BUFFER_HEIGHT) - pos) / size; \
uv.y = saturate(uv.y); \
uv.x *= ratio * 2.0; \
float id = array[int(trunc(uv.x))]; \
if(uv.x <= arrSize && uv.x >= 0.0) \
text = tex2D(samplerText, (frac(uv) + float2( id % 14.0, trunc(id / 14.0))) \
/ float2( _DRAWTEXT_GRID_X, _DRAWTEXT_GRID_Y) ).x; \
output += text; }
float2 DrawText_Shift( float2 pos, int2 shift, float size, float ratio ) {
return pos + size * shift * float2(0.5, 1.0) / ratio;
}
void DrawText_Digit( float2 pos, float size, float ratio, float2 tex, int digit, float data, inout float res) {
int digits[13] = {
__0, __1, __2, __3, __4, __5, __6, __7, __8, __9, __Minus, __Space, __Dot
};
float2 uv = (tex * float2(BUFFER_WIDTH, BUFFER_HEIGHT) - pos) / size;
uv.y = saturate(uv.y);
uv.x *= ratio * 2.0;
float t = abs(data);
int radix = floor(t)? ceil(log2(t)/3.32192809):0;
//early exit:
if(uv.x > digit+1 || -uv.x > radix+1) return;
float index = t;
if(floor(uv.x) > 0)
for(int i = ceil(-uv.x); i<0; i++) index *= 10.;
else
for(int i = ceil(uv.x); i<0; i++) index /= 10.;
index = (uv.x >= -radix-!radix)? index%10 : (10+step(0, data)); //adding sign
index = (uv.x > 0 && uv.x < 1)? 12:index; //adding dot
index = digits[(uint)index];
res += tex2D(samplerText, (frac(uv) + float2( index % 14.0, trunc(index / 14.0))) /
float2( _DRAWTEXT_GRID_X, _DRAWTEXT_GRID_Y)).x;
}
#endif

View File

@ -0,0 +1,127 @@
/**
* FXAA 3.11
*
* for ReShade 3.0+
*/
#include "ReShadeUI.fxh"
uniform float Subpix < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Amount of sub-pixel aliasing removal. Higher values makes the image softer/blurrier.";
> = 0.25;
uniform float EdgeThreshold < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_label = "Edge Detection Threshold";
ui_tooltip = "The minimum amount of local contrast required to apply algorithm.";
> = 0.125;
uniform float EdgeThresholdMin < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_label = "Darkness Threshold";
ui_tooltip = "Pixels darker than this are not processed in order to increase performance.";
> = 0.0;
//------------------------------ Non-GUI-settings -------------------------------------------------
#ifndef FXAA_QUALITY__PRESET
// Valid Quality Presets
// 10 to 15 - default medium dither (10=fastest, 15=highest quality)
// 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
// 39 - no dither, very expensive
#define FXAA_QUALITY__PRESET 15
#endif
#ifndef FXAA_GREEN_AS_LUMA
#define FXAA_GREEN_AS_LUMA 0
#endif
#ifndef FXAA_LINEAR_LIGHT
#define FXAA_LINEAR_LIGHT 0
#endif
//-------------------------------------------------------------------------------------------------
#if (__RENDERER__ == 0xb000 || __RENDERER__ == 0xb100)
#define FXAA_GATHER4_ALPHA 1
#define FxaaTexAlpha4(t, p) tex2Dgather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) tex2Dgatheroffset(t, p, o, 3)
#define FxaaTexGreen4(t, p) tex2Dgather(t, p, 1)
#define FxaaTexOffGreen4(t, p, o) tex2Dgatheroffset(t, p, o, 1)
#endif
#define FXAA_PC 1
#define FXAA_HLSL_3 1
// Green as luma requires non-linear colorspace
#if FXAA_GREEN_AS_LUMA
#undef FXAA_LINEAR_LIGHT
#endif
#include "FXAA.fxh"
#include "ReShade.fxh"
// Samplers
sampler FXAATexture
{
Texture = ReShade::BackBufferTex;
MinFilter = Linear; MagFilter = Linear;
#if FXAA_LINEAR_LIGHT
SRGBTexture = true;
#endif
};
// Pixel shaders
#if !FXAA_GREEN_AS_LUMA
float4 FXAALumaPass(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D(ReShade::BackBuffer, texcoord.xy);
color.a = sqrt(dot(color.rgb * color.rgb, float3(0.299, 0.587, 0.114)));
return color;
}
#endif
float4 FXAAPixelShader(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return FxaaPixelShader(
texcoord, // pos
0, // fxaaConsolePosPos
FXAATexture, // tex
FXAATexture, // fxaaConsole360TexExpBiasNegOne
FXAATexture, // fxaaConsole360TexExpBiasNegTwo
BUFFER_PIXEL_SIZE, // fxaaQualityRcpFrame
0, // fxaaConsoleRcpFrameOpt
0, // fxaaConsoleRcpFrameOpt2
0, // fxaaConsole360RcpFrameOpt2
Subpix, // fxaaQualitySubpix
EdgeThreshold, // fxaaQualityEdgeThreshold
EdgeThresholdMin, // fxaaQualityEdgeThresholdMin
0, // fxaaConsoleEdgeSharpness
0, // fxaaConsoleEdgeThreshold
0, // fxaaConsoleEdgeThresholdMin
0 // fxaaConsole360ConstDir
);
}
// Rendering passes
technique FXAA
{
#if !FXAA_GREEN_AS_LUMA
pass
{
VertexShader = PostProcessVS;
PixelShader = FXAALumaPass;
}
#endif
pass
{
VertexShader = PostProcessVS;
PixelShader = FXAAPixelShader;
#if FXAA_LINEAR_LIGHT
SRGBWriteEnable = true;
#endif
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/**
* HDR
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Not actual HDR - It just tries to mimic an HDR look (relatively high performance cost)
*/
#include "ReShadeUI.fxh"
uniform float HDRPower < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 8.0;
ui_label = "Power";
> = 1.30;
uniform float radius1 < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 8.0;
ui_label = "Radius 1";
> = 0.793;
uniform float radius2 < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 8.0;
ui_label = "Radius 2";
ui_tooltip = "Raising this seems to make the effect stronger and also brighter.";
> = 0.87;
#include "ReShade.fxh"
float3 HDRPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
float3 bloom_sum1 = tex2D(ReShade::BackBuffer, texcoord + float2(1.5, -1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, -1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 1.5, 1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, 1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, -2.5) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, 2.5) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2(-2.5, 0.0) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 2.5, 0.0) * radius1 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum1 *= 0.005;
float3 bloom_sum2 = tex2D(ReShade::BackBuffer, texcoord + float2(1.5, -1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, -1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 1.5, 1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, 1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, -2.5) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, 2.5) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2(-2.5, 0.0) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 2.5, 0.0) * radius2 * BUFFER_PIXEL_SIZE).rgb;
bloom_sum2 *= 0.010;
float dist = radius2 - radius1;
float3 HDR = (color + (bloom_sum2 - bloom_sum1)) * dist;
float3 blend = HDR + color;
color = pow(abs(blend), abs(HDRPower)) + HDR; // pow - don't use fractions for HDRpower
return saturate(color);
}
technique HDR
{
pass
{
VertexShader = PostProcessVS;
PixelShader = HDRPass;
}
}

View File

@ -0,0 +1,104 @@
/**
* FilmGrain version 1.0
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Computes a noise pattern and blends it with the image to create a film grain look.
*/
#include "ReShadeUI.fxh"
uniform float Intensity < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "How visible the grain is. Higher is more visible.";
> = 0.50;
uniform float Variance < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Controls the variance of the Gaussian noise. Lower values look smoother.";
> = 0.40;
uniform float Mean < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Affects the brightness of the noise.";
> = 0.5;
uniform int SignalToNoiseRatio < __UNIFORM_SLIDER_INT1
ui_min = 0; ui_max = 16;
ui_label = "Signal-to-Noise Ratio";
ui_tooltip = "Higher Signal-to-Noise Ratio values give less grain to brighter pixels. 0 disables this feature.";
> = 6;
uniform float Timer < source = "timer"; >;
#include "ReShade.fxh"
float3 FilmGrainPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
//float inv_luma = dot(color, float3(-0.2126, -0.7152, -0.0722)) + 1.0;
float inv_luma = dot(color, float3(-1.0/3.0, -1.0/3.0, -1.0/3.0)) + 1.0; //Calculate the inverted luma so it can be used later to control the variance of the grain
/*---------------------.
| :: Generate Grain :: |
'---------------------*/
const float PI = 3.1415927;
//time counter using requested counter from ReShade
float t = Timer * 0.0022337;
//PRNG 2D - create two uniform noise values and save one DP2ADD
float seed = dot(texcoord, float2(12.9898, 78.233));// + t;
float sine = sin(seed);
float cosine = cos(seed);
float uniform_noise1 = frac(sine * 43758.5453 + t); //I just salt with t because I can
float uniform_noise2 = frac(cosine * 53758.5453 - t); // and it doesn't cost any extra ASM
//Get settings
float stn = SignalToNoiseRatio != 0 ? pow(abs(inv_luma), (float)SignalToNoiseRatio) : 1.0; // Signal to noise feature - Brighter pixels get less noise.
float variance = (Variance*Variance) * stn;
float mean = Mean;
//Box-Muller transform
uniform_noise1 = (uniform_noise1 < 0.0001) ? 0.0001 : uniform_noise1; //fix log(0)
float r = sqrt(-log(uniform_noise1));
r = (uniform_noise1 < 0.0001) ? PI : r; //fix log(0) - PI happened to be the right answer for uniform_noise == ~ 0.0000517.. Close enough and we can reuse a constant.
float theta = (2.0 * PI) * uniform_noise2;
float gauss_noise1 = variance * r * cos(theta) + mean;
//float gauss_noise2 = variance * r * sin(theta) + mean; //we can get two gaussians out of it :)
//gauss_noise1 = (ddx(gauss_noise1) - ddy(gauss_noise1)) * 0.50 + gauss_noise2;
//Calculate how big the shift should be
//float grain = lerp(1.0 - Intensity, 1.0 + Intensity, gauss_noise1);
float grain = lerp(1.0 + Intensity, 1.0 - Intensity, gauss_noise1);
//float grain2 = (2.0 * Intensity) * gauss_noise1 + (1.0 - Intensity);
//Apply grain
color = color * grain;
//color = (grain-1.0) *2.0 + 0.5;
//color = lerp(color,colorInput.rgb,sqrt(luma));
/*-------------------------.
| :: Debugging features :: |
'-------------------------*/
//color.rgb = frac(gauss_noise1).xxx; //show the noise
//color.rgb = (gauss_noise1 > 0.999) ? float3(1.0,1.0,0.0) : 0.0 ; //does it reach 1.0?
return color.rgb;
}
technique FilmGrain
{
pass
{
VertexShader = PostProcessVS;
PixelShader = FilmGrainPass;
}
}

View File

@ -0,0 +1,789 @@
////---------//
///**Flair**///
//---------////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Lens Flares are based on Blooming HDR Original Code
//* For Reshade 3.0+
//* ---------------------------------
//* Flair
//* Let's add some ------ to your images.
//* Flares
//* Due Diligence
//* Eye Adaptation
//* https://knarkowicz.wordpress.com/2016/01/09/automatic-exposure/ Search Ref. Temporal Adaptation
//* If I miss any please tell me.
//*
//* LICENSE
//* ============
//* Flare is licenses under: Attribution-NoDerivatives 4.0 International
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format
//* for any purpose, even commercially.
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* NoDerivatives - If you remix, transform, or build upon the material, you may not distribute the modified material.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by-nd/4.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//* Special thanks to NVIDIA on compatibility with GeForce GPUs and feedback on shader development
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Shared Texture for Blooming HDR or any other shader that want's to use it.
texture TexFlareShared { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
//You can also make a text file named "DisableFlare.txt" to dissable this shader output and
//only use the Share Texture above in your your shader.
uniform int Flare_Type <
ui_type = "combo";
ui_items = "Star Full\0Star Half\0Cross +\0Cross x\0Flare +Skew\0Flare -Skew\0Flare Horizontal\0Flare Vertical\0";
ui_label = "Flare Type";
ui_category = "Flare Type";
> = 0;
uniform bool Auto_Flare_Intensity <
ui_label = "Auto Flare Intensity";
ui_tooltip = "This will enable the shader to adjust Flare Intensity automatically.\n"
"Auto Bloom Intensity will set Bloom Intensity below.";
ui_category = "Flare Adjustments";
> = false;
uniform float Flare_Clamp_A <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Flare Brightness Threshold";
ui_tooltip = "Use this to set the color based brightness threshold for what is and what isn't allowed.\n"
"Number 1.0 is default.";
ui_category = "Flare Adjustments";
> = 1.0;
uniform float Flare_Clamp_B <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Flare Max Brightness Cutoff";
ui_tooltip = "Use this to set the max cutoff point of the brightness things in the image.\n"
"Number 1.0 is default.";
ui_category = "Flare Adjustments";
> = 1.0;
uniform float Flare_Spread <
ui_type = "slider";
ui_min = -1.0; ui_max = 1.0; ui_step = 0.01;
ui_label = "Flare Spread";
ui_tooltip = "Use this to adjust Flare size & you can override this.\n"
"Number 0.5 is default.";
ui_category = "Flare Adjustments";
> = 0.5;
uniform float Flare_Power <
ui_type = "slider";
ui_min = 0.0; ui_max = 12.5; ui_step = 0.125;
ui_label = "Flare Intensity";
ui_tooltip = "Use this to set Flare Intensity for your content.\n"
"Number 1.0 is default.";
ui_category = "Flare Adjustments";
> = 1.0;
uniform float Flare_Saturation <
ui_type = "slider";
ui_min = 0.0; ui_max = 10.0; ui_step = 0.1;
ui_label = "Flare Saturation";
ui_tooltip = "Adjustment The amount to adjust the saturation of the flare color.\n"
"Number 1.0 is default.";
ui_category = "Flare Adjustments";
> = 5.0;
//User_Flare_Color needs Flare_Color_Map to be set to -1 and the rest uncommented.
uniform int Flare_Color_Map <
ui_type = "slider";
ui_min = -1; ui_max = 8;
ui_label = "Flare Color Map";
ui_tooltip = "Use this to set MIP levels for the color map used to se Flare Color.\n"
"This samples color in the general area to achieve this effect.\n"
"Number 4 is default & Zero is Off.";
ui_category = "Flare Adjustments";
> = 4;
uniform float3 User_Flare_Color <
ui_type = "color";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Flare Color Adjust";
ui_tooltip = "Use this to set your own color settings.";
ui_category = "Flare Adjustments";
> = float3(1.0,1.0,1.0);
uniform float Flare_Localization <
ui_type = "slider";
ui_min = -1.0; ui_max = 1.0; ui_step = 0.1;
ui_label = "Flare Localization";
ui_tooltip = "This localizes flare to a user selected area.\n"
"Number Zero is default.";
ui_category = "Flare Adjustments";
> = 0.0;
uniform int CA_Type <
ui_type = "combo";
ui_items = "Off\0Type BD\0Type Box\0Type Hozi\0Type Verti\0";
ui_label = "Flare CA Type";
ui_category = "Flare Chromatic Aberration";
> = 1;
uniform float3 Flare_PBD <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Flare CA Adjust";
ui_tooltip = "Use this to set chromatic aberration for your content.";
ui_category = "Flare Chromatic Aberration";
> = float3(1.0,0.5,0.0);
//Depth Map//
uniform int Depth_Map <
ui_type = "combo";
ui_items = "Normal\0Reversed\0";
ui_label = "Depth Map Adjustment";
ui_tooltip = "Linearization for the zBuffer also known as Depth Map.\n"
"DM0 is Z-Normal and DM1 is Z-Reversed.\n";
ui_category = "Depth Map Masking";
> = 0;
uniform float Depth_Map_Adjust <
ui_type = "drag";
ui_min = 0.25; ui_max = 250.0; ui_step = 0.25;
ui_label = "Depth Map Adjustment";
ui_tooltip = "This allows for you to adjust the DM precision.\n"
"Adjust this to keep it as low as possible.\n"
"Default is 1.5";
ui_category = "Depth Map Masking";
> = 1.5;
uniform bool Depth_Map_Flip <
ui_label = "Depth Map Flip";
ui_tooltip = "Flip the depth map if it is upside down.";
ui_category = "Depth Map Masking";
> = false;
uniform bool Mask_Sky <
ui_label = "Sky Mask";
ui_tooltip = "Mask Sky using depth";
ui_category = "Depth Map Masking";
> = false;
uniform bool Flair_Falloff <
ui_label = "Falloff";
ui_tooltip = "A depth mask is use to add a fall off distance";
ui_category = "Depth Map Masking";
> = false;
#if __RENDERER__ >= 0x20000 //Vulkan
#define Rend 1
#else
#define Rend 0
#endif
/////////////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
uniform float timer < source = "timer"; >;
//Total amount of frames since the game started.
uniform uint framecount < source = "framecount"; >;
uniform float frametime < source = "frametime";>;
//Made Up Values that look nice not correct.
static const float OffsetA[25] = { 0.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 21.0, 23.0, 25.0, 27.0, 29.0, 31.0, 33.0, 35.0, 37.0, 39.0, 41.0, 43.0, 45.0, 47.0 };
static const float OffsetB[25] = { 0.0, 2.0, 4.0, 6.0, 8.0,10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0, 32.0, 34.0, 36.0, 38.0, 40.0, 42.0, 44.0, 46.0, 48.0 };
static const float OffsetC[25] = { 0.5, 1.5, 3.5, 5.5, 7.5, 9.5, 11.5, 13.5, 15.5, 17.5, 19.5, 21.5, 23.5, 25.5, 27.5, 29.5, 31.5, 33.5, 35.5, 37.5, 39.5, 41.5, 43.5, 45.5, 47.5 };
static const float OffsetD[25] = { 0.5, 2.5, 4.5, 6.5, 8.5,10.5, 12.5, 14.5, 16.5, 18.5, 20.5, 22.5, 24.5, 26.5, 28.5, 30.5, 32.5, 34.5, 36.5, 38.5, 40.5, 42.5, 44.5, 46.5, 48.5 };
static const float Weight[25] = { 0.10761,0.10306,0.09750, 0.09110,0.08409,0.07666,0.06903,0.06139,0.05394,0.04680,0.0401,0.0339,0.0284,0.0234,0.0191,0.0154,0.0122,0.0096,0.0074,0.0057,0.0043,0.0032,0.0024,0.0017,0.0012 };
#define FS Flare_Spread < 0 ? Flare_Spread * 4.0 : Flare_Spread * 2.2
#define Flare_Softness 0 //saturate(abs(Flare_Spread)) //Removed because of Opti
#define Alternate framecount % 2 == 0
//Eye Adaptation Set from 0 to 1
static const float Adapt_Seek = 0.5;//Use this to Adjust Eye Adaptation Speed
static const float Adapt_Adjust = 0.5;//Use this to Adjust Eye Seeking Radius for Average Brightness.
float lum(float3 RGB){ return dot(RGB, float3(0.2126, 0.7152, 0.0722) );}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
texture TexDepthBuffer : DEPTH;
texture TexBackBuffer : COLOR;
sampler DepthBufferF
{
Texture = TexDepthBuffer;
};
sampler BackBufferF
{
Texture = TexBackBuffer;
};
texture texFlare { Width = BUFFER_WIDTH * 0.25; Height = BUFFER_HEIGHT * 0.25; Format = RGBA16f; };
sampler SamplerGlammor
{
Texture = texFlare;
};
texture TexBC { Width = BUFFER_WIDTH * 0.5; Height = BUFFER_HEIGHT * 0.5; Format = RGBA8; };
sampler SamplerBC
{
Texture = TexBC;
};
texture TexMBB { Width = BUFFER_WIDTH ; Height = BUFFER_HEIGHT ; Format = RGBA8; MipLevels = 8; };
sampler SamplerMBB
{
Texture = TexMBB;
MagFilter = POINT;
MinFilter = POINT;
MipFilter = POINT;
};
texture TexFlarePast { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler SamplerPastFlare
{
Texture = TexFlarePast;
MagFilter = POINT;
MinFilter = POINT;
MipFilter = POINT;
};
void A0(float2 texcoord,float PosX,float PosY,inout float D, inout float E, inout float P, inout float T, inout float H, inout float III, inout float DD )
{
float PosXD = -0.035+PosX, offsetD = 0.001;D = all( abs(float2( texcoord.x -PosXD, texcoord.y-PosY)) < float2(0.0025,0.009));D -= all( abs(float2( texcoord.x -PosXD-offsetD, texcoord.y-PosY)) < float2(0.0025,0.007));
float PosXE = -0.028+PosX, offsetE = 0.0005;E = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.009));E -= all( abs(float2( texcoord.x -PosXE-offsetE, texcoord.y-PosY)) < float2(0.0025,0.007));E += all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.001));
float PosXP = -0.0215+PosX, PosYP = -0.0025+PosY, offsetP = 0.001, offsetP1 = 0.002;P = all( abs(float2( texcoord.x -PosXP, texcoord.y-PosYP)) < float2(0.0025,0.009*0.775));P -= all( abs(float2( texcoord.x -PosXP-offsetP, texcoord.y-PosYP)) < float2(0.0025,0.007*0.680));P += all( abs(float2( texcoord.x -PosXP+offsetP1, texcoord.y-PosY)) < float2(0.0005,0.009));
float PosXT = -0.014+PosX, PosYT = -0.008+PosY;T = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosYT)) < float2(0.003,0.001));T += all( abs(float2( texcoord.x -PosXT, texcoord.y-PosY)) < float2(0.000625,0.009));
float PosXH = -0.0072+PosX;H = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.001));H -= all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.009));H += all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.00325,0.009));
float offsetFive = 0.001, PosX3 = -0.001+PosX;III = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.009));III -= all( abs(float2( texcoord.x -PosX3 - offsetFive, texcoord.y-PosY)) < float2(0.003,0.007));III += all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.001));
float PosXDD = 0.006+PosX, offsetDD = 0.001;DD = all( abs(float2( texcoord.x -PosXDD, texcoord.y-PosY)) < float2(0.0025,0.009));DD -= all( abs(float2( texcoord.x -PosXDD-offsetDD, texcoord.y-PosY)) < float2(0.0025,0.007));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
texture texLumF {Width = 256; Height = 256; Format = R16F; MipLevels = 9;}; //Sample at 256x256 map only has nine mip levels; 0-1-2-3-4-5-6-7-8 : 256,128,64,32,16,8,4,2, and 1 (1x1).
sampler SamplerLumG
{
Texture = texLumF;
};
float LuminanceG(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float2 texXY = texcoord;
float2 midHV = (Adapt_Seek-1) * float2(BUFFER_WIDTH * 0.5,BUFFER_HEIGHT * 0.5) * pix;
texcoord = float2((texXY.x*Adapt_Seek)-midHV.x,(texXY.y*Adapt_Seek)-midHV.y);
return lum(tex2D(BackBufferF,texcoord).rgb);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
texture texAvgLumF { Width = 256; Height = 256; Format = R16F; };
sampler SamplerAvgLumG
{
Texture = texAvgLumF;
};
texture TexAvgLumaLastF { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R16F; };
sampler SamplerAvgLumaLastG
{
Texture = TexAvgLumaLastF;
};
float Average_LuminanceF(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float AA = (1-Adapt_Adjust) * 1000, L = tex2Dlod(SamplerLumG,float4(texcoord,0,11)).x, PL = tex2D(SamplerAvgLumaLastG, texcoord).x;
//Temporal Adaptation
return PL + (L - PL) * (1.0 - exp(-frametime/AA));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float2 DepthMap(float2 texcoord : TEXCOORD0)
{
if (Depth_Map_Flip)
texcoord.y = 1 - texcoord.y;
float zBuffer = tex2Dlod(DepthBufferF, float4(texcoord,0,0)).x,Raw; //Depth Buffer
//Conversions to linear space.....
//Near & Far Adjustment
float Far = 1.0, Near = 0.125/Depth_Map_Adjust,DA = Depth_Map_Adjust*2; //Division Depth Map Adjust - Near
float2 Z = float2( zBuffer, 1-zBuffer );
if (Depth_Map == 0)//DM0. Normal
{
zBuffer = Far * Near / (Far + Z.x * (Near - Far));
Raw = pow(abs(Z.x),DA);
}
else if (Depth_Map == 1)//DM1. Reverse
{
zBuffer = Far * Near / (Far + Z.y * (Near - Far));
Raw = pow(abs(Z.y),DA);
}
return saturate(float2(zBuffer,Raw));
}
float4 BB( float2 texcoord )
{
return tex2Dlod(BackBufferF, float4(texcoord,0,0)).rgba;
}
void ColorBB(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float3 MBB : SV_Target)
{
MBB = BB( texcoord ).rgb;
}
float4 GBightColors( float2 texcoord )
{ float DM = smoothstep(0,1,DepthMap(texcoord).x);
//Forced Depth Masking
if(DM == 1)
DM = 1;
else
DM = 0;
if(!Mask_Sky)
DM = 0;
float4 CM = lerp(tex2Dlod(SamplerMBB,float4(texcoord,0,clamp(Flare_Color_Map,0,8))).rgba,0,DM);
float4 BC = lerp(BB(texcoord),0,DM);
// Check whether fragment output is higher than threshold,if so output as brightness color.
float I_A = lum(BC.rgb), I_B = 1-I_A;
I_A *= I_B >= 1-Flare_Clamp_B;//Trim from Top
BC.a = I_A > lerp(0.9,0.999,Flare_Clamp_A);// ? 1 : 0;
BC.rgb *= BC.a ;
if(Flare_Color_Map > 0)
BC.rgb = CM.rgb * BC.a;
else if(Flare_Color_Map == -1)
BC.rgb *= User_Flare_Color;
if(Flair_Falloff)
BC.rgb = lerp(BC.rgb,0.0,DepthMap(texcoord).y);
//Bloom Saturation
BC.rgb = lerp(lum(BC.rgb),BC.rgb,Flare_Saturation);
float2 Stored_TC = texcoord, FL;
if (Flare_Localization != 0)
{
Stored_TC *= 1.0 - Stored_TC;
float vignette = Stored_TC.x*Stored_TC.y*12.5;
if (Flare_Localization < 0)
FL = float2(0,abs(Flare_Localization));
else
FL = float2(abs(Flare_Localization),1);
vignette = 1-smoothstep(FL.x,FL.y,vignette);
if (Flare_Localization < 0)
vignette = 1-vignette;
BC.rgb = lerp(BC.rgb,0.0,vignette);
}
return float4(saturate(BC.rgb),BC.a);
}
void StoredBB(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float3 BC : SV_Target)
{
BC = GBightColors( texcoord ).rgb;
}
#if !Rend
//Done this way to reduce TempRegisters for DX9 compatablity.
float3 Glammor(sampler2D Sample, float2 texcoord, float N, int Switch, float BBS)
{
float3 GBloom = Switch ? tex2D(Sample,texcoord).rgb : GBightColors(texcoord).rgb;
GBloom *= Weight[0];
[loop]
for(int i = 1; i < N; ++i)
{ float4 offset = float4(OffsetA[i] * pix.xy,OffsetB[i] * pix.xy);
if (Alternate)
offset = float4(OffsetC[i] * pix.xy,OffsetD[i] * pix.xy);
//+ & X
if(Flare_Type == 4 || Flare_Type == 5 || Flare_Type == 6 || Flare_Type == 7)
{
float4 XXZZ = float4( offset.x,-offset.x, offset.z,-offset.z);
float4 YYWW = float4( offset.y,-offset.y, offset.w,-offset.w);
if(Flare_Type == 5 || Flare_Type == 7)
XXZZ = Switch ? 0 : float4(-offset.x, offset.x,-offset.z, offset.z);
if(Flare_Type == 6)
YYWW = Switch ? 0 : float4( offset.y,-offset.y, offset.w,-offset.w);
GBloom += tex2Dlod(Sample, float4(texcoord + float2( XXZZ.x, YYWW.x) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( XXZZ.y, YYWW.y) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( XXZZ.z, YYWW.z) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( XXZZ.w, YYWW.w) * BBS,0,0) ).rgb * Weight[i];
}
else
{
float4 YYXX = Switch ? 0 : float4( offset.y,-offset.y,-offset.x, offset.x);
GBloom += tex2Dlod(Sample, float4(texcoord + float2( offset.x, YYXX.x) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2(-offset.x, YYXX.y) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( YYXX.z, offset.y) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( YYXX.w,-offset.y) * BBS,0,0) ).rgb * Weight[i];
float4 WWZZ = Switch ? 0 : float4( offset.w,-offset.w,-offset.z, offset.z);
GBloom += tex2Dlod(Sample, float4(texcoord + float2( offset.z, WWZZ.x) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2(-offset.z, WWZZ.y) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( WWZZ.z, offset.w) * BBS,0,0) ).rgb * Weight[i];
GBloom += tex2Dlod(Sample, float4(texcoord + float2( WWZZ.w,-offset.w) * BBS,0,0) ).rgb * Weight[i];
}
}
GBloom *= 0.5;
return GBloom;
}
float3 GlammorA(float2 texcoord )
{
float N, BBS = FS;
if(Flare_Type == 0 || Flare_Type == 1 || Flare_Type == 2 || Flare_Type == 6 || Flare_Type == 7)
N = int(lerp(5,25,abs(Flare_Spread)));
else if(Flare_Type == 3 || Flare_Type == 4 || Flare_Type == 5 )
N = 1;
return Glammor(SamplerBC, texcoord, N, 1, BBS);
}
float3 GlammorB(float2 texcoord )
{
float N, BBS = FS;
if(Flare_Type == 0 || Flare_Type == 1 || Flare_Type == 3 || Flare_Type == 4 || Flare_Type == 5 )
N = int(lerp(5,25,abs(Flare_Spread)));
else if(Flare_Type == 2 || Flare_Type == 6 || Flare_Type == 7 )
N = 1;
if(Flare_Type == 1)
BBS *= 0.5;
return Glammor(SamplerBC, texcoord, N, 0, BBS);
}
#else
float3 GlammorA(float2 texcoord )
{ float3 GBloom = tex2D(SamplerBC,texcoord).rgb;
float N, BBS = FS;
GBloom *= Weight[0];
if(Flare_Type == 0 || Flare_Type == 1 || Flare_Type == 2 || Flare_Type == 6 || Flare_Type == 7)
N = 25;
else if(Flare_Type == 3 || Flare_Type == 4 || Flare_Type == 5 )
N = 1;
[unroll]
for(int i = 1; i < N; ++i)
{ float4 offset = float4(OffsetA[i] * pix.xy,OffsetB[i] * pix.xy);
if (Alternate)
offset = float4(OffsetC[i] * pix.xy,OffsetD[i] * pix.xy);
//+
if(Flare_Type == 6)
{
GBloom += tex2D(SamplerBC, texcoord + float2( offset.x, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.x, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.z, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.z, 0) * BBS ).rgb * Weight[i];
}
else if(Flare_Type == 7)
{
GBloom += tex2D(SamplerBC, texcoord + float2( 0, offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0,-offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0, offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0,-offset.w) * BBS ).rgb * Weight[i];
}
else
{
GBloom += tex2D(SamplerBC, texcoord + float2( offset.x, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.x, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0, offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0,-offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.z, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.z, 0) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0, offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( 0,-offset.w) * BBS ).rgb * Weight[i];
}
}
GBloom *= 0.5;
return GBloom;
}
float3 GlammorB(float2 texcoord )
{ float3 GBloom = GBightColors(texcoord).rgb;
float N, BBS = FS;
GBloom *= Weight[0];
if(Flare_Type == 0 || Flare_Type == 1 || Flare_Type == 3 || Flare_Type == 4 || Flare_Type == 5 )
N = 25;
else if(Flare_Type == 2 || Flare_Type == 6 || Flare_Type == 7 )
N = 1;
if(Flare_Type == 1)
BBS *= 0.5;
[unroll]
for(int i = 1; i < N; ++i)
{ float4 offset = float4(OffsetA[i] * pix.xy,OffsetB[i] * pix.xy);
if (Alternate)
offset = float4(OffsetC[i] * pix.xy,OffsetD[i] * pix.xy);
//X
if(Flare_Type == 4)
{
GBloom += tex2D(SamplerBC, texcoord + float2( offset.x, offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.x,-offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.z, offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.z,-offset.w) * BBS ).rgb * Weight[i];
}
else if(Flare_Type == 5)
{
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.x, offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.x,-offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.z, offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.z,-offset.w) * BBS ).rgb * Weight[i];
}
else
{
GBloom += tex2D(SamplerBC, texcoord + float2( offset.x, offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.x,-offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.x, offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.x,-offset.y) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.z, offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.z,-offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2(-offset.z, offset.w) * BBS ).rgb * Weight[i];
GBloom += tex2D(SamplerBC, texcoord + float2( offset.z,-offset.w) * BBS ).rgb * Weight[i];
}
}
GBloom *= 0.5;
return GBloom;
}
#endif
// Spread the blur a bit more.
void Glammor(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float3 GBloom : SV_Target)
{ GBloom = 0;
float GI = Flare_Power, AL = smoothstep(0,1,1. - tex2D(SamplerAvgLumG,0.0).x);
if(Auto_Flare_Intensity)
GI *= AL;
GBloom = ( GlammorA(texcoord) + GlammorB(texcoord) ) * GI;
}
float2 BD(float2 p, float k1) //Polynomial Lens
{
if(!CA_Type == 1)
discard;
p *= 0.5 + 0.5;//Center
// Normalize the u,v coordinates in the range [-1;+1]
p = (2.0f * p - 1.0f) / 1.0f;
// Calculate l2 norm
float r2 = p.x*p.x + p.y*p.y;
float r4 = pow(r2,2);
// Forward transform
float x2 = p.x * (1.0 + k1 * r2);
float y2 = p.y * (1.0 + k1 * r2);
// De-normalize to the original range
p.x = (x2 + 1.0) * 1.0 / 2.0;
p.y = (y2 + 1.0) * 1.0 / 2.0;
return p;
}
float2 HVP(float2 texcoord, float k1)
{
if(!CA_Type == 2)
discard;
float X = k1;
float Y = k1;
float midW = (X - 1)*(BUFFER_WIDTH*0.5)*pix.x;
float midH = (Y - 1)*(BUFFER_HEIGHT*0.5)*pix.y;
return float2((texcoord.x*X)-midW,(texcoord.y*Y)-midH);
}
float2 HP(float2 texcoord, float k1)
{
if(!CA_Type == 3)
discard;
float X = k1;
float Y = 1;
float midW = (X - 1)*(BUFFER_WIDTH*0.5)*pix.x;
float midH = (Y - 1)*(BUFFER_HEIGHT*0.5)*pix.y;
return float2((texcoord.x*X)-midW,(texcoord.y*Y)-midH);
}
float2 VP(float2 texcoord, float k1)
{
if(!CA_Type == 4)
discard;
float X = 1;
float Y = k1;
float midW = (X - 1)*(BUFFER_WIDTH*0.5)*pix.x;
float midH = (Y - 1)*(BUFFER_HEIGHT*0.5)*pix.y;
return float2((texcoord.x*X)-midW,(texcoord.y*Y)-midH);
}
float3 CAFlare(float2 texcoord)
{
float2 uv_red, uv_green, uv_blue;
float DM, color_red, color_green, color_blue, K1_Red = Flare_PBD.x , K1_Green = Flare_PBD.y , K1_Blue = Flare_PBD.z ;
if(CA_Type == 1)
{
uv_red = BD(texcoord.xy,K1_Red * 0.03);
uv_green = BD(texcoord.xy,K1_Green * 0.03);
uv_blue = BD(texcoord.xy,K1_Blue * 0.03);
}
else if(CA_Type == 2)
{
uv_red = HVP(texcoord.xy,1-K1_Red * 0.025);
uv_green = HVP(texcoord.xy,1-K1_Green * 0.025);
uv_blue = HVP(texcoord.xy,1-K1_Blue * 0.025);
}
else if(CA_Type == 3)
{
uv_red = HP(texcoord.xy,1-K1_Red * 0.025);
uv_green = HP(texcoord.xy,1-K1_Green * 0.025);
uv_blue = HP(texcoord.xy,1-K1_Blue * 0.025);
}
else if(CA_Type == 4)
{
uv_red = VP(texcoord.xy,1-K1_Red * 0.025);
uv_green = VP(texcoord.xy,1-K1_Green * 0.025);
uv_blue = VP(texcoord.xy,1-K1_Blue * 0.025);
}
if(CA_Type > 0)
{
color_red = tex2Dlod(SamplerGlammor,float4(uv_red,0,Flare_Softness)).r;
color_green = tex2Dlod(SamplerGlammor,float4(uv_green,0,Flare_Softness)).g;
color_blue = tex2Dlod(SamplerGlammor,float4(uv_blue,0,Flare_Softness)).b;
}
else
{
color_red = tex2Dlod(SamplerGlammor,float4(texcoord,0,Flare_Softness)).r;
color_green = tex2Dlod(SamplerGlammor,float4(texcoord,0,Flare_Softness)).g;
color_blue = tex2Dlod(SamplerGlammor,float4(texcoord,0,Flare_Softness)).b;
}
return float3(color_red,color_green,color_blue);
}
void PS_StoreAvgLumaF(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float Stored : SV_Target0, out float3 Shared : SV_Target1)
{
Stored = tex2D(SamplerAvgLumG,texcoord).x;
Shared = (CAFlare(texcoord) + tex2D(SamplerPastFlare,texcoord).rgb) ;
}
float3 ShaderGlammor(float2 texcoord)
{ float DM;
float3 Color = BB(texcoord).rgb, FBloom = (CAFlare(texcoord) + tex2D(SamplerPastFlare,texcoord).rgb) ;
//Gamma Correction
Color = pow(abs(Color),2.2);
//Bloom
Color = Color + FBloom;
Color = pow(abs(Color),rcp(2.2));
return Color;
}
void Past_Flare(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float3 Stored : SV_Target)
{
Stored = CAFlare(texcoord);
}
void A1(float2 texcoord,float PosX,float PosY,inout float I, inout float N, inout float F, inout float O)
{
float PosXI = 0.0155+PosX, PosYI = 0.004+PosY, PosYII = 0.008+PosY;I = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosY)) < float2(0.003,0.001));I += all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYI)) < float2(0.000625,0.005));I += all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYII)) < float2(0.003,0.001));
float PosXN = 0.0225+PosX, PosYN = 0.005+PosY,offsetN = -0.001;N = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN)) < float2(0.002,0.004));N -= all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN - offsetN)) < float2(0.003,0.005));
float PosXF = 0.029+PosX, PosYF = 0.004+PosY, offsetF = 0.0005, offsetF1 = 0.001;F = all( abs(float2( texcoord.x -PosXF-offsetF, texcoord.y-PosYF-offsetF1)) < float2(0.002,0.004));F -= all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0025,0.005));F += all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0015,0.00075));
float PosXO = 0.035+PosX, PosYO = 0.004+PosY;O = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.003,0.005));O -= all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.002,0.003));
}
////////////////////////////////////////////////////////Watermark/////////////////////////////////////////////////////////////////////////
float4 OutF(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float3 Color = ShaderGlammor(texcoord).rgb;
float PosX = 0.9525f*BUFFER_WIDTH*pix.x,PosY = 0.975f*BUFFER_HEIGHT*pix.y,A,B,C,D,E,F,G,H,I,J,K,L,PosXDot = 0.011+PosX, PosYDot = 0.008+PosY;L = all( abs(float2( texcoord.x -PosXDot, texcoord.y-PosYDot)) < float2(0.00075,0.0015));A0(texcoord,PosX,PosY,A,B,C,D,E,F,G );A1(texcoord,PosX,PosY,H,I,J,K);
return timer <= 12500 ? A+B+C+D+E+F+G+H+I+J+K+L ? 0.02 : float4(Color,1.) : float4(Color,1.);
}
///////////////////////////////////////////////////////////////////ReShade.fxh//////////////////////////////////////////////////////////////////////
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{// Vertex shader generating a triangle covering the entire screen
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}//Using this to make it portable
//*Rendering passes*//
technique Flair
{
pass ColorMap
{
VertexShader = PostProcessVS;
PixelShader = ColorBB;
RenderTarget = TexMBB;
}
pass Past
{
VertexShader = PostProcessVS;
PixelShader = Past_Flare;
RenderTarget = TexFlarePast;
}
pass BrigthColors
{
VertexShader = PostProcessVS;
PixelShader = StoredBB;
RenderTarget = TexBC;
}
pass Star
{
VertexShader = PostProcessVS;
PixelShader = Glammor;
RenderTarget = texFlare;
}
pass Lum
{
VertexShader = PostProcessVS;
PixelShader = LuminanceG;
RenderTarget = texLumF;
}
pass Avg_Lum
{
VertexShader = PostProcessVS;
PixelShader = Average_LuminanceF;
RenderTarget = texAvgLumF;
}
pass StoreAvgLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_StoreAvgLumaF;
RenderTarget0 = TexAvgLumaLastF;
RenderTarget1 = TexFlareShared;
}
#if !exists "DisableFlare.txt"
pass FlareOut
{
VertexShader = PostProcessVS;
PixelShader = OutF;
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ReShade effect file
// visit facebook.com/MartyMcModding for news/updates
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Marty's LUT shader 1.0 for ReShade 3.0
// Copyright © 2008-2016 Marty McFly
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifndef fLUT_TextureName
#define fLUT_TextureName "lut.png"
#endif
#ifndef fLUT_TileSizeXY
#define fLUT_TileSizeXY 32
#endif
#ifndef fLUT_TileAmount
#define fLUT_TileAmount 32
#endif
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "ReShadeUI.fxh"
uniform float fLUT_AmountChroma < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.00; ui_max = 1.00;
ui_label = "LUT chroma amount";
ui_tooltip = "Intensity of color/chroma change of the LUT.";
> = 1.00;
uniform float fLUT_AmountLuma < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.00; ui_max = 1.00;
ui_label = "LUT luma amount";
ui_tooltip = "Intensity of luma change of the LUT.";
> = 1.00;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "ReShade.fxh"
texture texLUT < source = fLUT_TextureName; > { Width = fLUT_TileSizeXY*fLUT_TileAmount; Height = fLUT_TileSizeXY; Format = RGBA8; };
sampler SamplerLUT { Texture = texLUT; };
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PS_LUT_Apply(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 res : SV_Target0)
{
float4 color = tex2D(ReShade::BackBuffer, texcoord.xy);
float2 texelsize = 1.0 / fLUT_TileSizeXY;
texelsize.x /= fLUT_TileAmount;
float3 lutcoord = float3((color.xy*fLUT_TileSizeXY-color.xy+0.5)*texelsize.xy,color.z*fLUT_TileSizeXY-color.z);
float lerpfact = frac(lutcoord.z);
lutcoord.x += (lutcoord.z-lerpfact)*texelsize.y;
float3 lutcolor = lerp(tex2D(SamplerLUT, lutcoord.xy).xyz, tex2D(SamplerLUT, float2(lutcoord.x+texelsize.y,lutcoord.y)).xyz,lerpfact);
color.xyz = lerp(normalize(color.xyz), normalize(lutcolor.xyz), fLUT_AmountChroma) *
lerp(length(color.xyz), length(lutcolor.xyz), fLUT_AmountLuma);
res.xyz = color.xyz;
res.w = 1.0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
technique LUT
{
pass LUT_Apply
{
VertexShader = PostProcessVS;
PixelShader = PS_LUT_Apply;
}
}

View File

@ -0,0 +1,98 @@
/*------------------.
| :: Description :: |
'-------------------/
Layer (version 0.2)
Author: CeeJay.dk
License: MIT
About:
Blends an image with the game.
The idea is to give users with graphics skills the ability to create effects using a layer just like in an image editor.
Maybe they could use this to create custom CRT effects, custom vignettes, logos, custom hud elements, toggable help screens and crafting tables or something I haven't thought of.
Ideas for future improvement:
* More blend modes
* Tiling control
* A default Layer texture with something useful in it
History:
(*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility
Version 0.2 by seri14 & Marot Satil
* Added the ability to scale and move the layer around on XY axis
*/
#include "ReShade.fxh"
#ifndef LAYER_SOURCE
#define LAYER_SOURCE "Layer.png"
#endif
#ifndef LAYER_SIZE_X
#define LAYER_SIZE_X 1280
#endif
#ifndef LAYER_SIZE_Y
#define LAYER_SIZE_Y 720
#endif
#if LAYER_SINGLECHANNEL
#define TEXFORMAT R8
#else
#define TEXFORMAT RGBA8
#endif
#include "ReShadeUI.fxh"
uniform float2 Layer_Pos < __UNIFORM_DRAG_FLOAT2
ui_label = "Layer Position";
ui_min = 0.0; ui_max = 1.0;
ui_step = (1.0 / 200.0);
> = float2(0.5, 0.5);
uniform float Layer_Scale < __UNIFORM_DRAG_FLOAT1
ui_label = "Layer Scale";
ui_min = (1.0 / 100.0); ui_max = 4.0;
ui_step = (1.0 / 250.0);
> = 1.0;
uniform float Layer_Blend < __UNIFORM_COLOR_FLOAT1
ui_label = "Layer Blend";
ui_tooltip = "How much to blend layer with the original image.";
ui_min = 0.0; ui_max = 1.0;
ui_step = (1.0 / 255.0); // for slider and drag
> = 1.0;
texture Layer_Tex <
source = LAYER_SOURCE;
> {
Format = TEXFORMAT;
Width = LAYER_SIZE_X;
Height = LAYER_SIZE_Y;
};
sampler Layer_Sampler
{
Texture = Layer_Tex;
AddressU = BORDER;
AddressV = BORDER;
};
void PS_Layer(float4 pos : SV_Position, float2 texCoord : TEXCOORD, out float4 passColor : SV_Target)
{
const float4 backColor = tex2D(ReShade::BackBuffer, texCoord);
const float2 pixelSize = 1.0 / (float2(LAYER_SIZE_X, LAYER_SIZE_Y) * Layer_Scale / BUFFER_SCREEN_SIZE);
const float4 layer = tex2D(Layer_Sampler, texCoord * pixelSize + Layer_Pos * (1.0 - pixelSize));
passColor = lerp(backColor, layer, layer.a * Layer_Blend);
passColor.a = backColor.a;
}
technique Layer
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_Layer;
}
}

View File

@ -0,0 +1,85 @@
/**
* Levels version 1.2
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Allows you to set a new black and a white level.
* This increases contrast, but clips any colors outside the new range to either black or white
* and so some details in the shadows or highlights can be lost.
*
* The shader is very useful for expanding the 16-235 TV range to 0-255 PC range.
* You might need it if you're playing a game meant to display on a TV with an emulator that does not do this.
* But it's also a quick and easy way to uniformly increase the contrast of an image.
*
* -- Version 1.0 --
* First release
* -- Version 1.1 --
* Optimized to only use 1 instruction (down from 2 - a 100% performance increase :) )
* -- Version 1.2 --
* Added the ability to highlight clipping regions of the image with #define HighlightClipping 1
*/
#include "ReShadeUI.fxh"
uniform int BlackPoint < __UNIFORM_SLIDER_INT1
ui_min = 0; ui_max = 255;
ui_label = "Black Point";
ui_tooltip = "The black point is the new black - literally. Everything darker than this will become completely black.";
> = 16;
uniform int WhitePoint < __UNIFORM_SLIDER_INT1
ui_min = 0; ui_max = 255;
ui_label = "White Point";
ui_tooltip = "The new white point. Everything brighter than this becomes completely white";
> = 235;
uniform bool HighlightClipping <
ui_label = "Highlight clipping pixels";
ui_tooltip = "Colors between the two points will stretched, which increases contrast, but details above and below the points are lost (this is called clipping).\n"
"This setting marks the pixels that clip.\n"
"Red: Some detail is lost in the highlights\n"
"Yellow: All detail is lost in the highlights\n"
"Blue: Some detail is lost in the shadows\n"
"Cyan: All detail is lost in the shadows.";
> = false;
#include "ReShade.fxh"
float3 LevelsPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float black_point_float = BlackPoint / 255.0;
float white_point_float = WhitePoint == BlackPoint ? (255.0 / 0.00025) : (255.0 / (WhitePoint - BlackPoint)); // Avoid division by zero if the white and black point are the same
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
color = color * white_point_float - (black_point_float * white_point_float);
if (HighlightClipping)
{
float3 clipped_colors;
clipped_colors = any(color > saturate(color)) // any colors whiter than white?
? float3(1.0, 0.0, 0.0)
: color;
clipped_colors = all(color > saturate(color)) // all colors whiter than white?
? float3(1.0, 1.0, 0.0)
: clipped_colors;
clipped_colors = any(color < saturate(color)) // any colors blacker than black?
? float3(0.0, 0.0, 1.0)
: clipped_colors;
clipped_colors = all(color < saturate(color)) // all colors blacker than black?
? float3(0.0, 1.0, 1.0)
: clipped_colors;
color = clipped_colors;
}
return color;
}
technique Levels
{
pass
{
VertexShader = PostProcessVS;
PixelShader = LevelsPass;
}
}

View File

@ -0,0 +1,52 @@
/**
* Lift Gamma Gain version 1.1
* by 3an and CeeJay.dk
*/
#include "ReShadeUI.fxh"
uniform float3 RGB_Lift < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.0; ui_max = 2.0;
ui_label = "RGB Lift";
ui_tooltip = "Adjust shadows for red, green and blue.";
> = float3(1.0, 1.0, 1.0);
uniform float3 RGB_Gamma < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.0; ui_max = 2.0;
ui_label = "RGB Gamma";
ui_tooltip = "Adjust midtones for red, green and blue.";
> = float3(1.0, 1.0, 1.0);
uniform float3 RGB_Gain < __UNIFORM_SLIDER_FLOAT3
ui_min = 0.0; ui_max = 2.0;
ui_label = "RGB Gain";
ui_tooltip = "Adjust highlights for red, green and blue.";
> = float3(1.0, 1.0, 1.0);
#include "ReShade.fxh"
float3 LiftGammaGainPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
// -- Lift --
color = color * (1.5 - 0.5 * RGB_Lift) + 0.5 * RGB_Lift - 0.5;
color = saturate(color); // Is not strictly necessary, but does not cost performance
// -- Gain --
color *= RGB_Gain;
// -- Gamma --
color = pow(abs(color), 1.0 / RGB_Gamma);
return saturate(color);
}
technique LiftGammaGain
{
pass
{
VertexShader = PostProcessVS;
PixelShader = LiftGammaGainPass;
}
}

View File

@ -0,0 +1,200 @@
/**
LumaSharpen version 1.5.0
by Christian Cann Schuldt Jensen ~ CeeJay.dk
It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image.
It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts.
This is similar to using Unsharp Mask in Photoshop.
Version 1.5.1
- UI improvements for Reshade 3.x
*/
#include "ReShadeUI.fxh"
uniform float sharp_strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.1; ui_max = 3.0;
ui_label = "Shapening strength";
ui_tooltip = "Strength of the sharpening";
> = 0.65;
uniform float sharp_clamp < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0; ui_step = 0.005;
ui_label = "Sharpening limit";
ui_tooltip = "Limits maximum amount of sharpening a pixel receives\nThis helps avoid \"haloing\" artifacts which would otherwise occur when you raised the strength too much.";
> = 0.035;
uniform int pattern <
ui_type = "combo";
ui_items = "Fast" "\0"
"Normal" "\0"
"Wider" "\0"
"Pyramid shaped" "\0";
ui_label = "Sample pattern";
ui_tooltip = "Choose a sample pattern.\n"
"Fast is faster but slightly lower quality.\n"
"Normal is normal.\n"
"Wider is less sensitive to noise but also to fine details.\n"
"Pyramid has a slightly more aggresive look.";
> = 1;
uniform float offset_bias < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 6.0;
ui_label = "Offset bias";
ui_tooltip = "Offset bias adjusts the radius of the sampling pattern. I designed the pattern for an offset bias of 1.0, but feel free to experiment.";
> = 1.0;
uniform bool show_sharpen <
ui_label = "Show sharpening pattern";
ui_tooltip = "Visualize the strength of the sharpen\nThis is useful for seeing what areas the sharpning affects the most";
> = false;
#include "ReShade.fxh"
/*-----------------------------------------------------------.
/ Developer settings /
'-----------------------------------------------------------*/
#define CoefLuma float3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television)
//#define CoefLuma float3(0.299, 0.587, 0.114) // BT.601 luma coefficient (SD Television)
//#define CoefLuma float3(1.0/3.0, 1.0/3.0, 1.0/3.0) // Equal weight coefficient
/*-----------------------------------------------------------.
/ Main code /
'-----------------------------------------------------------*/
float3 LumaSharpenPass(float4 position : SV_Position, float2 tex : TEXCOORD) : SV_Target
{
// -- Get the original pixel --
float3 ori = tex2D(ReShade::BackBuffer, tex).rgb; // ori = original pixel
// -- Combining the strength and luma multipliers --
float3 sharp_strength_luma = (CoefLuma * sharp_strength); //I'll be combining even more multipliers with it later on
/*-----------------------------------------------------------.
/ Sampling patterns /
'-----------------------------------------------------------*/
float3 blur_ori;
// [ NW, , NE ] Each texture lookup (except ori)
// [ ,ori, ] samples 4 pixels
// [ SW, , SE ]
// -- Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches.
if (pattern == 0)
{
// -- Gaussian filter --
// [ 1/9, 2/9, ] [ 1 , 2 , ]
// [ 2/9, 8/9, 2/9] = [ 2 , 8 , 2 ]
// [ , 2/9, 1/9] [ , 2 , 1 ]
blur_ori = tex2D(ReShade::BackBuffer, tex + (BUFFER_PIXEL_SIZE / 3.0) * offset_bias).rgb; // North West
blur_ori += tex2D(ReShade::BackBuffer, tex + (-BUFFER_PIXEL_SIZE / 3.0) * offset_bias).rgb; // South East
//blur_ori += tex2D(ReShade::BackBuffer, tex + (BUFFER_PIXEL_SIZE / 3.0) * offset_bias); // North East
//blur_ori += tex2D(ReShade::BackBuffer, tex + (-BUFFER_PIXEL_SIZE / 3.0) * offset_bias); // South West
blur_ori /= 2; //Divide by the number of texture fetches
sharp_strength_luma *= 1.5; // Adjust strength to aproximate the strength of pattern 2
}
// -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches.
if (pattern == 1)
{
// -- Gaussian filter --
// [ .25, .50, .25] [ 1 , 2 , 1 ]
// [ .50, 1, .50] = [ 2 , 4 , 2 ]
// [ .25, .50, .25] [ 1 , 2 , 1 ]
blur_ori = tex2D(ReShade::BackBuffer, tex + float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) * 0.5 * offset_bias).rgb; // South East
blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * 0.5 * offset_bias).rgb; // South West
blur_ori += tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * 0.5 * offset_bias).rgb; // North East
blur_ori += tex2D(ReShade::BackBuffer, tex - float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) * 0.5 * offset_bias).rgb; // North West
blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches
}
// -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches.
if (pattern == 2)
{
// -- Gaussian filter --
// [ , 4 , 6 , , ]
// [ ,16 ,24 ,16 , 4 ]
// [ 6 ,24 , ,24 , 6 ]
// [ 4 ,16 ,24 ,16 , ]
// [ , , 6 , 4 , ]
blur_ori = tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * float2(0.4, -1.2) * offset_bias).rgb; // South South East
blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * float2(1.2, 0.4) * offset_bias).rgb; // West South West
blur_ori += tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * float2(1.2, 0.4) * offset_bias).rgb; // East North East
blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * float2(0.4, -1.2) * offset_bias).rgb; // North North West
blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches
sharp_strength_luma *= 0.51;
}
// -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches.
if (pattern == 3)
{
// -- Gaussian filter --
// [ .50, .50, .50] [ 1 , 1 , 1 ]
// [ .50, , .50] = [ 1 , , 1 ]
// [ .50, .50, .50] [ 1 , 1 , 1 ]
blur_ori = tex2D(ReShade::BackBuffer, tex + float2(0.5 * BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y * offset_bias)).rgb; // South South East
blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * -BUFFER_PIXEL_SIZE.x, 0.5 * -BUFFER_PIXEL_SIZE.y)).rgb; // West South West
blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * BUFFER_PIXEL_SIZE.x, 0.5 * BUFFER_PIXEL_SIZE.y)).rgb; // East North East
blur_ori += tex2D(ReShade::BackBuffer, tex + float2(0.5 * -BUFFER_PIXEL_SIZE.x, BUFFER_PIXEL_SIZE.y * offset_bias)).rgb; // North North West
//blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect.
blur_ori /= 4.0; //Divide by the number of texture fetches
sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2
}
/*-----------------------------------------------------------.
/ Sharpen /
'-----------------------------------------------------------*/
// -- Calculate the sharpening --
float3 sharp = ori - blur_ori; //Subtracting the blurred image from the original image
#if 0 //older 1.4 code (included here because the new code while faster can be difficult to understand)
// -- Adjust strength of the sharpening --
float sharp_luma = dot(sharp, sharp_strength_luma); //Calculate the luma and adjust the strength
// -- Clamping the maximum amount of sharpening to prevent halo artifacts --
sharp_luma = clamp(sharp_luma, -sharp_clamp, sharp_clamp); //TODO Try a curve function instead of a clamp
#else //new code
// -- Adjust strength of the sharpening and clamp it--
float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / sharp_clamp),0.5); //Roll part of the clamp into the dot
//sharp_luma = saturate((0.5 / sharp_clamp) * sharp_luma + 0.5); //scale up and clamp
float sharp_luma = saturate(dot(float4(sharp,1.0), sharp_strength_luma_clamp)); //Calculate the luma, adjust the strength, scale up and clamp
sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; //scale down
#endif
// -- Combining the values to get the final sharpened pixel --
float3 outputcolor = ori + sharp_luma; // Add the sharpening to the the original.
/*-----------------------------------------------------------.
/ Returning the output /
'-----------------------------------------------------------*/
if (show_sharpen)
{
//outputcolor = abs(sharp * 4.0);
outputcolor = saturate(0.5 + (sharp_luma * 4.0)).rrr;
}
return saturate(outputcolor);
}
technique LumaSharpen
{
pass
{
VertexShader = PostProcessVS;
PixelShader = LumaSharpenPass;
}
}

View File

@ -0,0 +1,625 @@
////////////////////////////////////////////////////////////
// BASIC MACROS FOR RESHADE 4 //
// AUTHOR: TREYM //
////////////////////////////////////////////////////////////
// Modified by dddfault //
// //
// Changelogs : //
// Added Sampler texture boundary resolver option //
// Added float2 parameters option //
////////////////////////////////////////////////////////////
// Macros Guide: //
////////////////////////////////////////////////////////////
/* //////////////////////////////////////////////////// *
* //////////////////////////////////////////////////// *
Usage of these macros is very simple once you understand
the syntax and variable names. Let's start with a Simple
integer slider. To begin, type:
UI_INT
Next we need to add _S to indicate that this is a
"slider" widget. Follow the syntax below:
UI_INT_S(INT_NAME, "Label", "Tooltip", 0, 100, 50)
Using just a single line of code, we have created a UI
tweakable integer named INT_NAME with a minimum value of
0, a maximum value of 100, and a default value of 50.
Next, let's create that same widget, but within a UI
category. This time, we'll type:
CAT_INT_S(INT_NAME, "Category", "Label", "Tooltip", 0, 100, 50)
As you can see, the syntax follows the same pattern but
with a new input for "Category"
Below you will find a useful list of examples to get you
started. I hope you find these useful and they help your
workflow. Happy coding!
- TreyM
* //////////////////////////////////////////////////// *
* //////////////////////////////////////////////////// *
Widget Types
Input = _I
Slider = _S
Drag = _D
* //////////////////////////////////////////////////// *
BOOLEAN Macro
UI_BOOL(BOOL_NAME, "Label", "Tooltip", true)
BOOLEAN Categorized Macro
CAT_BOOL(BOOL_NAME, "Category", "Label", "Tooltip", true)
* //////////////////////////////////////////////////// *
INTEGER Combo Widget
UI_COMBO(INT_NAME, "Label", "Tooltip", 0, 2, 0, "Item 1\0Item 2\0Item 3\0")
INTEGER Drag Widget
UI_INT_D(INT_NAME, "Label", "Tooltip", 0, 100, 50)
INTEGER Input Widget
UI_INT_I(INT_NAME, "Label", "Tooltip", 0, 100, 50)
INTEGER Radio Widget
UI_RADIO(INT_NAME, "Label", "Tooltip", 0, 2, 0, " Item 1 \0 Item 2 \0 Item 3\0")
INTEGER Slider Widget
UI_INT_S(INT_NAME, "Label", "Tooltip", 0, 100, 50)
INTEGER Categorized Combo Widget
CAT_COMBO(INT_NAME, "Category", "Label", "Tooltip", 0, 2, 0, " Item 1 \0 Item 2 \0 Item 3\0")
INTEGER Categorized Drag Widget
CAT_INT_D(INT_NAME, "Category", "Label", "Tooltip", 0, 100, 50)
INTEGER Categorized Input Widget
CAT_INT_I(INT_NAME, "Category", "Label", "Tooltip", 0, 100, 50)
INTEGER Categorized Radio Widget
CAT_RADIO(INT_NAME, "Category", "Label", "Tooltip", 0, 2, 0, " Item 1 \0 Item 2 \0 Item 3\0")
INTEGER Categorized Slider Widget
CAT_INT_S(INT_NAME, "Category", "Label", "Tooltip", 0, 100, 50)
* //////////////////////////////////////////////////// *
FLOAT Drag Widget
UI_FLOAT_D(FLOAT_NAME, "Label", "Tooltip", 0.0, 1.0, 0.5)
FLOAT Input Widget
UI_FLOAT_I(FLOAT_NAME, "Label", "Tooltip", 0.0, 1.0, 0.5)
FLOAT Slider Widget
UI_FLOAT_S(FLOAT_NAME, "Label", "Tooltip", 0.0, 1.0, 0.5)
FLOAT Categorized Drag Widget
CAT_FLOAT_D(FLOAT_NAME, "Category", "Label", "Tooltip", 0.0, 1.0, 0.5)
FLOAT Categorized Input Widget
CAT_FLOAT_I(FLOAT_NAME, "Category", "Label", "Tooltip", 0.0, 1.0, 0.5)
FLOAT Categorized Slider Widget
CAT_FLOAT_S(FLOAT_NAME, "Category", "Label", "Tooltip", 0.0, 1.0, 0.5)
FLOAT macro with full control (value after "Tooltip" is ui_step)
UI_FLOAT_FULL(FLOAT_NAME, "ui_type", "Label", "Tooltip", 0.1, 0.0, 1.0, 0.5)
FLOAT Categorized macro with full control (value after "Tooltip" is ui_step)
CAT_FLOAT_FULL(FLOAT_NAME, "ui_type", "Category", "Label", "Tooltip", 0.1, 0.0, 1.0, 0.5)
* //////////////////////////////////////////////////// *
FLOAT2 Drag Widget
UI_FLOAT2_D(FLOAT_NAME, "Label", "Tooltip", 0.0, 1.0, 0.5, 0.5)
FLOAT2 Input Widget
UI_FLOAT2_I(FLOAT_NAME, "Label", "Tooltip", 0.0, 1.0, 0.5, 0.5)
FLOAT2 Slider Widget
UI_FLOAT2_S(FLOAT_NAME, "Label", "Tooltip", 0.0, 1.0, 0.5, 0.5)
FLOAT2 Categorized Drag Widget
CAT_FLOAT2_D(FLOAT_NAME, "Category", "Label", "Tooltip", 0.0, 1.0, 0.5, 0.5)
FLOAT2 Categorized Input Widget
CAT_FLOAT2_I(FLOAT_NAME, "Category", "Label", "Tooltip", 0.0, 1.0, 0.5, 0.5)
FLOAT2 Categorized Slider Widget
CAT_FLOAT2_S(FLOAT_NAME, "Category", "Label", "Tooltip", 0.0, 1.0, 0.5, 0.5)
FLOAT2 macro with full control (value after "Tooltip" is ui_step)
UI_FLOAT2_FULL(FLOAT_NAME, "ui_type", "Label", "Tooltip", 0.1, 0.0, 1.0, 0.5, 0.5)
FLOAT2 Categorized macro with full control (value after "Tooltip" is ui_step)
CAT_FLOAT2_FULL(FLOAT_NAME, "ui_type", "Category", "Label", "Tooltip", 0.1, 0.0, 1.0, 0.5, 0.5)
* //////////////////////////////////////////////////// *
FLOAT3 Drag Widget
UI_FLOAT3_D(FLOAT_NAME, "Label", "Tooltip", 0.5, 0.5, 0.5)
FLOAT3 Input Widget
UI_FLOAT3_I(FLOAT_NAME, "Label", "Tooltip", 0.5, 0.5, 0.5)
FLOAT3 Slider Widget
UI_FLOAT3_S(FLOAT_NAME, "Label", "Tooltip", 0.5, 0.5, 0.5)
FLOAT3 Categorized Drag Widget
CAT_FLOAT3_D(FLOAT_NAME, "Category", "Label", "Tooltip", 0.5, 0.5, 0.5)
FLOAT3 Categorized Input Widget
CAT_FLOAT3_I(FLOAT_NAME, "Category", "Label", "Tooltip", 0.5, 0.5, 0.5)
FLOAT3 Categorized Slider Widget
CAT_FLOAT3_S(FLOAT_NAME, "Category", "Label", "Tooltip", 0.5, 0.5, 0.5)
* //////////////////////////////////////////////////// *
FLOAT3 Color Widget
UI_COLOR(FLOAT_NAME, "Label", "Tooltip", 0.5, 0.5, 0.5)
FLOAT3 Categorized Color Widget
CAT_COLOR(FLOAT_NAME, "Category", "Label", "Tooltip", 0.5, 0.5, 0.5)
* //////////////////////////////////////////////////// *
SAMPLER Macro
SAMPLER(SamplerName, TextureName)
SAMPLER Macro with texture boundary resolver option
SAMPLER_UV(SamplerName, TextureName, ResolverType)
TEXTURE Macro
TEXTURE(TextureName, "TexturePath")
TEXTURE Full Macro
TEXTURE_FULL(TextureName, "TexturePath", Width, Height, Format)
* //////////////////////////////////////////////////// *
TECHNIQUE Macro
TECHNIQUE(TechniqueName, PassMacro)
PASS Macro
PASS(PassID, VertexShader, PixelShader)
PASS Macro with RenderTarget
PASS_RT(PassID, VertexShader, PixelShader, RenderTarget)
////////////////////////////////////////////////////
* //////////////////////////////////////////////////// */
// INTEGER MACROS ////////////////////////////////
#define UI_COMBO(var, label, tooltip, minval, maxval, defval, items) \
uniform int var \
< \
ui_type = "combo"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_items = items; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_COMBO(var, category, label, tooltip, minval, maxval, defval, items) \
uniform int var \
< \
ui_type = "combo"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_items = items; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_INT_I(var, label, tooltip, minval, maxval, defval) \
uniform int var \
< \
ui_type = "input"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_INT_I(var, category, label, tooltip, minval, maxval, defval) \
uniform int var \
< \
ui_type = "input"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_INT_S(var, label, tooltip, minval, maxval, defval) \
uniform int var \
< \
ui_type = "slider"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_INT_S(var, category, label, tooltip, minval, maxval, defval) \
uniform int var \
< \
ui_type = "slider"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_INT_D(var, label, tooltip, minval, maxval, defval) \
uniform int var \
< \
ui_type = "drag"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_INT_D(var, category, label, tooltip, minval, maxval, defval) \
uniform int var \
< \
ui_type = "drag"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_RADIO(var, label, tooltip, minval, maxval, defval, items) \
uniform int var \
< \
ui_type = "radio"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_items = items; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_RADIO(var, category, label, tooltip, minval, maxval, defval, items) \
uniform int var \
< \
ui_type = "radio"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_items = items; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
// BOOL MACROS ///////////////////////////////////
#define UI_BOOL(var, label, tooltip, def) \
uniform bool var \
< \
ui_label = label; \
ui_tooltip = tooltip; \
> = def;
#define CAT_BOOL(var, category, label, tooltip, def) \
uniform bool var \
< \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
> = def;
// FLOAT MACROS //////////////////////////////////
#define UI_FLOAT_D(var, label, tooltip, minval, maxval, defval) \
uniform float var \
< \
ui_type = "drag"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_FLOAT_D(var, category, label, tooltip, minval, maxval, defval) \
uniform float var \
< \
ui_type = "drag"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_FLOAT_FULL(var, uitype, label, tooltip, uistep, minval, maxval, defval) \
uniform float var \
< \
ui_type = uitype; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_step = uistep; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_FLOAT_FULL(var, uitype, category, label, tooltip, uistep, minval, maxval, defval) \
uniform float var \
< \
ui_type = uitype; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_step = uistep; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_FLOAT_I(var, label, tooltip, minval, maxval, defval) \
uniform float var \
< \
ui_type = "input"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_FLOAT_I(var, category, label, tooltip, minval, maxval, defval) \
uniform float var \
< \
ui_type = "input"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_FLOAT_S(var, label, tooltip, minval, maxval, defval) \
uniform float var \
< \
ui_type = "slider"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define CAT_FLOAT_S(var, category, label, tooltip, minval, maxval, defval) \
uniform float var \
< \
ui_type = "slider"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = defval;
#define UI_FLOAT2_D(var, label, tooltip, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = "drag"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define CAT_FLOAT2_D(var, category, label, tooltip, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = "drag"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define UI_FLOAT2_FULL(var, uitype, label, tooltip, uistep, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = uitype; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_step = uistep; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define CAT_FLOAT2_FULL(var, uitype, category, label, tooltip, uistep, minval, defval1, defval2) \
uniform float2 var \
< \
ui_type = uitype; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_step = uistep; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define UI_FLOAT2_I(var, label, tooltip, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = "input"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define CAT_FLOAT2_I(var, category, label, tooltip, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = "input"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define UI_FLOAT2_S(var, label, tooltip, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = "slider"; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define CAT_FLOAT2_S(var, category, label, tooltip, minval, maxval, defval1, defval2) \
uniform float2 var \
< \
ui_type = "slider"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
ui_min = minval; \
ui_max = maxval; \
> = float2(defval1, defval2);
#define UI_FLOAT3_D(var, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "drag"; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
#define CAT_FLOAT3_D(var, category, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "drag"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
#define UI_FLOAT3_I(var, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "input"; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
#define CAT_FLOAT3_I(var, category, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "input"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
#define UI_FLOAT3_S(var, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "slider"; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
#define CAT_FLOAT3_S(var, category, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "slider"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
// COLOR WIDGET MACROS ///////////////////////////
#define UI_COLOR(var, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "color"; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
#define CAT_COLOR(var, category, label, tooltip, defval1, defval2, defval3) \
uniform float3 var \
< \
ui_type = "color"; \
ui_category = category; \
ui_label = label; \
ui_tooltip = tooltip; \
> = float3(defval1, defval2, defval3);
// SAMPLER MACRO /////////////////////////////////
#define SAMPLER(sname, tname) \
sampler sname \
{ \
Texture = tname; \
};
#define SAMPLER_UV(sname, tname, addUVW) \
sampler sname \
{ \
Texture = tname; \
AddressU = addUVW; \
AddressV = addUVW; \
AddressW = addUVW; \
};
// TEXTURE MACROs ////////////////////////////////
#define TEXTURE(tname, src) \
texture tname <source=src;> \
{ \
Width = BUFFER_WIDTH; \
Height = BUFFER_HEIGHT; \
Format = RGBA8; \
};
#define TEXTURE_FULL(tname, src, width, height, fomat) \
texture tname <source=src;> \
{ \
Width = width; \
Height = height; \
Format = fomat; \
};
// TECHNIQUE MACROS //////////////////////////////
#define TECHNIQUE(tname, pass) \
technique tname \
{ \
pass \
}
#define PASS(ID, vs, ps) pass \
{ \
VertexShader = vs; \
PixelShader = ps; \
}
#define PASS_RT(ID, vs, ps, rt) pass \
{ \
VertexShader = vs; \
PixelShader = ps; \
RenderTarget = rt; \
}

View File

@ -0,0 +1,131 @@
/*------------------.
| :: Description :: |
'-------------------/
Monochrome (version 1.1)
Author: CeeJay.dk
License: MIT
About:
Removes color making everything monochrome.
Ideas for future improvement:
* Tinting
* Select a hue to keep its color, thus making it stand out against a monochrome background
* Try Lab colorspace
* Apply color gradient
* Add an option to normalize the coefficients
* Publish best-selling book titled "256 shades of grey"
History:
(*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility
Version 1.0
* Converts image to monochrome
* Allows users to add saturation back in.
Version 1.1
* Added many presets based on B/W camera films
+ Improved settings UI
! Made settings backwards compatible with SweetFX
*/
/*---------------.
| :: Includes :: |
'---------------*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
uniform int Monochrome_preset <
ui_type = "combo";
ui_label = "Preset";
ui_tooltip = "Choose a preset";
//ui_category = "";
ui_items = "Custom\0"
"Monitor or modern TV\0"
"Equal weight\0"
"Agfa 200X\0"
"Agfapan 25\0"
"Agfapan 100\0"
"Agfapan 400\0"
"Ilford Delta 100\0"
"Ilford Delta 400\0"
"Ilford Delta 400 Pro & 3200\0"
"Ilford FP4\0"
"Ilford HP5\0"
"Ilford Pan F\0"
"Ilford SFX\0"
"Ilford XP2 Super\0"
"Kodak Tmax 100\0"
"Kodak Tmax 400\0"
"Kodak Tri-X\0";
> = 0;
uniform float3 Monochrome_conversion_values < __UNIFORM_COLOR_FLOAT3
ui_label = "Custom Conversion values";
> = float3(0.21, 0.72, 0.07);
/*
uniform bool Normalize <
ui_label = "Normalize";
ui_tooltip = "Normalize the coefficients?";
> = false;
*/
uniform float Monochrome_color_saturation < __UNIFORM_SLIDER_FLOAT1
ui_label = "Saturation";
ui_min = 0.0; ui_max = 1.0;
> = 0.0;
float3 MonochromePass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
float3 Coefficients = float3(0.21, 0.72, 0.07);
float3 Coefficients_array[18] =
{
Monochrome_conversion_values, //Custom
float3(0.21, 0.72, 0.07), //sRGB monitor
float3(0.3333333, 0.3333334, 0.3333333), //Equal weight
float3(0.18, 0.41, 0.41), //Agfa 200X
float3(0.25, 0.39, 0.36), //Agfapan 25
float3(0.21, 0.40, 0.39), //Agfapan 100
float3(0.20, 0.41, 0.39), //Agfapan 400
float3(0.21, 0.42, 0.37), //Ilford Delta 100
float3(0.22, 0.42, 0.36), //Ilford Delta 400
float3(0.31, 0.36, 0.33), //Ilford Delta 400 Pro & 3200
float3(0.28, 0.41, 0.31), //Ilford FP4
float3(0.23, 0.37, 0.40), //Ilford HP5
float3(0.33, 0.36, 0.31), //Ilford Pan F
float3(0.36, 0.31, 0.33), //Ilford SFX
float3(0.21, 0.42, 0.37), //Ilford XP2 Super
float3(0.24, 0.37, 0.39), //Kodak Tmax 100
float3(0.27, 0.36, 0.37), //Kodak Tmax 400
float3(0.25, 0.35, 0.40) //Kodak Tri-X
};
Coefficients = Coefficients_array[Monochrome_preset];
// Calculate monochrome
float3 grey = dot(Coefficients, color);
// Adjust the remaining saturation
color = lerp(grey, color, Monochrome_color_saturation);
// Return the result
return saturate(color);
}
technique Monochrome
{
pass
{
VertexShader = PostProcessVS;
PixelShader = MonochromePass;
}
}

View File

@ -0,0 +1,357 @@
////-------------//
///**NFAA Fast**///
//-------------////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Normal Filter Anti Aliasing.
//* For ReShade 3.0+ & Freestyle
//* ---------------------------------
//* NFAA
//* Due Diligence
//* Based on port by b34r
//* https://www.gamedev.net/forums/topic/580517-nfaa---a-post-process-anti-aliasing-filter-results-implementation-details/?page=2
//* Later rewritten by Eric B. AKA Kourinn
//* https://github.com/BlueSkyDefender/AstrayFX/pull/17
//* If I missed any please tell me.
//*
//* LICENSE
//* ============
//* Normal Filter Anti Aliasing is licenses under: Attribution-NoDerivatives 4.0 International
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format
//* for any purpose, even commercially.
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* NoDerivatives - If you remix, transform, or build upon the material, you may not distribute the modified material.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by-nd/4.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define BUFFER_PIXEL_SIZE float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define BUFFER_ASPECT_RATIO (BUFFER_WIDTH * BUFFER_RCP_HEIGHT)
uniform int EdgeDetectionType <
ui_type = "combo";
ui_items = "Luminance edge detection\0Perceived Luminance edge detection\0Color edge detection\0Perceived Color edge detection\0";
ui_label = "Edge Detection Type";
> = 3;
uniform float EdgeDetectionThreshold <
ui_type = "drag";
ui_label = "Edge Detection Threshold";
ui_tooltip = "The difference in Luminence/Color that would be perceived as an edge.\n"
"Try lowering this slightly if the Edge Mask misses some edges.\n"
"Default is 0.063";
ui_min = 0.050; ui_max = 0.200; ui_step = 0.001;
> = 0.100;
uniform float EdgeSearchRadius <
ui_type = "drag";
ui_label = "Edge Search Radius";
ui_tooltip = "The radius to search for edges.\n"
"Try raising this if using in-game upscaling.\n"
"Default is 1.000";
ui_min = 0.000; ui_max = 4.000; ui_step = 0.001;
> = 1.000;
uniform float UnblurFilterStrength <
ui_type = "drag";
ui_label = "Unblur Filter Strength";
ui_tooltip = "Adjusts the Edge Mask and Corner Mask contrast for filtering unwanted edge blur.\n"
"Try raising this if text or icons become blurry.\n"
"Try lowering this if edges are still too aliased.\n"
"Default is 1.000";
ui_min = 0.000; ui_max = 2.000; ui_step = 0.001;
> = 1.000;
uniform float BlurStrength <
ui_type = "drag";
ui_label = "Blur Strength";
ui_tooltip = "Adjusts the Normal Map weights for stronger edge blur.\n"
"Try raising this if edges are still too aliased.\n"
"Try lowering this if text or icons become blurry.\n"
"Default is 1.000";
ui_min = 0.000; ui_max = 2.000; ui_step = 0.001;
> = 1.000;
uniform float2 BlurSize <
ui_type = "drag";
ui_label = "Blur Size";
ui_tooltip = "Adjusts the Normal Map depth for larger/longer edge blur.\n"
"Inputs are blur size parallel and perpendicular to the edge respectively.\n"
"Try raising this if edges are still too aliased.\n"
"Try lowering this if text or icons become blurry.\n"
"Defaults are 2.000 and 1.000";
ui_min = 0.000; ui_max = 4.000; ui_step = 0.001;
> = float2(2.000, 1.000);
uniform int DebugOutput <
ui_type = "combo";
ui_label = "Debug Output";
ui_items = "None\0Edge Mask View\0Corner Mask View\0Normal Map View\0Pre-Blur Mask View\0Post-Blur Mask View\0";
ui_tooltip = "Edge Mask View shows the Edge Detection and Unblur Filter Strength.\n"
"Corner Mask View shows the Corner Detection and Unblur Filter Strength.\n"
"Normal Map View shows the Normal Map depth, used for Blur Size and Blur Direction.\n"
"Pre-Blur Mask View shows just the edges that will be blurred.\n"
"Post-Blur Mask View shows just the edges have been blurred.";
ui_spacing = 2;
> = 0;
////////////////////////////////////////////////////////////Variables////////////////////////////////////////////////////////////////////
// sRGB Luminance
static const float3 LinearizeVector[4] = { float3(0.2126, 0.7152, 0.0722), float3(0.299, 0.587, 0.114), float3(0.3333333, 0.3333333, 0.3333333), float3(0.299, 0.587, 0.114) };
static const float Cos45 = 0.70710678118654752440084436210485;
static const float MaxSlope = 1024.0;
texture BackBufferTex : COLOR;
sampler BackBuffer { Texture = BackBufferTex; };
////////////////////////////////////////////////////////////Functions////////////////////////////////////////////////////////////////////
float LinearDifference(float3 A, float3 B)
{
float lumDiff = dot(A, LinearizeVector[EdgeDetectionType]) - dot(B, LinearizeVector[EdgeDetectionType]);
if (EdgeDetectionType < 2)
return lumDiff;
float3 C = abs(A - B);
return max(max(C.r, C.g), C.b) * (lumDiff < 0.0 ? -1.0 : 1.0); // sign intrinsic can return 0, which we don't want. Plus this is faster.
}
float2 Rotate45(float2 p) {
return float2(mad(p.x, Cos45, -p.y * Cos45), mad(p.x, Cos45, p.y * Cos45));
// return float2(p.x * Cos45 - p.y * Cos45, p.x * Cos45 + p.y * Cos45);
}
////////////////////////////////////////////////////////////NFAA////////////////////////////////////////////////////////////////////
float4 NFAA(float2 texcoord, float4 offsets[4])
{
float4 color = tex2Dlod(BackBuffer, float4(texcoord, 0.0, 0.0));
// Find Edges
// +---+---+---+---+---+
// | | | | | |
// +---+---+---+---+---+
// | | e | f | g | |
// +---+--(a)-(b)--+---+
// | | h | P | i | |
// +---+--(c)-(d)--+---+
// | | j | k | l | |
// +---+---+---+---+---+
// | | | | | |
// +---+---+---+---+---+
// Much better at horizontal/vertical lines, slightly better diagonals, always compares 6 pixels, not 2.
float3 a = tex2Dlod(BackBuffer, offsets[0]).rgb;
float3 b = tex2Dlod(BackBuffer, offsets[1]).rgb;
float3 c = tex2Dlod(BackBuffer, offsets[2]).rgb;
float3 d = tex2Dlod(BackBuffer, offsets[3]).rgb;
// Original edge detection from b34r & BlueSkyDefender
// +---+---+---+---+---+
// | | | | | |
// +---+---+---+---+---+
// | | | t | | |
// +---+---+---+---+---+
// | | l | C | r | |
// +---+---+---+---+---+
// | | | b | | |
// +---+---+---+---+---+
// | | | | | |
// +---+---+---+---+---+
// float angle = 0.0;
// float3 t = tex2Dlod(BackBuffer, float4(mad(float2(0.0, -EdgeSearchRadius), BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
// float3 b = tex2Dlod(BackBuffer, float4(mad(float2(-0.0, EdgeSearchRadius), BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
// float3 r = tex2Dlod(BackBuffer, float4(mad(float2(EdgeSearchRadius, 0.0), BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
// float3 l = tex2Dlod(BackBuffer, float4(mad(float2(-EdgeSearchRadius, 0.0), BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
// float2 n = float2(LinearDifference(t, b), LinearDifference(r, l));
// i.e. top vs bottom = a + b - (c + d) = (e + 2*f + g) / 4 - (j + 2*k + l) / 4
float2 normal = float2(LinearDifference(b + d, a + c), LinearDifference(c + d, a + b)); // right - left, bottom - top
float edge = length(normal);
float edgeMask = 1.0;
float cornerMask = 1.0;
if (edge > EdgeDetectionThreshold)
{
// Lets make that edgeMask for a sharper image.
float edgeConfidence = log2(edge / EdgeDetectionThreshold);
edgeMask = saturate(mad(edgeConfidence, UnblurFilterStrength - 2.0, 1.0));
// edgeMask = saturate((1.0 - (UnblurFilterStrength - 2.0) * edgeConfidence);
// Then subtract corners from edge mask to avoid bluring text and detailed icons
float4 corners = float4(LinearDifference(a + b + c, 3.0 * d), LinearDifference(a + b + d, 3.0 * c), LinearDifference(a + c + d, 3.0 * b), LinearDifference(c + d + b, 3.0 * a));
float corner = dot(abs(corners), 0.25);
cornerMask = saturate(edgeMask + corner);
// calculate x/y coordinates along the edge at specified distances and offsets
// +---+---+---+---+---+ +---+---+---+---+---+
// | | | | | | | | | | | |
// +---+---+---+---+---+ +---+---+---+---+---+
// | | | | | | | | | (e) | |
// +---+(g)a---b(e)+---+ +---+---a---b(f)+---+
// | |-O | P | O | | | | | P | | |
// +---+(h)c---d(f)+---+ +---+(g)c---d---+---+
// | | | | | | | | (h) | | |
// +---+---+---+---+---+ +---+---+---+---+---+
// | | | | | | | | | | | |
// +---+---+---+---+---+ +---+---+---+---+---+
// slope m = normal.r / normal.g
// distance d
// y = mx
// d^2 = y^2 + x^2 = (mx)^2+x^2
// d^2 = x^2(1 + m^2)
// x^2 = d^2/(1 + m^2)
// Follow the edge for 1/2 of BlurSize.x
float4 offset;
float m = normal.g != 0 ? normal.r / normal.g : MaxSlope;
float d = 0.5 * BlurSize.x;
offset.x = sqrt(d *d / (1.0 + m * m));
offset.y = m * offset.x;
// Then move perpendicular to the edge for 1/2 of BlurSize.y
m = normal.r != 0 ? -normal.g / normal.r : MaxSlope;
d = 0.5 * BlurSize.y;
offset.z = sqrt(d * d / (1.0 + m * m));
offset.w = m * offset.z;
float3 e = tex2Dlod(BackBuffer, float4(mad(offset.xy + offset.zw, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
float3 f = tex2Dlod(BackBuffer, float4(mad(offset.xy - offset.zw, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
float3 g = tex2Dlod(BackBuffer, float4(mad(-offset.xy - offset.zw, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
float3 h = tex2Dlod(BackBuffer, float4(mad(-offset.xy + offset.zw, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0)).rgb;
// It's possible to reduce taps by re-using edge detection taps a, b, c, d,
// but it's not worth it. Nearby pixels should already be cached, and it would need more math.
// apply blur
if (DebugOutput != 4)
color.rgb = lerp(color.rgb, (e + f + g + h) * 0.25, BlurStrength * 0.5 * (1.0 - cornerMask));
// Pre/Post Blur Mask
if (DebugOutput > 3)
color.a = cornerMask;
// original blur from b34r & BlueSkyDefender
// may need some work to be functional again, due to some variable name refactoring after I reversed how/why it worked
// +---+---+---+---+---+
// | | | | | |
// +---+---+---+---+---+
// |\\\| | x | x | |
// +---+---+---+---+---+
// | |\\\|\\\| x | |
// +---+---+---+---+---+
// | | | x |\\\|\\\|
// +---+---+---+---+---+
// | | | | | |
// +---+---+---+---+---+
// y = -0.5x; n.x = 1; n.y = 0.5; nl = 1.18; dn.x = 0.85; dn.y = 0.42;
// t0/1 = 0.425, 0.21; d ~= 0.5
// t2/3 = 0.765, -0.38; d ~= 0.85
// float2 dn = n / nl * BlurSize;
// float4 t0 = tex2Dlod(BackBuffer, float4(mad(-dn * 0.5, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0));
// float4 t1 = tex2Dlod(BackBuffer, float4(mad(dn * 0.5, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0));
// float4 t2 = tex2Dlod(BackBuffer, float4(mad(float2(dn.x, -dn.y) * 0.9, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0));
// float4 t3 = tex2Dlod(BackBuffer, float4(mad(float2(-dn.x, dn.y) * 0.9, BUFFER_PIXEL_SIZE, texcoord), 0.0, 0.0));
// color = lerp(mad(color, 0.23, 0.175 * (t2 + t3) + 0.21 * (t0 + t1)), color, edgeMask);
}
else {
color.a = 0.0;
}
if(DebugOutput == 1) // Edge Mask
{
color.rgb = edgeMask;
}
if(DebugOutput == 2) // Corner Mask
{
color.rgb = cornerMask;
}
else if (DebugOutput == 3) // Normal Map
{
// Normal map, right = red, green = top, configured using white box with black background
float3 normalMap;
normalMap.b = 1.0;
normalMap.rg = mad(float2(-normal.r, normal.g) * BlurSize.x * BlurStrength, 0.25, 0.5);
normalMap.rg = lerp(float2(0.5, 0.5), saturate(normalMap.rg), (1.0 - edgeMask) * BlurSize.y);
color.rgb = normalMap;
}
else if (DebugOutput > 3) { // Pre/Post Blur Mask
uint row = floor(texcoord.y / 0.1);
uint col = floor(texcoord.x * BUFFER_ASPECT_RATIO / 0.1);
float3 lightGray = 0.5;
float3 darkGray = 0.1667;
lightGray = lerp(lightGray, color.rgb, color.a);
darkGray = lerp(darkGray, color.rgb, color.a);
// Create checkerboad background to depict transparency
if (row % 2 == 0) {
if (col % 2 == 0) {
color.rgb = lightGray;
}
else {
color.rgb = darkGray;
}
}
else {
if (col % 2 == 0) {
color.rgb = darkGray;
}
else {
color.rgb = lightGray;
}
}
}
color.a = 1.0;
return color;
}
void NFAA_VS(in uint id : SV_VertexID, out float4 position : SV_POSITION, out float2 texcoord : TEXCOORD, out float4 offsets[4] : TEXCOORD1 )
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
float2 offset = Cos45 * EdgeSearchRadius * BUFFER_PIXEL_SIZE;
offsets[0] = float4(mad(float2(-1.0, -1.0), offset, texcoord), 0.0, 0.0);
offsets[1] = float4(mad(float2(1.0, -1.0), offset, texcoord), 0.0, 0.0);
offsets[2] = float4(mad(float2(-1.0, 1.0), offset, texcoord), 0.0, 0.0);
offsets[3] = float4(mad(float2(1.0, 1.0), offset, texcoord), 0.0, 0.0);
}
float4 NFAA_PS(in float4 position : SV_Position, in float2 texcoord : TEXCOORD, in float4 offsets[4] : TEXCOORD1) : SV_Target
{
return NFAA(texcoord, offsets);
}
technique NFAA
{
pass NFAA_Fast
{
VertexShader = NFAA_VS;
PixelShader = NFAA_PS;
}
}

View File

@ -0,0 +1,602 @@
/*------------------.
| :: Description :: |
'-------------------/
Nostalgia (version 1.3)
Author: CeeJay.dk
License: MIT
About:
In this effect I try to recreate the looks of systems from a bygone era.
I've started with reducing the color to that of systems with 16 color palette.
Ideas for future improvement:
* Try HSL / HCY / Lab or other colorspaces. I'm not sure RGB is the best choice for color matching.
* Pixelation
* Scanlines
* CRT patterns
* Curvature
* More Dithering (both good and the bad dithering used back then)
* Levels (might be needed because older system were often displayed on televisions and older monitors - not modern monitors)
History:
(*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility
Version 1.0 by CeeJay.dk
* Color reduction to C64 palette
Version 1.1 by CeeJay.dk
* Added ability to set a custom palette
* Added EGA palette
+ Improved settings UI
- Commented much of the code
Version 1.2 by microdee
+ Added more color palettes from wikipedia
+ Palettes can have different color counts
Version 1.3 by CeeJay.dk
* Added Aek16 palette
+ Made Nostalgia do color matching in linear space which improves color matching
* Added checker board dithering
* Added scanlines
*/
/*---------------.
| :: Includes :: |
'---------------*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
/*--------------.
| :: Defines :: |
'--------------*/
#ifndef Nostalgia_linear
#define Nostalgia_linear 1
#endif
/*------------------.
| :: UI Settings :: |
'------------------*/
uniform int Nostalgia_scanlines
<
ui_type = "combo";
ui_label = "Scanlines";
ui_items =
"None\0"
"Type 1\0"
"Type 2\0";
//ui_category = "";
> = 1;
uniform int Nostalgia_color_reduction
<
ui_type = "combo";
ui_label = "Color reduction type";
//ui_tooltip = "Choose a color reduction type";
//ui_category = "";
ui_items =
"None\0"
"Palette\0"
//"Quantize\0"
;
> = 1;
uniform bool Nostalgia_dither
<
ui_label = "Dither";
> = 0;
uniform int Nostalgia_palette <
ui_type = "combo";
ui_label = "Palette";
ui_tooltip = "Choose a palette";
//ui_category = "";
ui_items =
"Custom\0"
"C64 palette\0"
"EGA palette\0"
"IBMPC palette\0"
"ZXSpectrum palette\0"
"AppleII palette\0"
"NTSC palette\0"
"Commodore VIC-20\0"
"MSX Systems\0"
"Thomson MO5\0"
"Amstrad CPC\0"
"Atari ST\0"
"Mattel Aquarius\0"
"Gameboy\0"
"Aek16 palette";
> = 0;
uniform float3 Nostalgia_color_0 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 0";
ui_category = "Custom palette";
> = float3( 0. , 0. , 0. ); //Black;
uniform float3 Nostalgia_color_1 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 1";
ui_category = "Custom palette"; >
= float3(255. , 255. , 255. ) / 255.; //White
uniform float3 Nostalgia_color_2 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 2";
ui_category = "Custom palette";
> = float3(136. , 0. , 0. ) / 255.; //Red;
uniform float3 Nostalgia_color_3 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 3";
ui_category = "Custom palette";
> = float3(170. , 255. , 238. ) / 255.; //Cyan
uniform float3 Nostalgia_color_4 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 4";
ui_category = "Custom palette";
> = float3(204. , 68. , 204. ) / 255.; //Violet
uniform float3 Nostalgia_color_5 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 5";
ui_category = "Custom palette";
> = float3( 0. , 204. , 85. ) / 255.; //Green
uniform float3 Nostalgia_color_6 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 6";
ui_category = "Custom palette";
> = float3( 0. , 0. , 170. ) / 255.; //Blue
uniform float3 Nostalgia_color_7 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 7";
ui_category = "Custom palette";
> = float3(238. , 238. , 119. ) / 255.; //Yellow 1
uniform float3 Nostalgia_color_8 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 8";
ui_category = "Custom palette";
> = float3(221. , 136. , 85. ) / 255.; //Orange
uniform float3 Nostalgia_color_9 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 9";
ui_category = "Custom palette";
> = float3(102. , 68. , 0. ) / 255.; //Brown
uniform float3 Nostalgia_color_10 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 10";
ui_category = "Custom palette";
> = float3(255. , 119. , 119. ) / 255.; //Yellow 2
uniform float3 Nostalgia_color_11 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 11";
ui_category = "Custom palette";
> = float3( 51. , 51. , 51. ) / 255.; //Grey 1
uniform float3 Nostalgia_color_12 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 12";
ui_category = "Custom palette";
> = float3(119. , 119. , 119. ) / 255.; //Grey 2
uniform float3 Nostalgia_color_13 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 13";
ui_category = "Custom palette";
> = float3(170. , 255. , 102. ) / 255.; //Lightgreen
uniform float3 Nostalgia_color_14 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 14";
ui_category = "Custom palette";
> = float3( 0. , 136. , 255. ) / 255.; //Lightblue
uniform float3 Nostalgia_color_15 < __UNIFORM_COLOR_FLOAT3
ui_label = "Color 15";
ui_category = "Custom palette";
> = float3(187. , 187. , 187. ) / 255.; //Grey 3
/*
uniform bool Nostalgia_linear //Can't currently make a UI setting for this since I need the preprocessor for that and it does not accept uniforms from the UI
<
ui_label = "Linear";
//ui_category = "Color options";
> = 0;
*/
/*--------------.
| :: Sampler :: |
'--------------*/
sampler Linear
{
Texture = ReShade::BackBufferTex;
SRGBTexture = true;
};
/*-------------.
| :: Effect :: |
'-------------*/
float3 PS_Nostalgia(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float3 color;
int colorCount = 16;
#if Nostalgia_linear == 1
color = tex2D(Linear, texcoord.xy).rgb;
#else
color = tex2D(ReShade::BackBuffer, texcoord.xy).rgb;
#endif
if (Nostalgia_color_reduction)
{
float3 palette[16] = //Custom palette
{
Nostalgia_color_0,
Nostalgia_color_1,
Nostalgia_color_2,
Nostalgia_color_3,
Nostalgia_color_4,
Nostalgia_color_5,
Nostalgia_color_6,
Nostalgia_color_7,
Nostalgia_color_8,
Nostalgia_color_9,
Nostalgia_color_10,
Nostalgia_color_11,
Nostalgia_color_12,
Nostalgia_color_13,
Nostalgia_color_14,
Nostalgia_color_15
};
if (Nostalgia_palette == 1) //C64 palette from http://www.c64-wiki.com/index.php/Color
{
palette[0] = float3( 0. , 0. , 0. ) / 255.; //Black
palette[1] = float3(255. , 255. , 255. ) / 255.; //White
palette[2] = float3(136. , 0. , 0. ) / 255.; //Red
palette[3] = float3(170. , 255. , 238. ) / 255.; //Cyan
palette[4] = float3(204. , 68. , 204. ) / 255.; //Violet
palette[5] = float3( 0. , 204. , 85. ) / 255.; //Green
palette[6] = float3( 0. , 0. , 170. ) / 255.; //Blue
palette[7] = float3(238. , 238. , 119. ) / 255.; //Yellow 1
palette[8] = float3(221. , 136. , 85. ) / 255.; //Orange
palette[9] = float3(102. , 68. , 0. ) / 255.; //Brown
palette[10] = float3(255. , 119. , 119. ) / 255.; //Yellow 2
palette[11] = float3( 51. , 51. , 51. ) / 255.; //Grey 1
palette[12] = float3(119. , 119. , 119. ) / 255.; //Grey 2
palette[13] = float3(170. , 255. , 102. ) / 255.; //Lightgreen
palette[14] = float3( 0. , 136. , 255. ) / 255.; //Lightblue
palette[15] = float3(187. , 187. , 187. ) / 255.; //Grey 3
}
if (Nostalgia_palette == 2) //EGA palette
{
palette[0] = float3(0.0, 0.0, 0.0 ); //Black
palette[1] = float3(0.0, 0.0, 0.666667); //Blue
palette[2] = float3(0.0, 0.666667, 0.0 ); //Green
palette[3] = float3(0.0, 0.666667, 0.666667); //Cyan
palette[4] = float3(0.666667, 0.0, 0.0 ); //Red
palette[5] = float3(0.666667, 0.0, 0.666667); //Magenta
palette[6] = float3(0.666667, 0.333333, 0.0 ); //Brown
palette[7] = float3(0.666667, 0.666667, 0.666667); //Light gray
palette[8] = float3(0.333333, 0.333333, 0.333333); //Dark gray
palette[9] = float3(0.333333, 0.333333, 1.0 ); //Bright blue
palette[10] = float3(0.333333, 1.0, 0.333333); //Bright green
palette[11] = float3(0.333333, 1.0, 1.0 ); //Bright cyan
palette[12] = float3(1.0, 0.333333, 0.333333); //Bright red
palette[13] = float3(1.0, 0.333333, 1.0 ); //Bright magenta
palette[14] = float3(1.0, 1.0, 0.333333); //Bright yellow
palette[15] = float3(1.0, 1.0, 1.0 ); //White
}
if (Nostalgia_palette == 3) //IBMPC palette
{
palette[0] = float3(0,0,0);
palette[1] = float3(0,0,0.8);
palette[2] = float3(0,0.6,0);
palette[3] = float3(0,0.6,0.8);
palette[4] = float3(0.8,0,0);
palette[5] = float3(0.8,0,0.8);
palette[6] = float3(0.8,0.6,0);
palette[7] = float3(0.8,0.8,0.8);
palette[8] = float3(0.4,0.4,0.4);
palette[9] = float3(0.4,0.4,1);
palette[10] = float3(0.4,1,0.4);
palette[11] = float3(0.4,1,1);
palette[12] = float3(0.99,0.4,0.4);
palette[13] = float3(1,0.4,1);
palette[14] = float3(1,1,0.4);
palette[15] = float3(1,1,1);
}
if (Nostalgia_palette == 4) //ZX Spectrum palette
{
palette[0] = float3(0,0,0);
palette[1] = float3(0,0,0.811764705882353);
palette[2] = float3(0,0.811764705882353,0);
palette[3] = float3(0,0.811764705882353,0.811764705882353);
palette[4] = float3(0.811764705882353,0,0);
palette[5] = float3(0.811764705882353,0,0.752941176470588);
palette[6] = float3(0.811764705882353,0.811764705882353,0);
palette[7] = float3(0.811764705882353,0.811764705882353,0.811764705882353);
palette[8] = float3(0,0,0);
palette[9] = float3(0,0,1);
palette[10] = float3(0,1,0);
palette[11] = float3(0,1,1);
palette[12] = float3(1,0,0);
palette[13] = float3(1,0,1);
palette[14] = float3(1,1,0);
palette[15] = float3(1,1,1);
}
if (Nostalgia_palette == 5) //AppleII palette
{
palette[0] = float3(0,0,0);
palette[1] = float3(0.890196078431373,0.117647058823529,0.376470588235294);
palette[2] = float3(0.376470588235294,0.305882352941176,0.741176470588235);
palette[3] = float3(1,0.266666666666667,0.992156862745098);
palette[4] = float3(0,0.63921568627451,0.376470588235294);
palette[5] = float3(0.611764705882353,0.611764705882353,0.611764705882353);
palette[6] = float3(0.0784313725490196,0.811764705882353,0.992156862745098);
palette[7] = float3(0.815686274509804,0.764705882352941,1);
palette[8] = float3(0.376470588235294,0.447058823529412,0.0117647058823529);
palette[9] = float3(1,0.415686274509804,0.235294117647059);
palette[10] = float3(0.611764705882353,0.611764705882353,0.611764705882353);
palette[11] = float3(1,0.627450980392157,0.815686274509804);
palette[12] = float3(0.0784313725490196,0.96078431372549,0.235294117647059);
palette[13] = float3(0.815686274509804,0.866666666666667,0.552941176470588);
palette[14] = float3(0.447058823529412,1,0.815686274509804);
palette[15] = float3(1,1,1);
}
if (Nostalgia_palette == 6) //NTSC palette
{
palette[0] = float3(0.831372549019608,0.831372549019608,0.831372549019608);
palette[1] = float3(0.866666666666667,0.776470588235294,0.474509803921569);
palette[2] = float3(0.0392156862745098,0.96078431372549,0.776470588235294);
palette[3] = float3(0.0470588235294118,0.917647058823529,0.380392156862745);
palette[4] = float3(1,0.156862745098039,0.709803921568627);
palette[5] = float3(1,0.109803921568627,0.298039215686275);
palette[6] = float3(0.149019607843137,0.254901960784314,0.607843137254902);
palette[7] = float3(0,0.87843137254902,0.905882352941176);
palette[8] = float3(1,1,1);
palette[9] = float3(1,0.317647058823529,1);
palette[10] = float3(0.16078431372549,0.16078431372549,0.16078431372549);
palette[11] = float3(0.16078431372549,0.16078431372549,0.16078431372549);
palette[12] = float3(0.16078431372549,0.16078431372549,0.16078431372549);
palette[13] = float3(0.831372549019608,0.831372549019608,0.831372549019608);
palette[14] = float3(0.866666666666667,0.776470588235294,0.474509803921569);
palette[15] = float3(0.0392156862745098,0.96078431372549,0.776470588235294);
}
if (Nostalgia_palette == 7) // Commodore VIC-20
{
palette[0] = float3(0,0,0);
palette[1] = float3(1,1,1);
palette[2] = float3(0.470588235294118,0.16078431372549,0.133333333333333);
palette[3] = float3(0.529411764705882,0.83921568627451,0.866666666666667);
palette[4] = float3(0.666666666666667,0.372549019607843,0.713725490196078);
palette[5] = float3(0.101960784313725,0.509803921568627,0.149019607843137);
palette[6] = float3(0.250980392156863,0.192156862745098,0.552941176470588);
palette[7] = float3(0.749019607843137,0.807843137254902,0.447058823529412);
palette[8] = float3(0.666666666666667,0.454901960784314,0.286274509803922);
palette[9] = float3(0.917647058823529,0.705882352941177,0.537254901960784);
palette[10] = float3(0.72156862745098,0.411764705882353,0.384313725490196);
palette[11] = float3(0.780392156862745,1,1);
palette[12] = float3(0.917647058823529,0.623529411764706,0.964705882352941);
palette[13] = float3(0.580392156862745,0.87843137254902,0.537254901960784);
palette[14] = float3(0.501960784313725,0.443137254901961,0.8);
palette[15] = float3(1,1,0.698039215686274);
}
if (Nostalgia_palette == 8) // MSX Systems
{
palette[0] = float3(0,0,0);
palette[1] = float3(1,1,1);
palette[2] = float3(0.243137254901961,0.72156862745098,0.286274509803922);
palette[3] = float3(0.454901960784314,0.815686274509804,0.490196078431373);
palette[4] = float3(0.349019607843137,0.333333333333333,0.87843137254902);
palette[5] = float3(0.501960784313725,0.462745098039216,0.945098039215686);
palette[6] = float3(0.725490196078431,0.368627450980392,0.317647058823529);
palette[7] = float3(0.396078431372549,0.858823529411765,0.937254901960784);
palette[8] = float3(0.858823529411765,0.396078431372549,0.349019607843137);
palette[9] = float3(1,0.537254901960784,0.490196078431373);
palette[10] = float3(0.8,0.764705882352941,0.368627450980392);
palette[11] = float3(0.870588235294118,0.815686274509804,0.529411764705882);
palette[12] = float3(0.227450980392157,0.635294117647059,0.254901960784314);
palette[13] = float3(0.717647058823529,0.4,0.709803921568627);
palette[14] = float3(0.8,0.8,0.8);
palette[15] = float3(1,1,0.698039215686274);
}
if (Nostalgia_palette == 9) // Thomson MO5
{
palette[0] = float3(0,0,0);
palette[1] = float3(1,1,1);
palette[2] = float3(1,0,0);
palette[3] = float3(0,1,0);
palette[4] = float3(1,1,0);
palette[5] = float3(0,0,1);
palette[6] = float3(1,0,1);
palette[7] = float3(0,1,1);
palette[8] = float3(0,0,0);
palette[9] = float3(0.733333333333333,0.733333333333333,0.733333333333333);
palette[10] = float3(0.866666666666667,0.466666666666667,0.466666666666667);
palette[11] = float3(0.466666666666667,0.866666666666667,0.466666666666667);
palette[12] = float3(0.866666666666667,0.866666666666667,0.466666666666667);
palette[13] = float3(0.466666666666667,0.466666666666667,0.866666666666667);
palette[14] = float3(0.866666666666667,0.466666666666667,0.933333333333333);
palette[15] = float3(0.733333333333333,1,1);
}
if (Nostalgia_palette == 10) // Amstrad CPC
{
palette[0] = float3(0,0,0);
palette[1] = float3(1,1,1);
palette[2] = float3(0,0,0.498039215686275);
palette[3] = float3(0.498039215686275,0,0);
palette[4] = float3(0.498039215686275,0,0.498039215686275);
palette[5] = float3(0,0.498039215686275,0);
palette[6] = float3(1,0,0);
palette[7] = float3(0,0.498039215686275,0.498039215686275);
palette[8] = float3(0.498039215686275,0.498039215686275,0);
palette[9] = float3(0.498039215686275,0.498039215686275,0.498039215686275);
palette[10] = float3(0.498039215686275,0.498039215686275,1);
palette[11] = float3(1,0.498039215686275,0);
palette[12] = float3(1,0.498039215686275,0.498039215686275);
palette[13] = float3(0.498039215686275,1,0.498039215686275);
palette[14] = float3(0.498039215686275,1,1);
palette[15] = float3(1,1,0.498039215686275);
}
if (Nostalgia_palette == 11) // Atari ST
{
palette[0] = float3(0,0,0);
palette[1] = float3(1,0.886274509803922,0.882352941176471);
palette[2] = float3(0.376470588235294,0.0392156862745098,0.0117647058823529);
palette[3] = float3(0.811764705882353,0.133333333333333,0.0549019607843137);
palette[4] = float3(0.16078431372549,0.345098039215686,0.0352941176470588);
palette[5] = float3(0.937254901960784,0.16078431372549,0.0705882352941176);
palette[6] = float3(0.356862745098039,0.349019607843137,0.0431372549019608);
palette[7] = float3(0.352941176470588,0.352941176470588,0.352941176470588);
palette[8] = float3(0.803921568627451,0.372549019607843,0.207843137254902);
palette[9] = float3(0.494117647058824,0.509803921568627,0.756862745098039);
palette[10] = float3(0.305882352941176,0.623529411764706,0.0980392156862745);
palette[11] = float3(0.792156862745098,0.509803921568627,0.364705882352941);
palette[12] = float3(1,0.392156862745098,0.215686274509804);
palette[13] = float3(1,0.525490196078431,0.368627450980392);
palette[14] = float3(0.631372549019608,0.63921568627451,0.76078431372549);
palette[15] = float3(1,0.768627450980392,0.517647058823529);
}
if (Nostalgia_palette == 12) // Mattel Aquarius
{
palette[0] = float3(0,0,0);
palette[1] = float3(1,1,1);
palette[2] = float3(0.494117647058824,0.0980392156862745,0.164705882352941);
palette[3] = float3(0.764705882352941,0,0.105882352941176);
palette[4] = float3(0.725490196078431,0.694117647058824,0.337254901960784);
palette[5] = float3(0.784313725490196,0.725490196078431,0.0274509803921569);
palette[6] = float3(0.231372549019608,0.592156862745098,0.180392156862745);
palette[7] = float3(0.0274509803921569,0.749019607843137,0);
palette[8] = float3(0.250980392156863,0.650980392156863,0.584313725490196);
palette[9] = float3(0,0.776470588235294,0.643137254901961);
palette[10] = float3(0.749019607843137,0.749019607843137,0.749019607843137);
palette[11] = float3(0.513725490196078,0.152941176470588,0.564705882352941);
palette[12] = float3(0.717647058823529,0,0.819607843137255);
palette[13] = float3(0.0196078431372549,0.0509803921568627,0.407843137254902);
colorCount = 14;
}
if (Nostalgia_palette == 13) // Gameboy
{
palette[0] = float3(0.0588235294117647,0.219607843137255,0.0588235294117647);
palette[1] = float3(0.607843137254902,0.737254901960784,0.0588235294117647);
palette[2] = float3(0.188235294117647,0.384313725490196,0.188235294117647);
palette[3] = float3(0.545098039215686,0.674509803921569,0.0588235294117647);
colorCount = 4;
}
if (Nostalgia_palette == 14) //aek16 ( http://eastfarthing.com/blog/2016-05-06-palette/ )
{
palette[0] = float3(0.247059, 0.196078, 0.682353); //
palette[1] = float3(0.890196, 0.054902, 0.760784); //
palette[2] = float3(0.729412, 0.666667, 1.000000); //
palette[3] = float3(1., 1.000000, 1. ); //White
palette[4] = float3(1.000000, 0.580392, 0.615686); //
palette[5] = float3(0.909804, 0.007843, 0.000000); //
palette[6] = float3(0.478431, 0.141176, 0.239216); //
palette[7] = float3(0., 0. , 0. ); //Black
palette[8] = float3(0.098039, 0.337255, 0.282353); //
palette[9] = float3(0.415686, 0.537255, 0.152941); //
palette[10] = float3(0.086275, 0.929412, 0.458824); //
palette[11] = float3(0.196078, 0.756863, 0.764706); //
palette[12] = float3(0.019608, 0.498039, 0.756863); //
palette[13] = float3(0.431373, 0.305882, 0.137255); //
palette[14] = float3(0.937255, 0.890196, 0.019608); //
palette[15] = float3(0.788235, 0.560784, 0.298039); //
}
// :: Dither :: //
if (Nostalgia_dither == 1) //aek16 ( http://eastfarthing.com/blog/2016-05-06-palette/ )
{
//Calculate grid position
float grid_position = frac(dot(texcoord, BUFFER_SCREEN_SIZE * 0.5) + 0.25); //returns 0.25 and 0.75
//Calculate how big the shift should be
float dither_shift = (0.25) * (1.0 / (pow(2,2.0) - 1.0)); // 0.25 seems good both when using math and when eyeballing it. So does 0.75 btw.
//Shift the individual colors differently, thus making it even harder to see the dithering pattern
float3 dither_shift_RGB = float3(dither_shift, dither_shift, dither_shift); //dithering
//modify shift acording to grid position.
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position.
//shift the color by dither_shift
//color.rgb += lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position.
color.rgb += dither_shift_RGB;
}
// :: Color matching :: //
float3 diff = color - palette[0]; //find the difference in color compared to color 0
float dist = dot(diff,diff); //squared distance of difference - we don't need to calculate the square root of this
float closest_dist = dist; //this has to be the closest distance so far as it's the first we have checked
float3 closest_color = palette[0]; //and closest color so far is this one
for (int i = 1 ; i < colorCount ; i++) //for colors 1 to colorCount
{
diff = color - palette[i]; //find the difference in color
dist = dot(diff,diff); //squared distance of difference - we don't need to calculate the square root of this
if (dist < closest_dist) //is the distance closer than the previously closest distance?
{
closest_dist = dist; //closest distance is now this distance
closest_color = palette[i]; //closest color is now this color
}
}
color = closest_color; //return the pixel
}
if (Nostalgia_scanlines == 1)
{
color *= frac(texcoord.y * (BUFFER_HEIGHT * 0.5)) + 0.5; //Scanlines
}
if (Nostalgia_scanlines == 2)
{
float grey = dot(color,float(1.0/3.0));
color = (frac(texcoord.y * (BUFFER_HEIGHT * 0.5)) < 0.25) ? color : color * ((-grey*grey+grey+grey) * 0.5 + 0.5);
}
return color; //return the pixel
}
/*----------------.
| :: Technique :: |
'----------------*/
technique Nostalgia
{
pass NostalgiaPass
{
VertexShader = PostProcessVS;
PixelShader = PS_Nostalgia;
#if Nostalgia_linear == 1
SRGBWriteEnable = true;
#endif
ClearRenderTargets = false;
}
}

View File

@ -0,0 +1,211 @@
////-------------//
///**Limbo Mod**///
//-------------////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Super Simple Limbo Like Shader implementation:
//* For ReShade 3.0+
//* ---------------------------------
//* Limbo Mod
//* Due Diligence
//* https://reshade.me
//* https://github.com/crosire/reshade-shaders/blob/a9ab2880eebf5b1b29cad0a16a5f0910fad52492/Shaders/DisplayDepth.fx
//*
//*
//* LICENSE
//* ============
//* Limbo Mod is licenses under: Attribution 2.0 Generic (CC BY 2.0)l
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format.
//* Adapt - remix, transform, and build upon the material for any purpose, even commercially.
//*
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//*
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others
//* from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by/2.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//* April 1 2021
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "ReShade.fxh"
uniform float G_Radius<
ui_type = "slider";
ui_min = 0.0; ui_max = 1.00;
ui_label = "Subtle Blur Radius";
ui_tooltip = "Increase persistence of the frames this is really the Temporal Part.\n"
"Default is 0.625. But, a value around 0.625 is recommended.";
ui_category = "Limbo Lighting";
> = 0.5;
uniform float Target_Lighting <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.00;
ui_label = "Target Lighting";
ui_tooltip = "Use this to target the brighter areas of the game.\n"
"Default is 0.5. But, any value around 0 - 2 can be used.";
ui_category = "Limbo Lighting";
> = 0.5;
uniform float2 Depth_Map_Adjust <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Depth Near and Far";
ui_tooltip = "Adjust the depth map precision near and far.";
ui_category = "Depth Buffer";
> = float2(0.075,0.750);
uniform float Dither_Bit <
ui_type = "drag";
ui_min = 1; ui_max = 15;
ui_label = "Dither Bit";
ui_tooltip = "Dither is an intentionally applied form of noise used to randomize quantization error, preventing banding in images.";
ui_category = "Depth Buffer";
> = 8;
/////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
texture DepthBufferTex : DEPTH;
sampler DepthBuffer
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
};
texture Mips_Buffer_A { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;MipLevels = 4;};
sampler MipMaps_A
{
Texture = Mips_Buffer_A;
};
texture Mips_Buffer_B { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;MipLevels = 4;};
sampler MipMaps_B
{
Texture = Mips_Buffer_B;
};
uniform float frametime < source = "frametime"; >;
float DepthM(float2 texcoord)
{
float zBuffer = ReShade::GetLinearizedDepth(texcoord).x;
zBuffer = (zBuffer - Depth_Map_Adjust.x)/(Depth_Map_Adjust.y - Depth_Map_Adjust.x);
// Dither for DepthBuffer adapted from gedosato ramdom dither https://github.com/PeterTh/gedosato/blob/master/pack/assets/dx9/deband.fx
// I noticed in some games the depth buffer started to have banding so this is used to remove that.
float DB = Dither_Bit;
float noise = frac(sin(dot(texcoord * frametime, float2(12.9898, 78.233))) * 43758.5453);
float dither_shift = (1.0 / (pow(2,DB) - 1.0));
float dither_shift_half = (dither_shift * 0.5);
dither_shift = dither_shift * noise - dither_shift_half;
zBuffer += -dither_shift;
zBuffer += dither_shift;
zBuffer += -dither_shift;
// Dither End
return zBuffer;
}
float4 BB_M(float2 TC)
{
return tex2D(BackBuffer, TC );
}
float4 DirectLighting(float2 texcoords )
{
float4 BC = BB_M(texcoords);
float GS = dot(BC.rgb,0.333), Boost = 1;
BC.rgb /= GS;
BC.rgb *= saturate(GS - lerp(0.0,0.5,saturate(Target_Lighting)));
Boost = lerp(1,2.5,saturate(Target_Lighting));
return float4(BC.rgb * Boost,BC.a);
}
float4 GussBlur(sampler image, float2 TC, int dir, float Mips)
{
//direction
float W0 = G_Radius > 0 ? 0.1964825501511404 : 1, W1 = 0.2969069646728344, W2 = 0.09447039785044732, W3 = 0.010381362401148057;
float2 off0 = pix * lerp(0,5,G_Radius);
float2 off1 = dir ? float2( 0, 1.411764705882353) * off0 : float2(1.411764705882353, 0) * off0;
float2 off2 = dir ? float2( 0, 3.294117647058823) * off0 : float2(3.294117647058823, 0) * off0;
float2 off3 = dir ? float2( 0, 5.176470588235294) * off0 : float2(5.176470588235294, 0) * off0;
float4 color = tex2Dlod(image, float4(TC,0,Mips)) * W0;
if(G_Radius > 0)
{
color += tex2Dlod(image, float4(TC + off1,0,Mips) ) * W1;
color += tex2Dlod(image, float4(TC - off1,0,Mips) ) * W1;
color += tex2Dlod(image, float4(TC + off2,0,Mips) ) * W2;
color += tex2Dlod(image, float4(TC - off2,0,Mips) ) * W2;
color += tex2Dlod(image, float4(TC + off2,0,Mips) ) * W3;
color += tex2Dlod(image, float4(TC - off2,0,Mips) ) * W3;
}
return color;
}
void Buffers_Mip_A(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 MipMapper_A : SV_Target0)
{
MipMapper_A = DirectLighting( texcoord );
}
void Buffers_Mip_B(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 MipMapper_B : SV_Target0)
{
MipMapper_B = GussBlur(MipMaps_A, texcoord, 0, lerp(0,4,G_Radius));
}
float4 Out(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 BWorColor = dot(GussBlur(MipMaps_B, texcoord, 1, lerp(0,4,G_Radius)),0.333);
return DepthM(texcoord) + (dot(tex2Dlod(MipMaps_A,float4(texcoord,0,0)),0.333) * BWorColor );
}
technique Limbo_Mod
{
pass Mips_A
{
VertexShader = PostProcessVS;
PixelShader = Buffers_Mip_A;
RenderTarget0 = Mips_Buffer_A;
}
pass Mips_B
{
VertexShader = PostProcessVS;
PixelShader = Buffers_Mip_B;
RenderTarget0 = Mips_Buffer_B;
}
pass Out
{
VertexShader = PostProcessVS;
PixelShader = Out;
}
}

View File

@ -0,0 +1,473 @@
////--------------//
///**Snow Scape**///
//--------------////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Super Simple Snow Shader "Snow Scape" implementation:
//* For ReShade 3.0+
//* ---------------------------------
//* Snow Scape
//* Due Diligence
//* Based on POM
//* http://graphics.cs.brown.edu/games/SteepParallax/index.html
//* Other Needed Links for the code here.
//* http://www.shadertoy.com/view/XtKyzD
//* https://reshade.me
//* https://github.com/crosire/reshade-shaders/blob/a9ab2880eebf5b1b29cad0a16a5f0910fad52492/Shaders/DisplayDepth.fx
//* I am not sure I got it all.
//*
//* LICENSE
//* ============
//* Snow Scape is licenses under: Attribution 2.0 Generic (CC BY 2.0)l
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format.
//* Adapt - remix, transform, and build upon the material for any purpose, even commercially.
//*
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//*
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others
//* from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by/2.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//*
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "ReShade.fxh"
#define MaxDepth_Cutoff 0.999 //[0.1 - 1.0]
#define SN_offset float2(2,2) // Smooth Normals Set the first value from 1-6
uniform float BG <
ui_type = "slider";
ui_min = 0.5; ui_max = 1.0;
ui_label = "Best Guess Sensitivity";
ui_tooltip = "Increases the sensitiviy of the Algo used for gussing where the user is looking at.\n"
"Default is 0.9625. But, any value around 0.5 - 1.0 can be used. Decreasing this makes it stronger.";
ui_category = "Snow";
> = 0.9625;
uniform float SSC <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.00;
ui_label = "Snow Scape Adjust";
ui_tooltip = "Increase persistence of the frames this is really the Temporal Part.\n"
"Default is 0.625. But, a value around 0.625 is recommended.";
ui_category = "Snow";
> = 0.625;
uniform float HMP <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.00;
ui_label = "Height Map Scaling";
ui_tooltip = "Increases the Detail that it takes from the color information from the world.\n"
"Default is 0.5. But, any value around 0 - 2 can be used.";
ui_category = "Snow";
> = 0.5;
uniform float Elevation <
ui_type = "slider";
ui_min = 0; ui_max = 50;
ui_label = "Elevation";
ui_tooltip = "Increase Parallax Occlusion Mapping Elevation.\n"
"Default is 10. But, a value around 1-25 is recommended.";
ui_category = "Snow";
> = 10;
uniform bool I_Ice <
ui_label = "Invert Snow";
ui_tooltip = "Use this so you can invert the Height Map.";
ui_category = "Snow";
> = !true;
uniform float Depth_Map_Adjust <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Depth Map Adjustment";
ui_tooltip = "Adjust the depth map and sharpness distance.";
ui_category = "Depth Buffer";
> = 1.0;
/////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
texture DepthBufferTex : DEPTH;
sampler DepthBuffer
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
};
texture SnowMask_A { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; MipLevels = 11;};
sampler CSnowMask
{
Texture = SnowMask_A;
};
texture Normals_A { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16; MipLevels = 11;};
sampler N_Sampler_A
{
Texture = Normals_A;
};
texture Normals_B { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16; MipLevels = 11;};
sampler N_Sampler_B
{
Texture = Normals_B;
};
texture BB_Depth_A { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;MipLevels = 11;};
sampler CDBuffer
{
Texture = BB_Depth_A;
};
texture Bump_C { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;MipLevels = 11;};
sampler BumpMap
{
Texture = Bump_C;
};
//Total amount of frames since the game started.
uniform uint framecount < source = "framecount"; >;
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define PI 3.14159265358979323846264 // PI
float fmod(float a, float b)
{
float c = frac(abs(a / b)) * abs(b);
return a < 0 ? -c : c;
}
float2 DepthM(float2 texcoord)
{
float zBuffer = ReShade::GetLinearizedDepth(texcoord).x; //Depth Buffer
zBuffer = smoothstep(0,Depth_Map_Adjust,zBuffer);
return float2(zBuffer,(1-zBuffer - 0.5)/(1.0 - 0.5) );
}
float4 BB_H(float2 TC)
{
return tex2D(BackBuffer, TC );
}
float3 DepthNormals(float2 texcoord)
{
float3 offset = float3(pix.xy, 0.0);
float2 posCenter = texcoord.xy;
float2 posNorth = posCenter - offset.zy;
float2 posEast = posCenter + offset.xz;
float3 vertCenter = float3(posCenter - 0.5, 1) * DepthM(posCenter).x;
float3 vertNorth = float3(posNorth - 0.5, 1) * DepthM(posNorth).x;
float3 vertEast = float3(posEast - 0.5, 1) * DepthM(posEast).x;
return normalize(cross(vertCenter - vertNorth, vertCenter - vertEast)) ;
}
void MCNoise(inout float Noise,float2 TC, float FC,float seed)
{ //This is the noise I used for rendering
float motion = FC, a = 12.9898, b = 78.233, c = 43758.5453, dt= dot( TC.xy * 2.0 , float2(a,b)), sn= fmod(dt,PI);
Noise = frac(frac(tan(distance(sn*(seed+dt), float2(a,b) )) * c) + 0.61803398875f * motion);
}
float LumaMask(sampler Texture,float2 texcoord)
{
float2 samples[12] = {
float2(-0.326212,-0.405805),
float2(-0.840144,-0.073580),
float2(-0.695914, 0.457137),
float2(-0.203345, 0.620716),
float2( 0.962340,-0.194983),
float2( 0.473434,-0.480026),
float2( 0.519456, 0.767022),
float2( 0.185461,-0.893124),
float2( 0.507431, 0.064425),
float2( 0.896420, 0.412458),
float2(-0.321940,-0.932615),
float2(-0.791559,-0.597705)
};
int MipM = 5;
float4 sum = tex2Dlod(Texture,float4(texcoord,0,MipM));
for (int i = 0; i < 12; i++)
{
float Spread = 0.0275;
sum += tex2Dlod(Texture,float4(texcoord + Spread * samples[i],0,MipM));
}
sum /= 13;
return dot(sum,0.333);
}
float4 Mask(float2 texcoord)
{
//Code for Guessing where the user was looking at was removed in favor of martys improved world normals.
//Nope added Guessing back Marty Improved World Normals not ready yet. But, I hope for the future.
// I am silly I forgot what I did befor..... so I had to rewrite this from memory welp....Forgot a lot lol Fuck......
//Not the same code in the video. since I forgot what I did and my cloud stroage seems to forget what I did if I rename the file.
//New thing was made........ Happy guessing.
float3 Normals = tex2Dlod(N_Sampler_B,float4(texcoord,0,0)).xyz;
//Changed my mind since my memory sucks New system Guessing where the user is looking at with 8 Detectors kind of like SuperDepth3D.
float2 Location[8] = {
float2(0.25,0.5 ),//Left of Center
float2(0.5 ,0.25),//Above Center
float2(0.5 ,0.5 ),//Center
float2(0.5 ,0.75),//Below Center
float2(0.75,0.5 ),//Right of Center
float2(0.25,0.75),//Down Left
float2(0.75,0.75),//Down Right
float2(0.5 ,0.125)//Way Above Center
};
float Best_Guess = 0.5,Center,Above,Below,Left,Right,DL,DR,WAC,WTF;
if(DepthM(Location[2]).x > BG)//Center
Center = 1;
if(DepthM(Location[1]).x > BG)//Above
Above = 1;
if(DepthM(Location[3]).x > BG)//Below
Below = 1;
if(DepthM(Location[0]).x > BG)//Left
Left = 1;
if(DepthM(Location[4]).x > BG)//Right
Right = 1;
if(DepthM(Location[5]).x > BG)//Down Left
DL = 1;
if(DepthM(Location[6]).x > BG)//Down Right
DR = 1;
if(DepthM(Location[7]).x > BG)//Down Right
WAC = 1;
//Now we guess Where/What the fuck the User is looking at.
if(!Center && !Above && !Below && !Left && !Right && !DL && !DR && WAC)
Best_Guess = 0.250;
if(!Center && Above && !Below && !Left && !Right && !DL && !DR && WAC)
Best_Guess = 0.125;
if( Center && Above && !Below && !Left && !Right && !DL && !DR && WAC)
Best_Guess = 0.0;
if( !Center && !Above && !Below && !Left && !Right && !DL && !DR && !WAC)
Best_Guess = 1.0;
if( Center && Above && Below && Left && Right && !DL && DR && WAC)
Best_Guess = 0.0625;
if( Center && Above && Below && Left && Right && DL && !DR && WAC)
Best_Guess = 0.0625;
//to be used later to guess if the user if close to a wall...... But, got lazy.
//if( !Center && !Above && !Below && !Left && !Right && !DL && !DR && !WAC)
//WTF = 1;
// float DD = saturate(tex2Dlod(N_Sampler_B,float4(texcoord,0,10)).w),DS = smoothstep(0,0.1,DD),Depth = smoothstep(0,1,DepthM(0.5).x);
float Top = dot(float3(0,1,0), Normals), Wall = step(Best_Guess,dot(float3(0,0,1), Normals));;
float Snow = smoothstep(1-SSC,1,WTF ? Top : Top-Wall);
float Noise;
MCNoise( Noise, texcoord, 1 , 1 );
//Hold over for wave noise
float2 Di[4] = {float2(pix.x,0),float2(-pix.x,0),float2(0,pix.y),float2(0,-pix.y)};
float3 SN = 1-BB_H(texcoord).rgb;
[fastopt]
for (int i = 0; i < 4; i ++)
{
SN += (1-BB_H(texcoord + Di[i] * Noise * (0.1*100)).rgb);
}
float HeightMap = Top * dot(saturate(SN/5) , HMP);
HeightMap = I_Ice ? 1-HeightMap : HeightMap;
return float4(Snow, lerp(0,HeightMap,Snow) ,Snow,1);
}
float Bump(float2 TC)
{
float2 t, l, r, d, MA = 5;
float2 UV = TC.xy, SW = pix * MA;
float3 NormalsFromHeightMap, NHM_A, NHM_B;
float Noise;
MCNoise( Noise, TC, 1 , 1 );
t.x = Mask( float2( UV.x , UV.y - SW.y ) ).y;
d.x = Mask( float2( UV.x , UV.y + SW.y ) ).y;
l.x = Mask( float2( UV.x - SW.x , UV.y ) ).y;
r.x = Mask( float2( UV.x + SW.x , UV.y ) ).y;
SW *= 0.5;
t.y = Mask( float2( UV.x , UV.y - SW.y ) ).y;
d.y = Mask( float2( UV.x , UV.y + SW.y ) ).y;
l.y = Mask( float2( UV.x - SW.x , UV.y ) ).y;
r.y = Mask( float2( UV.x + SW.x , UV.y ) ).y;
NHM_A = float3(-float2(-(r.x - l.x),-(t.x - d.x)) * 0.5 + 0.4,1);
NHM_B = float3(-float2(-(r.y - l.y),-(t.y - d.y)) * 0.5 + 0.4,1);
NormalsFromHeightMap = lerp(NHM_A , NHM_B, 0.5);
return saturate(dot(0.5,NormalsFromHeightMap));
}
float HeightMap(float2 TC)
{
float HM1 = tex2Dlod(CSnowMask,float4(TC,0,1)).y;
float HM2 = tex2Dlod(CSnowMask,float4(TC,0,3)).y;
float HM = (HM1 + HM2)/2;
return HM * DepthM(TC).y;
}
float2 Parallax( float2 Diverge, float2 Coordinates)
{ float2 TC = Coordinates;
float D = abs(length(Diverge));
float Cal_Steps = D + (D * 0.05);
//ParallaxSteps
float Steps = clamp(Cal_Steps * 2,1,255);
// Offset per step progress & Limit
float LayerDepth = rcp(Steps);
//Offsets listed here Max Seperation is 3% - 8% of screen space with Depth Offsets & Netto layer offset change based on MS.
float2 MS = Diverge * pix;
float2 deltaCoordinates = MS * LayerDepth, ParallaxCoord = Coordinates;
float CurrentDepthMapValue = Mask(ParallaxCoord).x, CurrentLayerDepth = 0;
[loop] //Steep parallax mapping
for ( int i = 0; i < Steps; i++ )
{ // Doing it this way should stop crashes in older version of reshade, I hope.
if (CurrentDepthMapValue <= CurrentLayerDepth)
break; // Once we hit the limit Stop Exit Loop.
// Shift coordinates horizontally in linear fasion
ParallaxCoord -= deltaCoordinates;
// Get depth value at current coordinates
CurrentDepthMapValue = HeightMap( ParallaxCoord );
// Get depth of next layer
CurrentLayerDepth += LayerDepth;
}
// Parallax Occlusion Mapping
float2 PrevParallaxCoord = ParallaxCoord + deltaCoordinates, DepthDifference;
float afterDepthValue = CurrentDepthMapValue - CurrentLayerDepth;
float beforeDepthValue = HeightMap( ParallaxCoord ) - CurrentLayerDepth + LayerDepth;
// Interpolate coordinates
float weight = afterDepthValue / (afterDepthValue - beforeDepthValue);
ParallaxCoord = PrevParallaxCoord * max(0,weight) + ParallaxCoord * min(1,1.0f - weight);
return ParallaxCoord;
}
//Super Simple Sparkly Shader https://www.shadertoy.com/view/XtKyzD
float SSSS(float2 TC)
{
float2 Noise;
Noise.x = tex2D(BumpMap,TC).y;
Noise.y = tex2D(BumpMap,TC).z;
float result = Noise.x;
result *= Noise.y;
result = pow(abs(result), 12.0);
return 5.0*result;
}
void Out(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float3 color : SV_Target)
{
float2 TC = Parallax(float2(0,-Elevation * DepthM(texcoord).y) , texcoord ).xy;
float Snow = Mask(TC.xy).x, SS = tex2Dlod(BumpMap,float4(TC,0,2)).w;
float3 Snow_Color = float3(0.75,0.8,0.85), Snow_Scape = (Mask(TC.xy).x - 0.01) * Snow_Color + SSSS(TC.xy * 0.75);
float3 T_A_A = lerp(Snow_Scape + LumaMask(CDBuffer,TC)*0.2, BB_H( TC.xy ).rgb,1-Snow);
// if(TC.y > 1)
// color = Snow_Color;
// else
color = T_A_A * lerp(SS,1,1-Snow);
}
float3 SmoothNormals(float2 TC, int NS,int Dir, float SNOffset)
{ //Smooth Normals done in two passes now Faster. But, still slow.
float4 StoredNormals_Depth = float4(Dir ? DepthNormals(TC) : tex2Dlod(N_Sampler_A,float4(TC,0,0)).xyz,DepthM(TC).x), SmoothedNormals = float4(StoredNormals_Depth.xyz,1);
[loop] // -1 0 +1 on x and y
for(float xy = -NS; xy <= NS; xy++)
{
if(smoothstep(0,1,StoredNormals_Depth.w) > MaxDepth_Cutoff)
break;
float2 XY = Dir ? float2(xy,0) : float2(0,xy);
float2 offsetcoords = TC + XY * pix * SNOffset;
float4 Normals_Depth = float4(Dir ? DepthNormals(offsetcoords) : tex2Dlod(N_Sampler_A,float4(offsetcoords,0,0)).xyz,DepthM(offsetcoords).x);
if (abs(StoredNormals_Depth.w - Normals_Depth.w) < 0.001 && dot(Normals_Depth.xyz, StoredNormals_Depth.xyz) > 0.5f)
{
SmoothedNormals.xyz += Normals_Depth.xyz;
++SmoothedNormals.w;
}
}
return SmoothedNormals.xyz / SmoothedNormals.w;
}
void Buffers_A(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 Normals : SV_Target0, out float4 BackBuffer_Depth : SV_Target1, out float4 Snow_Info : SV_Target2)
{
//AO was removed seems going over board for this simple effect.
Normals = SmoothNormals(texcoord, SN_offset.x, 1, SN_offset.y);
BackBuffer_Depth = float4(tex2D(BackBuffer,texcoord).rgb,DepthM(texcoord).x);
Snow_Info = float4(Mask(texcoord).xyz,0);
}
void Buffers_B(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 Normals_LM : SV_Target0)
{ //AO was removed seems going over board for this simple effect.
Normals_LM = float4(SmoothNormals(texcoord, SN_offset.x, 0, SN_offset.y).xyz,DepthM(texcoord).x);
}
void Buffers_C(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 BumpMap_Else : SV_Target0)
{
float2 Noise;
//should add fake glitter movement comp..... here
MCNoise( Noise.x, texcoord , framecount * -0.005, 1 );
MCNoise( Noise.y, texcoord , framecount * +0.005, 2 );
BumpMap_Else = float4(0,Noise.x,Noise.y,Bump(texcoord));
}
technique OS_SnowScape
{
pass Alpha
{
VertexShader = PostProcessVS;
PixelShader = Buffers_A;
RenderTarget0 = Normals_A;
RenderTarget1 = BB_Depth_A;
RenderTarget2 = SnowMask_A;
}
pass Beta
{
VertexShader = PostProcessVS;
PixelShader = Buffers_B;
RenderTarget0 = Normals_B;
}
pass Gamma
{
VertexShader = PostProcessVS;
PixelShader = Buffers_C;
RenderTarget0 = Bump_C;
}
pass Out
{
VertexShader = PostProcessVS;
PixelShader = Out;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
/*
* Collection of simple base effects often used across shaders by prod80
* Required for proper effect execution
* Includes [range]: exposure [-4, 4], contrast [-1, 1.5], brightness [-1, 1.5], saturation [-1, 1], vibrance[-1, 1]
*/
float3 sl( float3 c, float3 b )
{
return b < 0.5f ? ( 2.0f * c * b + c * c * ( 1.0f - 2.0f * b )) :
( sqrt( c ) * ( 2.0f * b - 1.0f ) + 2.0f * c * ( 1.0f - b ));
}
float getLum( in float3 x )
{
return dot( x, float3( 0.212656, 0.715158, 0.072186 ));
}
float3 exposure( float3 res, float x )
{
x = x < 0.0f ? x * 0.333f : x;
return saturate( res.xyz * ( x * ( 1.0f - res.xyz ) + 1.0f ));
}
float3 con( float3 res, float x )
{
//softlight
float3 c = sl( res.xyz, res.xyz );
x = ( x < 0.0f ) ? x * 0.5f : x;
return saturate( lerp( res.xyz, c.xyz, x ));
}
float3 bri( float3 res, float x )
{
//screen
float3 c = 1.0f - ( 1.0f - res.xyz ) * ( 1.0f - res.xyz );
x = ( x < 0.0f ) ? x * 0.5f : x;
return saturate( lerp( res.xyz, c.xyz, x ));
}
float3 sat( float3 res, float x )
{
return saturate( lerp( getLum( res.xyz ), res.xyz, x + 1.0f ));
}
float3 vib( float3 res, float x )
{
float4 sat = 0.0f;
sat.xy = float2( min( min( res.x, res.y ), res.z ), max( max( res.x, res.y ), res.z ));
sat.z = sat.y - sat.x;
sat.w = getLum( res.xyz );
return saturate( lerp( sat.w, res.xyz, 1.0f + ( x * ( 1.0f - sat.z ))));
}

View File

@ -0,0 +1,137 @@
/*
* Blend functions across shaders by prod80
* Required for proper effect execution
* These can be used by calling the function blendmode() taking input of base, blend, blendmode, opacity
* The effects only operate in LDR space
* UI elements
uniform int blendmode < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Description";
ui_category = "Category";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 0;
uniform float opacity <
ui_label = "Opacity";
ui_tooltip = "Description";
ui_category = "Category";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
*/
float getAvgColor( float3 col )
{
return dot( col.xyz, float3( 0.333333f, 0.333334f, 0.333333f ));
}
// nVidia blend modes
// Source: https://www.khronos.org/registry/OpenGL/extensions/NV/NV_blend_equation_advanced.txt
float3 ClipColor( float3 color )
{
float lum = getAvgColor( color.xyz );
float mincol = min( min( color.x, color.y ), color.z );
float maxcol = max( max( color.x, color.y ), color.z );
color.xyz = ( mincol < 0.0f ) ? lum + (( color.xyz - lum ) * lum ) / ( lum - mincol ) : color.xyz;
color.xyz = ( maxcol > 1.0f ) ? lum + (( color.xyz - lum ) * ( 1.0f - lum )) / ( maxcol - lum ) : color.xyz;
return color;
}
// Luminosity: base, blend
// Color: blend, base
float3 blendLuma( float3 base, float3 blend )
{
float lumbase = getAvgColor( base.xyz );
float lumblend = getAvgColor( blend.xyz );
float ldiff = lumblend - lumbase;
float3 col = base.xyz + ldiff;
return ClipColor( col.xyz );
}
// Hue: blend, base, base
// Saturation: base, blend, base
float3 blendColor( float3 base, float3 blend, float3 lum )
{
float minbase = min( min( base.x, base.y ), base.z );
float maxbase = max( max( base.x, base.y ), base.z );
float satbase = maxbase - minbase;
float minblend = min( min( blend.x, blend.y ), blend.z );
float maxblend = max( max( blend.x, blend.y ), blend.z );
float satblend = maxblend - minblend;
float3 color = ( satbase > 0.0f ) ? ( base.xyz - minbase ) * satblend / satbase : 0.0f;
return blendLuma( color.xyz, lum.xyz );
}
float3 darken(float3 c, float3 b) { return min(c,b);}
float3 multiply(float3 c, float3 b) { return c*b;}
float3 linearburn(float3 c, float3 b) { return max(c+b-1.0f,0.0f);}
float3 colorburn(float3 c, float3 b) { return b<=0.0f ? b:saturate(1.0f-((1.0f-c)/b)); }
float3 lighten(float3 c, float3 b) { return max(b,c);}
float3 screen(float3 c, float3 b) { return 1.0f-(1.0f-c)*(1.0f-b);}
float3 colordodge(float3 c, float3 b) { return b>=1.0f ? b:saturate(c/(1.0f-b));}
float3 lineardodge(float3 c, float3 b) { return min(c+b,1.0f);}
float3 overlay(float3 c, float3 b) { return c<0.5f ? 2.0f*c*b:(1.0f-2.0f*(1.0f-c)*(1.0f-b));}
float3 softlight(float3 c, float3 b) { return b<0.5f ? (2.0f*c*b+c*c*(1.0f-2.0f*b)):(sqrt(c)*(2.0f*b-1.0f)+2.0f*c*(1.0f-b));}
float3 vividlight(float3 c, float3 b) { return b<0.5f ? colorburn(c,(2.0f*b)):colordodge(c,(2.0f*(b-0.5f)));}
float3 linearlight(float3 c, float3 b) { return b<0.5f ? linearburn(c,(2.0f*b)):lineardodge(c,(2.0f*(b-0.5f)));}
float3 pinlight(float3 c, float3 b) { return b<0.5f ? darken(c,(2.0f*b)):lighten(c, (2.0f*(b-0.5f)));}
float3 hardmix(float3 c, float3 b) { return vividlight(c,b)<0.5f ? float3(0.0,0.0,0.0):float3(1.0,1.0,1.0);}
float3 reflect(float3 c, float3 b) { return b>=1.0f ? b:saturate(c*c/(1.0f-b));}
float3 glow(float3 c, float3 b) { return reflect(b,c);}
float3 blendhue(float3 c, float3 b) { return blendColor(b,c,c);}
float3 blendsaturation(float3 c, float3 b) { return blendColor(c,b,c);}
float3 blendcolor(float3 c, float3 b) { return blendLuma(b,c);}
float3 blendluminosity(float3 c, float3 b) { return blendLuma(c,b);}
float3 blendmode( float3 c, float3 b, int mode, float o )
{
float3 ret;
switch( mode )
{
case 0: // Default
{ ret.xyz = b.xyz; } break;
case 1: // Darken
{ ret.xyz = darken( c, b ); } break;
case 2: // Multiply
{ ret.xyz = multiply( c, b ); } break;
case 3: // Linearburn
{ ret.xyz = linearburn( c, b ); } break;
case 4: // Colorburn
{ ret.xyz = colorburn( c, b ); } break;
case 5: // Lighten
{ ret.xyz = lighten( c, b ); } break;
case 6: // Screen
{ ret.xyz = screen( c, b ); } break;
case 7: // Colordodge
{ ret.xyz = colordodge( c, b ); } break;
case 8: // Lineardodge
{ ret.xyz = lineardodge( c, b ); } break;
case 9: // Overlay
{ ret.xyz = overlay( c, b ); } break;
case 10: // Softlight
{ ret.xyz = softlight( c, b ); } break;
case 11: // Vividlight
{ ret.xyz = vividlight( c, b ); } break;
case 12: // Linearlight
{ ret.xyz = linearlight( c, b ); } break;
case 13: // Pinlight
{ ret.xyz = pinlight( c, b ); } break;
case 14: // Hard Mix
{ ret.xyz = hardmix( c, b ); } break;
case 15: // Reflect
{ ret.xyz = reflect( c, b ); } break;
case 16: // Glow
{ ret.xyz = glow( c, b ); } break;
case 17: // Hue
{ ret.xyz = blendhue( c, b ); } break;
case 18: // Saturation
{ ret.xyz = blendsaturation( c, b ); } break;
case 19: // Color
{ ret.xyz = blendcolor( c, b ); } break;
case 20: // Luminosity
{ ret.xyz = blendluminosity( c, b ); } break;
}
return saturate( lerp( c.xyz, ret.xyz, o ));
}

View File

@ -0,0 +1,187 @@
/*
* Color spaces shared across shaders by prod80
* Required for proper effect execution
*/
float3 HUEToRGB( in float H )
{
return saturate( float3( abs( H * 6.0f - 3.0f ) - 1.0f,
2.0f - abs( H * 6.0f - 2.0f ),
2.0f - abs( H * 6.0f - 4.0f )));
}
float3 RGBToHCV( in float3 RGB )
{
// Based on work by Sam Hocevar and Emil Persson
float4 P = ( RGB.g < RGB.b ) ? float4( RGB.bg, -1.0f, 2.0f/3.0f ) : float4( RGB.gb, 0.0f, -1.0f/3.0f );
float4 Q1 = ( RGB.r < P.x ) ? float4( P.xyw, RGB.r ) : float4( RGB.r, P.yzx );
float C = Q1.x - min( Q1.w, Q1.y );
float H = abs(( Q1.w - Q1.y ) / ( 6.0f * C + 0.000001f ) + Q1.z );
return float3( H, C, Q1.x );
}
float3 RGBToHSL( in float3 RGB )
{
RGB.xyz = max( RGB.xyz, 0.000001f );
float3 HCV = RGBToHCV(RGB);
float L = HCV.z - HCV.y * 0.5f;
float S = HCV.y / ( 1.0f - abs( L * 2.0f - 1.0f ) + 0.000001f);
return float3( HCV.x, S, L );
}
float3 HSLToRGB( in float3 HSL )
{
float3 RGB = HUEToRGB(HSL.x);
float C = (1.0f - abs(2.0f * HSL.z - 1.0f)) * HSL.y;
return ( RGB - 0.5f ) * C + HSL.z;
}
// Collected from
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
float3 RGBToHSV(float3 c)
{
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = c.g < c.b ? float4(c.bg, K.wz) : float4(c.gb, K.xy);
float4 q = c.r < p.x ? float4(p.xyw, c.r) : float4(c.r, p.yzx);
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
float3 HSVToRGB(float3 c)
{
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
}
// Color temperature
float3 KelvinToRGB( in float k )
{
float3 ret;
float kelvin = clamp( k, 1000.0f, 40000.0f ) / 100.0f;
if( kelvin <= 66.0f )
{
ret.r = 1.0f;
ret.g = saturate( 0.39008157876901960784f * log( kelvin ) - 0.63184144378862745098f );
}
else
{
float t = max( kelvin - 60.0f, 0.0f );
ret.r = saturate( 1.29293618606274509804f * pow( t, -0.1332047592f ));
ret.g = saturate( 1.12989086089529411765f * pow( t, -0.0755148492f ));
}
if( kelvin >= 66.0f )
ret.b = 1.0f;
else if( kelvin < 19.0f )
ret.b = 0.0f;
else
ret.b = saturate( 0.54320678911019607843f * log( kelvin - 10.0f ) - 1.19625408914f );
return ret;
}
// sRGB to Linear RGB conversion
float3 LinearTosRGB( float3 color )
{
float3 x = color * 12.92f;
float3 y = 1.055f * pow(saturate(color), 1.0f / 2.4f) - 0.055f;
float3 clr = color;
clr.r = color.r < 0.0031308f ? x.r : y.r;
clr.g = color.g < 0.0031308f ? x.g : y.g;
clr.b = color.b < 0.0031308f ? x.b : y.b;
return clr;
}
float3 SRGBToLinear( float3 color )
{
float3 x = color / 12.92f;
float3 y = pow(max((color + 0.055f) / 1.055f, 0.0f), 2.4f);
float3 clr = color;
clr.r = color.r <= 0.04045f ? x.r : y.r;
clr.g = color.g <= 0.04045f ? x.g : y.g;
clr.b = color.b <= 0.04045f ? x.b : y.b;
return clr;
}
// SRGB <--> CIELAB CONVERSIONS
// Reference white D65
#define reference_white float3( 0.95047, 1.0, 1.08883 )
// Source
// http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
#define K_val float( 24389.0 / 27.0 )
#define E_val float( 216.0 / 24389.0 )
float3 pd80_xyz_to_lab( float3 c )
{
// .xyz output contains .lab
float3 w = max( c / reference_white, 0.0f );
float3 v;
v.x = ( w.x > E_val ) ? pow( w.x, 1.0 / 3.0 ) : ( K_val * w.x + 16.0 ) / 116.0;
v.y = ( w.y > E_val ) ? pow( w.y, 1.0 / 3.0 ) : ( K_val * w.y + 16.0 ) / 116.0;
v.z = ( w.z > E_val ) ? pow( w.z, 1.0 / 3.0 ) : ( K_val * w.z + 16.0 ) / 116.0;
return float3( 116.0 * v.y - 16.0,
500.0 * ( v.x - v.y ),
200.0 * ( v.y - v.z ));
}
float3 pd80_lab_to_xyz( float3 c )
{
float3 v;
v.y = ( c.x + 16.0 ) / 116.0;
v.x = c.y / 500.0 + v.y;
v.z = v.y - c.z / 200.0;
return float3(( v.x * v.x * v.x > E_val ) ? v.x * v.x * v.x : ( 116.0 * v.x - 16.0 ) / K_val,
( c.x > K_val * E_val ) ? v.y * v.y * v.y : c.x / K_val,
( v.z * v.z * v.z > E_val ) ? v.z * v.z * v.z : ( 116.0 * v.z - 16.0 ) / K_val ) *
reference_white;
}
float3 pd80_srgb_to_xyz( float3 c )
{
// Source: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
// sRGB to XYZ (D65) - Standard sRGB reference white ( 0.95047, 1.0, 1.08883 )
const float3x3 mat = float3x3(
0.4124564, 0.3575761, 0.1804375,
0.2126729, 0.7151522, 0.0721750,
0.0193339, 0.1191920, 0.9503041
);
return mul( mat, c );
}
float3 pd80_xyz_to_srgb( float3 c )
{
// Source: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
// XYZ to sRGB (D65) - Standard sRGB reference white ( 0.95047, 1.0, 1.08883 )
const float3x3 mat = float3x3(
3.2404542,-1.5371385,-0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434,-0.2040259, 1.0572252
);
return mul( mat, c );
}
// Maximum value in LAB, B channel is pure blue with 107.8602... divide by 108 to get 0..1 range values
// Maximum value in LAB, L channel is pure white with 100
float3 pd80_srgb_to_lab( float3 c )
{
float3 lab = pd80_srgb_to_xyz( c );
lab = pd80_xyz_to_lab( lab );
return lab / float3( 100.0, 108.0, 108.0 );
}
float3 pd80_lab_to_srgb( float3 c )
{
float3 rgb = pd80_lab_to_xyz( c * float3( 100.0, 108.0, 108.0 ));
rgb = pd80_xyz_to_srgb( max( min( rgb, reference_white ), 0.0 ));
return saturate( rgb );
}

View File

@ -0,0 +1,55 @@
/*
* Shared textures across shaders by prod80
* Required for proper effect execution
*/
// Textures
texture texNoise < source = "pd80_bluenoise.png"; > { Width = 512; Height = 512; Format = RGBA8; };
texture texNoiseRGB < source = "pd80_bluenoise_rgba.png"; > { Width = 512; Height = 512; Format = RGBA8; };
texture texGaussNoise < source = "pd80_gaussnoise.png"; > { Width = 512; Height = 512; Format = RGBA8; };
// Samplers
sampler samplerNoise
{
Texture = texNoise;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
sampler samplerRGBNoise
{
Texture = texNoiseRGB;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
sampler samplerGaussNoise
{
Texture = texGaussNoise;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
AddressW = WRAP;
};
// Functions
uniform float2 pp < source = "pingpong"; min = 0; max = 128; step = 1; >;
static const float2 dither_uv = float2( BUFFER_WIDTH, BUFFER_HEIGHT ) / 512.0f;
float4 dither( sampler2D tex, float2 coords, int var, bool enabler, float str, bool motion, float swing )
{
coords.xy *= dither_uv.xy;
float4 noise = tex2D( tex, coords.xy );
float mot = motion ? pp.x + var : 0.0f;
noise = frac( noise + 0.61803398875f * mot );
noise = ( noise * 2.0f - 1.0f ) * swing;
return ( enabler ) ? noise * ( str / 255.0f ) : float4( 0.0f, 0.0f, 0.0f, 0.0f );
}

View File

@ -0,0 +1,263 @@
/*
Description : PD80 01A Correct Contrast for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_correctcontrast
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_fade <
ui_text = "----------------------------------------------";
ui_label = "Enable Time Based Fade";
ui_tooltip = "Enable Time Based Fade";
ui_category = "Global: Correct Contrasts";
> = true;
uniform bool freeze <
ui_label = "Freeze Correction";
ui_tooltip = "Freeze Correction";
ui_category = "Global: Correct Contrasts";
> = false;
uniform float transition_speed <
ui_type = "slider";
ui_label = "Time Based Fade Speed";
ui_tooltip = "Time Based Fade Speed";
ui_category = "Global: Correct Contrasts";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.5;
uniform bool rt_enable_whitepoint_correction <
ui_text = "----------------------------------------------";
ui_label = "Enable Whitepoint Correction";
ui_tooltip = "Enable Whitepoint Correction";
ui_category = "Whitepoint Correction";
> = false;
uniform float rt_wp_str <
ui_type = "slider";
ui_label = "White Point Correction Strength";
ui_tooltip = "White Point Correction Strength";
ui_category = "Whitepoint Correction";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform bool rt_enable_blackpoint_correction <
ui_text = "----------------------------------------------";
ui_label = "Enable Blackpoint Correction";
ui_tooltip = "Enable Blackpoint Correction";
ui_category = "Blackpoint Correction";
> = true;
uniform float rt_bp_str <
ui_type = "slider";
ui_label = "Black Point Correction Strength";
ui_tooltip = "Black Point Correction Strength";
ui_category = "Blackpoint Correction";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texDS_1_Max { Width = 32; Height = 32; Format = RGBA16F; };
texture texDS_1_Min { Width = 32; Height = 32; Format = RGBA16F; };
texture texPrevious { Width = 4; Height = 2; Format = RGBA16F; };
texture texDS_1x1 { Width = 4; Height = 2; Format = RGBA16F; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerDS_1_Max
{
Texture = texDS_1_Max;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerDS_1_Min
{
Texture = texDS_1_Min;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerPrevious
{
Texture = texPrevious;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerDS_1x1
{
Texture = texDS_1x1;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float frametime < source = "frametime"; >;
float3 interpolate( float3 o, float3 n, float factor, float ft )
{
return lerp( o.xyz, n.xyz, 1.0f - exp( -factor * ft ));
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
//Downscale to 32x32 min/max color matrix
void PS_MinMax_1( float4 pos : SV_Position, float2 texcoord : TEXCOORD, out float4 minValue : SV_Target0, out float4 maxValue : SV_Target1 )
{
float3 currColor;
minValue.xyz = 1.0f;
maxValue.xyz = 0.0f;
// RenderTarget size is 32x32
float pst = 0.03125f; // rcp( 32 )
float hst = 0.5f * pst; // half size
// Sample texture
float2 stexSize = float2( BUFFER_WIDTH, BUFFER_HEIGHT );
float2 start = floor(( texcoord.xy - hst ) * stexSize.xy ); // sample block start position
float2 stop = floor(( texcoord.xy + hst ) * stexSize.xy ); // ... end position
for( int y = start.y; y < stop.y; ++y )
{
for( int x = start.x; x < stop.x; ++x )
{
currColor = tex2Dfetch( ReShade::BackBuffer, int2( x, y ), 0 ).xyz;
// Dark color detection methods
minValue.xyz = min( minValue.xyz, currColor.xyz );
// Light color detection methods
maxValue.xyz = max( currColor.xyz, maxValue.xyz );
}
}
// Return
minValue = float4( minValue.xyz, 1.0f );
maxValue = float4( maxValue.xyz, 1.0f );
}
//Downscale to 32x32 to 1x1 min/max colors
float4 PS_MinMax_1x1( float4 pos : SV_Position, float2 texcoord : TEXCOORD ) : SV_Target
{
float3 minColor; float3 maxColor;
float3 minValue = 1.0f;
float3 maxValue = 0.0f;
//Get texture resolution
uint SampleRes = 32;
float Sigma = 0.0f;
for( int y = 0; y < SampleRes; ++y )
{
for( int x = 0; x < SampleRes; ++x )
{
// Dark color detection methods
minColor = tex2Dfetch( samplerDS_1_Min, int2( x, y), 0 ).xyz;
minValue.xyz = min( minValue.xyz, minColor.xyz );
// Light color detection methods
maxColor = tex2Dfetch( samplerDS_1_Max, int2( x, y ), 0 ).xyz;
maxValue.xyz = max( maxColor.xyz, maxValue.xyz );
}
}
//Try and avoid some flickering
//Not really working, too radical changes in min values sometimes
float3 prevMin = tex2D( samplerPrevious, float2( texcoord.x / 4.0f, texcoord.y )).xyz;
float3 prevMax = tex2D( samplerPrevious, float2(( texcoord.x + 2.0f ) / 4.0, texcoord.y )).xyz;
float smoothf = transition_speed * 4.0f + 0.5f;
float time = frametime * 0.001f;
maxValue.xyz = enable_fade ? interpolate( prevMax.xyz, maxValue.xyz, smoothf, time ) : maxValue.xyz;
minValue.xyz = enable_fade ? interpolate( prevMin.xyz, minValue.xyz, smoothf, time ) : minValue.xyz;
// Freeze Correction
maxValue.xyz = freeze ? prevMax.xyz : maxValue.xyz;
minValue.xyz = freeze ? prevMin.xyz : minValue.xyz;
// Return
if( pos.x < 2 )
return float4( minValue.xyz, 1.0f );
else
return float4( maxValue.xyz, 1.0f );
}
float4 PS_CorrectContrast(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float3 minValue = tex2D( samplerDS_1x1, float2( texcoord.x / 4.0f, texcoord.y )).xyz;
float3 maxValue = tex2D( samplerDS_1x1, float2(( texcoord.x + 2.0f ) / 4.0f, texcoord.y )).xyz;
// Black/White Point Change
float adjBlack = min( min( minValue.x, minValue.y ), minValue.z );
float adjWhite = max( max( maxValue.x, maxValue.y ), maxValue.z );
// Set min value
adjBlack = lerp( 0.0f, adjBlack, rt_bp_str );
adjBlack = rt_enable_blackpoint_correction ? adjBlack : 0.0f;
// Set max value
adjWhite = lerp( 1.0f, adjWhite, rt_wp_str );
adjWhite = rt_enable_whitepoint_correction ? adjWhite : 1.0f;
// Main color correction
color.xyz = saturate( color.xyz - adjBlack ) / saturate( adjWhite - adjBlack );
//color.xyz = tex2D( samplerDS_1_Max, texcoord ).xyz; // Debug
//color.xyz = tex2D( samplerDS_1_Min, texcoord ).xyz;
return float4( color.xyz, 1.0f );
}
float4 PS_StorePrev( float4 pos : SV_Position, float2 texcoord : TEXCOORD ) : SV_Target
{
float3 minValue = tex2D( samplerDS_1x1, float2( texcoord.x / 4.0f, texcoord.y )).xyz;
float3 maxValue = tex2D( samplerDS_1x1, float2(( texcoord.x + 2.0f ) / 4.0f, texcoord.y )).xyz;
if( pos.x < 2 )
return float4( minValue.xyz, 1.0f );
else
return float4( maxValue.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_01A_RT_Correct_Contrast
{
pass prod80_pass1
{
VertexShader = PostProcessVS;
PixelShader = PS_MinMax_1;
RenderTarget0 = texDS_1_Min;
RenderTarget1 = texDS_1_Max;
}
pass prod80_pass2
{
VertexShader = PostProcessVS;
PixelShader = PS_MinMax_1x1;
RenderTarget = texDS_1x1;
}
pass prod80_pass3
{
VertexShader = PostProcessVS;
PixelShader = PS_CorrectContrast;
}
pass prod80_pass4
{
VertexShader = PostProcessVS;
PixelShader = PS_StorePrev;
RenderTarget = texPrevious;
}
}
}

View File

@ -0,0 +1,497 @@
/*
Description : PD80 01B RT Correct Color for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
namespace pd80_correctcolor
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
#ifndef RT_PRECISION_LEVEL_0_TO_4
#define RT_PRECISION_LEVEL_0_TO_4 0
#endif
#ifndef RT_ENABLE_HIGH_PERF_MODE
#define RT_ENABLE_HIGH_PERF_MODE 0
#endif
#if( RT_ENABLE_HIGH_PERF_MODE > 1 || RT_ENABLE_HIGH_PERF_MODE < 0 )
#error "RT_ENABLE_HIGH_PERF_MODE has a range of 0 to 1"
#endif
#if( RT_PRECISION_LEVEL_0_TO_4 > 4 || RT_PRECISION_LEVEL_0_TO_4 < 0 )
#error "RT_PRECISION_LEVEL_0_TO_4 has a range of 0 to 4"
#endif
//// DEFINES ////////////////////////////////////////////////////////////////////
#if( RT_PRECISION_LEVEL_0_TO_4 == 0 )
#define RT_RES 1
#define RT_MIPLVL 0
#elif( RT_PRECISION_LEVEL_0_TO_4 == 1 )
#define RT_RES 2
#define RT_MIPLVL 1
#elif( RT_PRECISION_LEVEL_0_TO_4 == 2 )
#define RT_RES 4
#define RT_MIPLVL 2
#elif( RT_PRECISION_LEVEL_0_TO_4 == 3 )
#define RT_RES 8
#define RT_MIPLVL 3
#else
#define RT_RES 16
#define RT_MIPLVL 4
#endif
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int debug_mode < __UNIFORM_COMBO_INT1
ui_label = "Debug Mode";
ui_tooltip = "Debug Mode";
ui_category = "Debug Mode";
ui_items = "Default\0Min Color Texture\0Max Color Texture\0Mid Color Texture\0";
> = 0;
uniform bool enable_fade <
ui_text = "----------------------------------------------";
ui_label = "Enable Time Based Fade";
ui_tooltip = "Enable Time Based Fade";
ui_category = "Global: Remove Tint";
> = true;
uniform bool freeze <
ui_label = "Freeze Correction";
ui_tooltip = "Freeze Correction";
ui_category = "Global: Remove Tint";
> = false;
uniform float transition_speed <
ui_type = "slider";
ui_label = "Time Based Fade Speed";
ui_tooltip = "Time Based Fade Speed";
ui_category = "Global: Remove Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.5;
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global: Remove Tint";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global: Remove Tint";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform bool rt_enable_whitepoint_correction <
ui_text = "----------------------------------------------";
ui_label = "Enable Whitepoint Correction";
ui_tooltip = "Enable Whitepoint Correction";
ui_category = "Whitepoint: Remove Tint";
> = true;
uniform bool rt_whitepoint_respect_luma <
ui_label = "Respect Luma";
ui_tooltip = "Whitepoint: Respect Luma";
ui_category = "Whitepoint: Remove Tint";
> = true;
uniform int rt_whitepoint_method < __UNIFORM_COMBO_INT1
ui_label = "Color Detection Method";
ui_category = "Whitepoint: Remove Tint";
ui_items = "By Color Channel (auto-color)\0Find Light Color (auto-tone)\0";
> = 0;
uniform float rt_wp_str <
ui_type = "slider";
ui_label = "White Point Correction Strength";
ui_tooltip = "Whitepoint: White Point Correction Strength";
ui_category = "Whitepoint: Remove Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform float rt_wp_rl_str <
ui_type = "slider";
ui_label = "White Point Respect Luma Strength";
ui_tooltip = "Whitepoint: White Point Respect Luma Strength";
ui_category = "Whitepoint: Remove Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform bool rt_enable_blackpoint_correction <
ui_text = "----------------------------------------------";
ui_label = "Enable Blackpoint Correction";
ui_tooltip = "Enable Blackpoint Correction";
ui_category = "Blackpoint: Remove Tint";
> = true;
uniform bool rt_blackpoint_respect_luma <
ui_label = "Respect Luma";
ui_tooltip = "Blackpoint: Respect Luma";
ui_category = "Blackpoint: Remove Tint";
> = false;
uniform int rt_blackpoint_method < __UNIFORM_COMBO_INT1
ui_label = "Color Detection Method";
ui_category = "Blackpoint: Remove Tint";
ui_items = "By Color Channel (auto-color)\0Find Dark Color (auto-tone)\0";
> = 1;
uniform float rt_bp_str <
ui_type = "slider";
ui_label = "Black Point Correction Strength";
ui_tooltip = "Blackpoint: Black Point Correction Strength";
ui_category = "Blackpoint: Remove Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform float rt_bp_rl_str <
ui_type = "slider";
ui_label = "Black Point Respect Luma Strength";
ui_tooltip = "Blackpoint: Black Point Respect Luma Strength";
ui_category = "Blackpoint: Remove Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform bool rt_enable_midpoint_correction <
ui_text = "----------------------------------------------";
ui_label = "Enable Midtone Correction";
ui_tooltip = "Enable Midtone Correction";
ui_category = "Midtone: Remove Tint";
> = true;
uniform bool rt_midpoint_respect_luma <
ui_label = "Respect Luma";
ui_tooltip = "Midtone: Respect Luma";
ui_category = "Midtone: Remove Tint";
> = true;
uniform bool mid_use_alt_method <
ui_label = "Use average Dark-Light as Mid";
ui_tooltip = "Midtone: Use average Dark-Light as Mid";
ui_category = "Midtone: Remove Tint";
> = true;
uniform float midCC_scale <
ui_type = "slider";
ui_label = "Midtone Correction Scale";
ui_tooltip = "Midtone: Midtone Correction Scale";
ui_category = "Midtone: Remove Tint";
ui_min = 0.0f;
ui_max = 5.0f;
> = 0.5;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texColor { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; MipLevels = 5; };
texture texDS_1_Max { Width = 32; Height = 32; Format = RGBA16F; };
texture texDS_1_Min { Width = 32; Height = 32; Format = RGBA16F; };
texture texDS_1_Mid { Width = 32; Height = 32; Format = RGBA16F; };
texture texDS_1x1 { Width = 6; Height = 2; Format = RGBA16F; };
texture texPrevious { Width = 6; Height = 2; Format = RGBA16F; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerColor { Texture = texColor; };
sampler samplerDS_1_Max
{
Texture = texDS_1_Max;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerDS_1_Min
{
Texture = texDS_1_Min;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerDS_1_Mid
{
Texture = texDS_1_Mid;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerDS_1x1
{
Texture = texDS_1x1;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
sampler samplerPrevious
{
Texture = texPrevious;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float frametime < source = "frametime"; >;
float3 interpolate( float3 o, float3 n, float factor, float ft )
{
return lerp( o.xyz, n.xyz, 1.0f - exp( -factor * ft ));
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_WriteColor(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D( ReShade::BackBuffer, texcoord );
}
//Downscale to 32x32 min/max color matrix
void PS_MinMax_1( float4 pos : SV_Position, float2 texcoord : TEXCOORD, out float4 minValue : SV_Target0, out float4 maxValue : SV_Target1, out float4 midValue : SV_Target2 )
{
float3 currColor;
float3 minMethod0 = 1.0f;
float3 minMethod1 = 1.0f;
float3 maxMethod0 = 0.0f;
float3 maxMethod1 = 0.0f;
midValue = 0.0f;
float getMid; float getMid2;
float getMin; float getMin2;
float getMax; float getMax2;
float3 prevMin = tex2D( samplerPrevious, float2( texcoord.x / 6.0f, texcoord.y )).xyz;
float3 prevMax = tex2D( samplerPrevious, float2(( texcoord.x + 4.0f ) / 6.0f, texcoord.y )).xyz;
float middle = dot( float2( dot( prevMin.xyz, 0.333333f ), dot( prevMax.xyz, 0.333333f )), 0.5f );
middle = ( mid_use_alt_method ) ? middle : 0.5f;
// RenderTarget size is 32x32
float pst = 0.03125f; // rcp( 32 )
float hst = 0.5f * pst; // half size
// Sample texture
float2 stexSize = float2( BUFFER_WIDTH/RT_RES, BUFFER_HEIGHT/RT_RES );
uint OFFSET = 1 + RT_ENABLE_HIGH_PERF_MODE * 3;
float2 start = floor(( texcoord.xy - hst ) * stexSize.xy ); // sample block start position
float2 stop = floor(( texcoord.xy + hst ) * stexSize.xy ); // ... end position
[loop]
for( int y = start.y; y < stop.y && y < stexSize.y; y += OFFSET )
{
for( int x = start.x; x < stop.x && x < stexSize.x; x += OFFSET )
{
currColor = tex2Dfetch( samplerColor, int2( x, y ), RT_MIPLVL ).xyz;
// Dark color detection methods
// Per channel
minMethod0.xyz = min( minMethod0.xyz, currColor.xyz );
// By color
getMin = max( max( currColor.x, currColor.y ), currColor.z ) + dot( currColor.xyz, 1.0f );
getMin2 = max( max( minMethod1.x, minMethod1.y ), minMethod1.z ) + dot( minMethod1.xyz, 1.0f );
minMethod1.xyz = ( getMin2 >= getMin ) ? currColor.xyz : minMethod1.xyz;
// Mid point detection
getMid = dot( abs( currColor.xyz - middle ), 1.0f );
getMid2 = dot( abs( midValue.xyz - middle ), 1.0f );
midValue.xyz = ( getMid2 >= getMid ) ? currColor.xyz : midValue.xyz;
// Light color detection methods
// Per channel
maxMethod0.xyz = max( currColor.xyz, maxMethod0.xyz );
// By color
getMax = dot( currColor.xyz, 1.0f );
getMax2 = dot( maxMethod1.xyz, 1.0f );
maxMethod1.xyz = ( getMax >= getMax2 ) ? currColor.xyz : maxMethod1.xyz;
}
}
minValue.xyz = rt_blackpoint_method ? minMethod1.xyz : minMethod0.xyz;
maxValue.xyz = rt_whitepoint_method ? maxMethod1.xyz : maxMethod0.xyz;
// Return
minValue = float4( minValue.xyz, 1.0f );
maxValue = float4( maxValue.xyz, 1.0f );
midValue = float4( midValue.xyz, 1.0f );
}
//Downscale to 32x32 to 1x1 min/max colors
float4 PS_MinMax_1x1( float4 pos : SV_Position, float2 texcoord : TEXCOORD ) : SV_Target
{
float3 minColor; float3 maxColor; float3 midColor;
float3 minValue; float3 maxValue; float3 midValue;
float getMin; float getMin2;
float getMax; float getMax2;
float3 minMethod0 = 1.0f;
float3 minMethod1 = 1.0f;
float3 maxMethod0 = 0.0f;
float3 maxMethod1 = 0.0f;
midValue = 0.0f;
//Get texture resolution
int2 SampleRes = 32;
float Sigma = 0.0f;
for( int y = 0; y < SampleRes.y; ++y )
{
for( int x = 0; x < SampleRes.x; ++x )
{
// Dark color detection methods
minColor = tex2Dfetch( samplerDS_1_Min, int2( x, y ), 0 ).xyz;
// Per channel
minMethod0.xyz = min( minMethod0.xyz, minColor.xyz );
// By color
getMin = max( max( minColor.x, minColor.y ), minColor.z ) + dot( minColor.xyz, 1.0f );
getMin2 = max( max( minMethod1.x, minMethod1.y ), minMethod1.z ) + dot( minMethod1.xyz, 1.0f );
minMethod1.xyz = ( getMin2 >= getMin ) ? minColor.xyz : minMethod1.xyz;
// Mid point detection
midColor += tex2Dfetch( samplerDS_1_Mid, int2( x, y ), 0 ).xyz;
Sigma += 1.0f;
// Light color detection methods
maxColor = tex2Dfetch( samplerDS_1_Max, int2( x, y ), 0 ).xyz;
// Per channel
maxMethod0.xyz = max( maxColor.xyz, maxMethod0.xyz );
// By color
getMax = dot( maxColor.xyz, 1.0f );
getMax2 = dot( maxMethod1.xyz, 1.0f );
maxMethod1.xyz = ( getMax >= getMax2 ) ? maxColor.xyz : maxMethod1.xyz;
}
}
minValue.xyz = rt_blackpoint_method ? minMethod1.xyz : minMethod0.xyz;
maxValue.xyz = rt_whitepoint_method ? maxMethod1.xyz : maxMethod0.xyz;
midValue.xyz = midColor.xyz / Sigma;
// When minValue = maxValue means the entire color is thrown out with correction
// This is correct behavior because this means that color component has the same fixed value on ALL pixels
// No game developer should ever make a coloring like that, but, you never know
maxValue.xyz = ( minValue.xyz >= maxValue.xyz ) ? float3( 1.0f, 1.0f, 1.0f ) : maxValue.xyz;
// Try and avoid some flickering
// Not really working consistently, too radical changes in min values sometimes
float3 prevMin = tex2D( samplerPrevious, float2( texcoord.x / 6.0f, texcoord.y )).xyz;
float3 prevMid = tex2D( samplerPrevious, float2(( texcoord.x + 2.0f ) / 6.0f, texcoord.y )).xyz;
float3 prevMax = tex2D( samplerPrevious, float2(( texcoord.x + 4.0f ) / 6.0f, texcoord.y )).xyz;
float smoothf = transition_speed * 4.0f + 1.0f;
float time = frametime * 0.001f;
maxValue.xyz = enable_fade ? interpolate( prevMax.xyz, maxValue.xyz, smoothf, time ) : maxValue.xyz;
minValue.xyz = enable_fade ? interpolate( prevMin.xyz, minValue.xyz, smoothf, time ) : minValue.xyz;
midValue.xyz = enable_fade ? interpolate( prevMid.xyz, midValue.xyz, smoothf, time ) : midValue.xyz;
// Freeze Correction
maxValue.xyz = freeze ? prevMax.xyz : maxValue.xyz;
minValue.xyz = freeze ? prevMin.xyz : minValue.xyz;
midValue.xyz = freeze ? prevMid.xyz : midValue.xyz;
// Return
if( pos.x < 2 )
return float4( minValue.xyz, 1.0f );
else if( pos.x >= 2 && pos.x < 4 )
return float4( midValue.xyz, 1.0f );
else
return float4( maxValue.xyz, 1.0f );
return float4( 0.5, 0.5, 0.5, 1.0 );
}
float4 PS_RemoveTint(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerColor, texcoord );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 0, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.xyz );
// Grab min, max, mid values
float3 minValue = tex2D( samplerDS_1x1, float2( texcoord.x / 6.0f, texcoord.y )).xyz;
float3 midValue = tex2D( samplerDS_1x1, float2(( texcoord.x + 2.0f ) / 6.0f, texcoord.y )).xyz;
float3 maxValue = tex2D( samplerDS_1x1, float2(( texcoord.x + 4.0f ) / 6.0f, texcoord.y )).xyz;
// Get middle correction method
float middle = dot( float2( dot( minValue.xyz, 0.333333f ), dot( maxValue.xyz, 0.333333f )), 0.5f );
middle = mid_use_alt_method ? middle : 0.5f;
// Set min value
minValue.xyz = lerp( 0.0f, minValue.xyz, rt_bp_str );
minValue.xyz = rt_enable_blackpoint_correction ? minValue.xyz : 0.0f;
// Set max value
maxValue.xyz = lerp( 1.0f, maxValue.xyz, rt_wp_str );
maxValue.xyz = rt_enable_whitepoint_correction ? maxValue.xyz : 1.0f;
// Set mid value
midValue.xyz = midValue.xyz - middle;
midValue.xyz *= midCC_scale;
midValue.xyz = rt_enable_midpoint_correction ? midValue.xyz : 0.0f;
// Main color correction
color.xyz = saturate( color.xyz - minValue.xyz ) / ( maxValue.xyz - minValue.xyz );
// White Point luma preservation
float avgMax = dot( maxValue.xyz, 0.333333f );
color.xyz = lerp( color.xyz, color.xyz * avgMax, rt_whitepoint_respect_luma * rt_wp_rl_str );
// Black Point luma preservation
float avgMin = dot( minValue.xyz, 0.333333f );
color.xyz = lerp( color.xyz, color.xyz * ( 1.0f - avgMin ) + avgMin, rt_blackpoint_respect_luma * rt_bp_rl_str );
// Mid Point correction
float avgCol = dot( color.xyz, 0.333333f ); // Avg after main correction
float avgMid = dot( midValue.xyz, 0.333333f );
avgCol = 1.0f - abs( avgCol * 2.0f - 1.0f );
color.xyz = saturate( color.xyz - midValue.xyz * avgCol + avgMid * avgCol * rt_midpoint_respect_luma );
// Debug
switch( debug_mode )
{
case 0: { color.xyz = color.xyz; } break;
case 1: { color.xyz = tex2D( samplerDS_1_Min, texcoord ).xyz; } break;
case 2: { color.xyz = tex2D( samplerDS_1_Max, texcoord ).xyz; } break;
case 3: { color.xyz = tex2D( samplerDS_1_Mid, texcoord ).xyz; } break;
}
return float4( color.xyz, 1.0f );
}
float4 PS_StorePrev( float4 pos : SV_Position, float2 texcoord : TEXCOORD ) : SV_Target
{
float3 minValue = tex2D( samplerDS_1x1, float2( texcoord.x / 6.0f, texcoord.y )).xyz;
float3 midValue = tex2D( samplerDS_1x1, float2(( texcoord.x + 2.0f ) / 6.0f, texcoord.y )).xyz;
float3 maxValue = tex2D( samplerDS_1x1, float2(( texcoord.x + 4.0f ) / 6.0f, texcoord.y )).xyz;
if( pos.x < 2 )
return float4( minValue.xyz, 1.0f );
else if( pos.x >= 2 && pos.x < 4 )
return float4( midValue.xyz, 1.0f );
else
return float4( maxValue.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_01B_RT_Correct_Color
< ui_tooltip = "Remove Tint/Color Cast\n\n"
"Automatically adjust Blackpoint, Whitepoint, and remove color tints/casts while enhancing contrast.\n"
"Both correcting per individual channel, as well as Light/Dark colors are supported.\n"
"This shader will not adjust tinting applied in gamma, and this is considered out of scope.\n\n"
"RT_PRECISION_LEVEL_0_TO_4\n"
"Sets the precision level in detecting the white and black points. Higher levels mean less precision and more color removal.\n"
"Too high values will remove significant amounts of color and may cause shifts in color, contrast, or banding artefacts.";>
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_WriteColor;
RenderTarget = texColor;
}
pass prod80_pass1
{
VertexShader = PostProcessVS;
PixelShader = PS_MinMax_1;
RenderTarget0 = texDS_1_Min;
RenderTarget1 = texDS_1_Max;
RenderTarget2 = texDS_1_Mid;
}
pass prod80_pass2
{
VertexShader = PostProcessVS;
PixelShader = PS_MinMax_1x1;
RenderTarget = texDS_1x1;
}
pass prod80_pass3
{
VertexShader = PostProcessVS;
PixelShader = PS_RemoveTint;
}
pass prod80_pass4
{
VertexShader = PostProcessVS;
PixelShader = PS_StorePrev;
RenderTarget = texPrevious;
}
}
}

View File

@ -0,0 +1,248 @@
/*
Description : PD80 01 Color Gamut for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_colorconversion
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int colorgamut <
ui_type = "combo";
ui_items= "No Change\0Adobe RGB\0Apple RGB\0Best RGB\0Beta RGB\0Bruce RGB\0CIE RGB\0Color Match\0Don\0ECI\0Ekta Space PS5\0NTSC\0PAL-SECAM\0ProPhoto\0SMPTE-C\0Wide Gamut RGB\0";
ui_label = "Color Gamut Selection";
ui_tooltip = "Color Gamut Selection";
> = 0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//D65
static const float3x3 sRGB_To_XYZ = float3x3(
0.4124564, 0.3575761, 0.1804375,
0.2126729, 0.7151522, 0.0721750,
0.0193339, 0.1191920, 0.9503041);
//D65 (0)
static const float3x3 XYZ_To_sRGB = float3x3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252);
//D65 (1)
static const float3x3 XYZ_To_AdobeRGB = float3x3(
2.0413690, -0.5649464, -0.3446944,
-0.9692660, 1.8760108, 0.0415560,
0.0134474, -0.1183897, 1.0154096);
//D65 (2)
static const float3x3 XYZ_To_AppleRGB = float3x3(
2.9515373, -1.2894116, -0.4738445,
-1.0851093, 1.9908566, 0.0372026,
0.0854934, -0.2694964, 1.0912975);
//D50 (3)
static const float3x3 XYZ_To_BestRGB = float3x3(
1.7552599, -0.4836786, -0.2530000,
-0.5441336, 1.5068789, 0.0215528,
0.0063467, -0.0175761, 1.2256959);
//D50 (4)
static const float3x3 XYZ_To_BetaRGB = float3x3(
1.6832270, -0.4282363, -0.2360185,
-0.7710229, 1.7065571, 0.0446900,
0.0400013, -0.0885376, 1.2723640);
//D65 (5)
static const float3x3 XYZ_To_BruceRGB = float3x3(
2.7454669, -1.1358136, -0.4350269,
-0.9692660, 1.8760108, 0.0415560,
0.0112723, -0.1139754, 1.0132541);
//E (6)
static const float3x3 XYZ_To_CIERGB = float3x3(
2.3706743, -0.9000405, -0.4706338,
-0.5138850, 1.4253036, 0.0885814,
0.0052982, -0.0146949, 1.0093968);
//D50 (7)
static const float3x3 XYZ_To_ColorMatch = float3x3(
2.6422874, -1.2234270, -0.3930143,
-1.1119763, 2.0590183, 0.0159614,
0.0821699, -0.2807254, 1.4559877);
//D50 (8)
static const float3x3 XYZ_To_Don = float3x3(
1.7603902, -0.4881198, -0.2536126,
-0.7126288, 1.6527432, 0.0416715,
0.0078207, -0.0347411, 1.2447743);
//D50 (9)
static const float3x3 XYZ_To_ECI = float3x3(
1.7827618, -0.4969847, -0.2690101,
-0.9593623, 1.9477962, -0.0275807,
0.0859317, -0.1744674, 1.3228273);
//D50 (10)
static const float3x3 XYZ_To_EktaSpacePS5 = float3x3(
2.0043819, -0.7304844, -0.2450052,
-0.7110285, 1.6202126, 0.0792227,
0.0381263, -0.0868780, 1.2725438);
//C (11)
static const float3x3 XYZ_To_NTSC = float3x3(
1.9099961, -0.5324542, -0.2882091,
-0.9846663, 1.9991710, -0.0283082,
0.0583056, -0.1183781, 0.8975535);
//D65 (12)
static const float3x3 XYZ_To_PALSECAM = float3x3(
3.0628971, -1.3931791, -0.4757517,
-0.9692660, 1.8760108, 0.0415560,
0.0678775, -0.2288548, 1.0693490);
//D50 (13)
static const float3x3 XYZ_To_ProPhoto = float3x3(
1.3459433, -0.2556075, -0.0511118,
-0.5445989, 1.5081673, 0.0205351,
0.0000000, 0.0000000, 1.2118128);
//D65 (14)
static const float3x3 XYZ_To_SMPTEC = float3x3(
3.5053960, -1.7394894, -0.5439640,
-1.0690722, 1.9778245, 0.0351722,
0.0563200, -0.1970226, 1.0502026);
//D50 (15)
static const float3x3 XYZ_To_WideGamutRGB = float3x3(
1.4628067, -0.1840623, -0.2743606,
-0.5217933, 1.4472381, 0.0677227,
0.0349342, -0.0968930, 1.2884099);
//D65 to D50
static const float3x3 D65_To_D50 = float3x3(
1.0478112, 0.0228866, -0.0501270,
0.0295424, 0.9904844, -0.0170491,
-0.0092345, 0.0150436, 0.7521316);
//D65 to E
static const float3x3 D65_To_E = float3x3(
1.0502616, 0.0270757, -0.0232523,
0.0390650, 0.9729502, -0.0092579,
-0.0024047, 0.0026446, 0.918087);
//D65 to C
static const float3x3 D65_To_C = float3x3(
1.0097785, 0.0070419, 0.0127971,
0.0123113, 0.9847094, 0.0032962,
0.0038284, -0.0072331, 1.0891639);
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float3 LinearTosRGB( float3 color )
{
float3 x = color * 12.92f;
float3 y = 1.055f * pow(saturate(color), 1.0f / 2.4f) - 0.055f;
float3 clr = color;
clr.r = color.r < 0.0031308f ? x.r : y.r;
clr.g = color.g < 0.0031308f ? x.g : y.g;
clr.b = color.b < 0.0031308f ? x.b : y.b;
return clr;
}
float3 SRGBToLinear( float3 color )
{
float3 x = color / 12.92f;
float3 y = pow(max((color + 0.055f) / 1.055f, 0.0f), 2.4f);
float3 clr = color;
clr.r = color.r <= 0.04045f ? x.r : y.r;
clr.g = color.g <= 0.04045f ? x.g : y.g;
clr.b = color.b <= 0.04045f ? x.b : y.b;
return clr;
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_ColorConversion(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
color.xyz = SRGBToLinear( color.xyz );
color.xyz = mul( sRGB_To_XYZ, color.xyz );
float3x3 gamut;
switch( colorgamut )
{
case 0: { gamut = XYZ_To_sRGB; } break;
case 1: { gamut = XYZ_To_AdobeRGB; } break;
case 2: { gamut = XYZ_To_AppleRGB; } break;
case 3: { gamut = XYZ_To_BestRGB; } break;
case 4: { gamut = XYZ_To_BetaRGB; } break;
case 5: { gamut = XYZ_To_BruceRGB; } break;
case 6: { gamut = XYZ_To_CIERGB; } break;
case 7: { gamut = XYZ_To_ColorMatch; } break;
case 8: { gamut = XYZ_To_Don; } break;
case 9: { gamut = XYZ_To_ECI; } break;
case 10: { gamut = XYZ_To_EktaSpacePS5; } break;
case 11: { gamut = XYZ_To_NTSC; } break;
case 12: { gamut = XYZ_To_PALSECAM; } break;
case 13: { gamut = XYZ_To_ProPhoto; } break;
case 14: { gamut = XYZ_To_SMPTEC; } break;
case 15: { gamut = XYZ_To_WideGamutRGB; } break;
}
float3x3 refwhitemat = float3x3(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0);
if( colorgamut == 3 ) refwhitemat = D65_To_D50;
if( colorgamut == 4 ) refwhitemat = D65_To_D50;
if( colorgamut == 6 ) refwhitemat = D65_To_E;
if( colorgamut == 7 ) refwhitemat = D65_To_D50;
if( colorgamut == 8 ) refwhitemat = D65_To_D50;
if( colorgamut == 9 ) refwhitemat = D65_To_D50;
if( colorgamut == 10 ) refwhitemat = D65_To_D50;
if( colorgamut == 11 ) refwhitemat = D65_To_C;
if( colorgamut == 13 ) refwhitemat = D65_To_D50;
if( colorgamut == 15 ) refwhitemat = D65_To_D50;
color.xyz = mul( gamut, mul( refwhitemat, color.xyz ));
color.xyz = LinearTosRGB( color.xyz );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_01_Color_Gamut
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_ColorConversion;
}
}
}

View File

@ -0,0 +1,813 @@
/*
Description : PD80 01 HQ Bloom for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits (exposure)
- Padraic Hennessy for the logic
https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/
- Padraic Hennessy for the logic
https://placeholderart.wordpress.com/2014/12/15/implementing-a-physically-based-camera-automatic-exposure/
- MJP and David Neubelt for the method
https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/Exposure.hlsl
License: MIT, Copyright (c) 2016 MJP
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Color_Spaces.fxh"
#include "PD80_00_Base_Effects.fxh"
namespace pd80_hqbloom
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
// Funky stuff
#ifndef BLOOM_ENABLE_CA
#define BLOOM_ENABLE_CA 0
#endif
// Min: 0, Max: 3 | Bloom Quality, 0 is best quality (full screen) and values higher than that will progessively use lower resolution texture. Value 3 will use 1/4th screen resolution texture size
// 0 = Fullscreen - Ultra
// 1 = 1/4th size - High
// 2 = 1/16th size - Medium
// Default = High quality (1) as difference is nearly impossible to tell during gameplay, and performance 60% faster than Ultra (0)
// Using medium quality can show some artifacts because of the low resolution of texture upscaled to fullscreen when using CA, however it's very fast
#ifndef BLOOM_QUALITY_0_TO_2
#define BLOOM_QUALITY_0_TO_2 1
#endif
#ifndef BLOOM_LOOPCOUNT
#define BLOOM_LOOPCOUNT 300
#endif
#ifndef BLOOM_LIMITER
#define BLOOM_LIMITER 0.0001
#endif
#ifndef BLOOM_USE_FOCUS_BLOOM
#define BLOOM_USE_FOCUS_BLOOM 0
#endif
// Dodgy code that should avoid some compilation errors that seem to happen sometimes for no particular reason
#if( BLOOM_QUALITY_0_TO_2 > 2 )
#define BLOOM_MIPLVL 2
#elif( BLOOM_QUALITY_0_TO_2 < 0 )
#define BLOOM_MIPLVL 0
#else
#define BLOOM_MIPLVL BLOOM_QUALITY_0_TO_2
#endif
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool debugBloom <
ui_label = "Show only bloom on screen";
ui_category = "Bloom debug";
> = false;
uniform float dither_strength <
ui_label = "Bloom Dither Stength";
ui_tooltip = "Bloom Dither Stength";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 0.0;
ui_max = 10.0;
> = 2.0;
uniform float BloomMix <
ui_label = "Bloom Mix";
ui_tooltip = "Bloom Mix";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.5;
uniform float BloomLimit <
ui_label = "Bloom Threshold";
ui_tooltip = "Bloom Threshold";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.333;
uniform float GreyValue <
ui_label = "Bloom Exposure 50% Greyvalue";
ui_tooltip = "Bloom Exposure 50% Greyvalue";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.333;
uniform float bExposure <
ui_label = "Bloom Exposure";
ui_tooltip = "Bloom Exposure";
ui_category = "Bloom";
ui_type = "slider";
ui_min = -1.0;
ui_max = 5.0;
> = 0.0;
#if( BLOOM_USE_FOCUS_BLOOM )
uniform float fBloomStrength <
ui_label = "Bloom Width (Focus Center) Bias";
ui_tooltip = "Bloom Width (Focus Center) Bias";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.25;
uniform float BlurSigmaNarrow <
ui_label = "Bloom Width (Focus Center)";
ui_tooltip = "Bloom Width (Focus Center)";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 10.0;
ui_max = 40.0;
> = 15.0;
#endif
uniform float BlurSigma <
ui_label = "Bloom Width";
ui_tooltip = "Bloom Width";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 10.0;
ui_max = 300.0;
> = 30.0;
uniform float BloomSaturation <
ui_label = "Bloom Add Saturation";
ui_tooltip = "Bloom Add Saturation";
ui_category = "Bloom";
ui_type = "slider";
ui_min = 0.0;
ui_max = 2.0;
> = 0.0;
#if( BLOOM_ENABLE_CA == 0 )
uniform bool enableBKelvin <
ui_label = "Enable Bloom Color Temp (K)";
ui_tooltip = "Enable Bloom Color Temp (K)";
ui_category = "Bloom Color Temperature";
> = false;
uniform uint BKelvin <
ui_type = "slider";
ui_label = "Bloom Color Temp (K)";
ui_tooltip = "Bloom Color Temp (K)";
ui_category = "Bloom Color Temperature";
ui_min = 1000;
ui_max = 40000;
> = 6500;
#endif
#if( BLOOM_ENABLE_CA == 1 )
uniform int CA_type < __UNIFORM_COMBO_INT1
ui_label = "Chromatic Aberration Type";
ui_tooltip = "Chromatic Aberration Type";
ui_category = "Chromatic Aberration";
ui_items = "Center Weighted Radial\0Center Weighted Longitudinal\0Full screen Radial\0Full screen Longitudinal\0";
> = 0;
uniform bool use_only_ca <
ui_label = "Use only CA";
ui_tooltip = "Use only CA";
ui_category = "Chromatic Aberration";
> = false;
uniform int degrees <
ui_type = "slider";
ui_label = "CA Rotation Offset";
ui_tooltip = "CA Rotation Offset";
ui_category = "Chromatic Aberration";
ui_min = 0;
ui_max = 360;
ui_step = 1;
> = 135;
uniform float CA <
ui_type = "slider";
ui_label = "CA Global Width";
ui_tooltip = "CA Global Width";
ui_category = "Chromatic Aberration";
ui_min = -150.0f;
ui_max = 150.0f;
> = 60.0;
uniform float CA_strength <
ui_type = "slider";
ui_label = "CA Effect Strength";
ui_tooltip = "CA Effect Strength";
ui_category = "Chromatic Aberration";
ui_min = 0.0f;
ui_max = 5.0f;
> = 0.5;
#endif
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texPrepLOD { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; MipLevels = 5; };
texture texBLuma { Width = 256; Height = 256; Format = R16F; MipLevels = 9; };
texture texBAvgLuma { Format = R16F; };
texture texBPrevAvgLuma { Format = R16F; };
#if( BLOOM_ENABLE_CA == 1 )
texture texCABloom { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
#endif
#if( BLOOM_QUALITY_0_TO_2 == 0 )
texture texBloomIn { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
texture texBloomH { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
texture texBloom { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
texture texBloomAll { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
#if( BLOOM_USE_FOCUS_BLOOM )
texture texBloomHF { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
texture texBloomF { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
#endif
#define SWIDTH BUFFER_WIDTH
#define SHEIGHT BUFFER_HEIGHT
#elif( BLOOM_QUALITY_0_TO_2 == 1 )
#define SWIDTH ( BUFFER_WIDTH / 2 )
#define SHEIGHT ( BUFFER_HEIGHT / 2 )
texture texBloomIn { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloomH { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloom { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloomAll { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
#if( BLOOM_USE_FOCUS_BLOOM )
texture texBloomF { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloomHF { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
#endif
#else
#define SWIDTH ( BUFFER_WIDTH / 4 )
#define SHEIGHT ( BUFFER_HEIGHT / 4 )
texture texBloomIn { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloomH { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloom { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloomAll { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
#if( BLOOM_USE_FOCUS_BLOOM )
texture texBloomF { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
texture texBloomHF { Width = SWIDTH; Height = SHEIGHT; Format = RGBA16F; };
#endif
#endif
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerLODColor { Texture = texPrepLOD; };
sampler samplerLinColor { Texture = ReShade::BackBufferTex; SRGBTexture = true; };
sampler samplerBLuma { Texture = texBLuma; };
sampler samplerBAvgLuma { Texture = texBAvgLuma; };
sampler samplerBPrevAvgLuma { Texture = texBPrevAvgLuma; };
sampler samplerBloomIn
{
Texture = texBloomIn;
AddressU = BORDER;
AddressV = BORDER;
AddressW = BORDER;
};
sampler samplerBloomH
{
Texture = texBloomH;
AddressU = BORDER;
AddressV = BORDER;
AddressW = BORDER;
};
#if( BLOOM_USE_FOCUS_BLOOM )
sampler samplerBloomHF
{
Texture = texBloomHF;
AddressU = BORDER;
AddressV = BORDER;
AddressW = BORDER;
};
sampler samplerBloomF { Texture = texBloomF; };
#endif
#if( BLOOM_ENABLE_CA == 1 )
sampler samplerCABloom { Texture = texCABloom; };
#endif
sampler samplerBloom { Texture = texBloom; };
sampler samplerBloomAll { Texture = texBloomAll; };
//// DEFINES ////////////////////////////////////////////////////////////////////
uniform float frametime < source = "frametime"; >;
#define LumCoeff float3(0.212656, 0.715158, 0.072186)
#define PI 3.141592f
#define LOOPCOUNT 500.0f
#define aspect float( BUFFER_WIDTH * BUFFER_RCP_HEIGHT )
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, LumCoeff );
}
float Log2Exposure( in float avgLuminance, in float GreyValue )
{
float exposure = 0.0f;
avgLuminance = max(avgLuminance, 0.000001f);
// GreyValue should be 0.148 based on https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/
// But more success using higher values >= 0.5
float linExp = GreyValue / avgLuminance;
exposure = log2( linExp );
return exposure;
}
float3 CalcExposedColor( in float3 color, in float avgLuminance, in float offset, in float GreyValue )
{
float exposure = Log2Exposure( avgLuminance, GreyValue );
exposure += offset; //offset = exposure
return exp2( exposure ) * color;
}
float3 screen( in float3 c, in float3 b )
{
return 1.0f - ( 1.0f - c ) * ( 1.0f - b );
}
//// COMPUTE SHADERS ////////////////////////////////////////////////////////////
// Not supported in ReShade (?)
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float PS_WriteBLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerLinColor, texcoord );
float luma = getLuminance( color.xyz );
luma = max( luma, BloomLimit ); // Bloom threshold
return log2( luma );
}
float PS_AvgBLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float luma = tex2Dlod( samplerBLuma, float4(0.5f, 0.5f, 0, 8 )).x;
luma = exp2( luma );
float prevluma = tex2D( samplerBPrevAvgLuma, float2( 0.5f, 0.5f )).x;
float fps = max( 1000.0f / frametime, 0.001f );
fps *= 0.5f; //approx. 1 second delay to change luma between bright and dark
float avgLuma = lerp( prevluma, luma, saturate( 1.0f / fps ));
return avgLuma;
}
float4 PS_PrepLOD(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D( ReShade::BackBuffer, texcoord );
}
float4 PS_BloomIn(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2Dlod( samplerLODColor, float4( texcoord.xy, 0, BLOOM_MIPLVL ));
float luma = tex2D( samplerBAvgLuma, float2( 0.5f, 0.5f )).x;
luma = clamp( luma, 0.000001f, 0.999999f );
color.xyz = saturate( color.xyz - luma ) / saturate( 1.0f - luma );
color.xyz = CalcExposedColor( color.xyz, luma, bExposure, GreyValue );
return float4( color.xyz, 1.0f );
}
#if( !BLOOM_USE_FOCUS_BLOOM )
float4 PS_GaussianH(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBloomIn, texcoord );
float px = rcp( SWIDTH );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float2 buffSigma = 0.0f;
#if( BLOOM_QUALITY_0_TO_2 == 0 )
float bSigma = BlurSigma;
#elif( BLOOM_QUALITY_0_TO_2 == 1 )
float bSigma = BlurSigma * 0.5f;
#else
float bSigma = BlurSigma * 0.25f;
#endif
//Gaussian Math
float3 Sigma;
Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
//Center Weight
color.xyz *= Sigma.x;
//Adding to total sum of distributed weights
SigmaSum += Sigma.x;
//Setup next weight
Sigma.xy *= Sigma.yz;
[loop]
for( int i = 0; i < BLOOM_LOOPCOUNT && Sigma.x > BLOOM_LIMITER; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2Dlod( samplerBloomIn, float4( texcoord.xy + float2( pxlOffset * px, 0.0f ), 0, 0 )) * buffSigma.y;
color += tex2Dlod( samplerBloomIn, float4( texcoord.xy - float2( pxlOffset * px, 0.0f ), 0, 0 )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color /= SigmaSum;
return color;
}
#endif
#if( BLOOM_USE_FOCUS_BLOOM )
void PS_GaussianH(float4 pos : SV_Position, float2 texcoord : TEXCOORD, out float4 bloom1 : SV_Target0, out float4 bloom2 : SV_Target1)
{
// This part of shader writes both wide and narrow gaussian horizontal during the same pass to avoid sampling same texture twice
// Bloom quality setting
#if( BLOOM_QUALITY_0_TO_2 == 0 )
float Mult = 1.0f;
#elif( BLOOM_QUALITY_0_TO_2 == 1 )
float Mult = 0.5f;
#else
float Mult = 0.25f;
#endif
// Required variables
float px = rcp( SWIDTH );
float pxlOffset = 1.5f;
// Color
bloom1 = tex2D( samplerBloomIn, texcoord );
bloom2 = bloom1;
// Wide bloom
float b1_Sum = 0.0f;
float2 b1_tSigma = 0.0f;
float b1_Width = BlurSigma * Mult;
float3 b1_Sigma;
b1_Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * b1_Width );
b1_Sigma.y = exp( -0.5f / ( b1_Width * b1_Width ));
b1_Sigma.z = b1_Sigma.y * b1_Sigma.y;
bloom1 *= b1_Sigma.x;
b1_Sum += b1_Sigma.x;
b1_Sigma.xy *= b1_Sigma.yz;
// Narrow bloom
float b2_Sum = 0.0f;
float2 b2_tSigma = 0.0f;
float b2_Width = BlurSigmaNarrow * Mult;
float3 b2_Sigma;
b2_Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * b2_Width );
b2_Sigma.y = exp( -0.5f / ( b2_Width * b2_Width ));
b2_Sigma.z = b2_Sigma.y * b2_Sigma.y;
bloom2 *= b2_Sigma.x;
b2_Sum += b2_Sigma.x;
b2_Sigma.xy *= b2_Sigma.yz;
// Temp variables
float4 temp1;
float4 temp2;
[loop]
for( int i = 0; i < BLOOM_LOOPCOUNT && b1_Sigma.x > BLOOM_LIMITER; ++i )
{
// Setup weights (wide)
b1_tSigma.x = b1_Sigma.x * b1_Sigma.y;
b1_tSigma.y = b1_Sigma.x + b1_tSigma.x;
// Setup weights (narrow)
b2_tSigma.x = b2_Sigma.x * b2_Sigma.y;
b2_tSigma.y = b2_Sigma.x + b2_tSigma.x;
// Fetch
temp1 = tex2Dlod( samplerBloomIn, float4( texcoord.xy + float2( pxlOffset * px, 0.0f ), 0, 0 ));
temp2 = tex2Dlod( samplerBloomIn, float4( texcoord.xy - float2( pxlOffset * px, 0.0f ), 0, 0 ));
// Merge
bloom1 += temp1 * b1_tSigma.y;
bloom1 += temp2 * b1_tSigma.y;
bloom2 += temp1 * b2_tSigma.y;
bloom2 += temp2 * b2_tSigma.y;
// Sum
b1_Sum += 2.0f * b1_tSigma.y;
b2_Sum += 2.0f * b2_tSigma.y;
// Next offset
pxlOffset += 2.0f;
// Next weights
b1_Sigma.xy *= b1_Sigma.yz;
b1_Sigma.xy *= b1_Sigma.yz;
b2_Sigma.xy *= b2_Sigma.yz;
b2_Sigma.xy *= b2_Sigma.yz;
}
bloom1 /= b1_Sum;
bloom2 /= b2_Sum;
}
#endif
float4 PS_GaussianV(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBloomH, texcoord );
float py = rcp( SHEIGHT );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float2 buffSigma = 0.0f;
#if( BLOOM_QUALITY_0_TO_2 == 0 )
float bSigma = BlurSigma;
#elif( BLOOM_QUALITY_0_TO_2 == 1 )
float bSigma = BlurSigma * 0.5f;
#else
float bSigma = BlurSigma * 0.25f;
#endif
//Gaussian Math
float3 Sigma;
Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
//Center Weight
color.xyz *= Sigma.x;
//Adding to total sum of distributed weights
SigmaSum += Sigma.x;
//Setup next weight
Sigma.xy *= Sigma.yz;
[loop]
for( int i = 0; i < BLOOM_LOOPCOUNT && Sigma.x > BLOOM_LIMITER; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2Dlod( samplerBloomH, float4( texcoord.xy + float2( 0.0f, pxlOffset * py ), 0, 0 )) * buffSigma.y;
color += tex2Dlod( samplerBloomH, float4( texcoord.xy - float2( 0.0f, pxlOffset * py ), 0, 0 )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color /= SigmaSum;
return color;
}
#if( BLOOM_USE_FOCUS_BLOOM )
float4 PS_GaussianVF(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBloomHF, texcoord );
float py = rcp( SHEIGHT );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float2 buffSigma = 0.0f;
#if( BLOOM_QUALITY_0_TO_2 == 0 )
float bSigma = BlurSigmaNarrow;
#elif( BLOOM_QUALITY_0_TO_2 == 1 )
float bSigma = BlurSigmaNarrow * 0.5f;
#else
float bSigma = BlurSigmaNarrow * 0.25f;
#endif
//Gaussian Math
float3 Sigma;
Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
//Center Weight
color.xyz *= Sigma.x;
//Adding to total sum of distributed weights
SigmaSum += Sigma.x;
//Setup next weight
Sigma.xy *= Sigma.yz;
[loop]
for( int i = 0; i < BLOOM_LOOPCOUNT && Sigma.x > BLOOM_LIMITER; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2Dlod( samplerBloomHF, float4( texcoord.xy + float2( 0.0f, pxlOffset * py ), 0, 0 )) * buffSigma.y;
color += tex2Dlod( samplerBloomHF, float4( texcoord.xy - float2( 0.0f, pxlOffset * py ), 0, 0 )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color /= SigmaSum;
return color;
}
#endif
float4 PS_Combine(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 widebloom = tex2D( samplerBloom, texcoord );
#if( BLOOM_USE_FOCUS_BLOOM )
float4 narrbloom = tex2D( samplerBloomF, texcoord );
return saturate( widebloom * ( 1.0 - fBloomStrength ) + narrbloom * fBloomStrength );
#else
return widebloom;
#endif
}
#if( BLOOM_ENABLE_CA )
float4 PS_CA(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = 0.0f;
float3 orig = tex2D( samplerBloomAll, texcoord ).xyz;
float px = BUFFER_RCP_WIDTH;
float py = BUFFER_RCP_HEIGHT;
float2 coords = texcoord.xy * 2.0f - 1.0f;
float2 uv = coords.xy;
coords.xy /= float2( 1.0f / aspect, 1.0f );
float2 caintensity= length( coords.xy ); // * 2.0f for higher weight in center
caintensity.y = caintensity.x * caintensity.x + 1.0f;
caintensity.x = 1.0f - ( 1.0f / ( caintensity.y * caintensity.y ));
int degreesY = degrees;
float c = 0.0f;
float s = 0.0f;
switch( CA_type )
{
// Radial: Y + 90 w/ multiplying with uv.xy
case 0:
{
degreesY = degrees + 90 > 360 ? degreesY = degrees + 90 - 360 : degrees + 90;
c = cos( radians( degrees )) * uv.x;
s = sin( radians( degreesY )) * uv.y;
}
break;
// Longitudinal: X = Y w/o multiplying with uv.xy
case 1:
{
c = cos( radians( degrees ));
s = sin( radians( degreesY ));
}
break;
// Full screen Radial
case 2:
{
degreesY = degrees + 90 > 360 ? degreesY = degrees + 90 - 360 : degrees + 90;
caintensity.x = 1.0f;
c = cos( radians( degrees )) * uv.x;
s = sin( radians( degreesY )) * uv.y;
}
break;
// Full screen Longitudinal
case 3:
{
caintensity.x = 1.0f;
c = cos( radians( degrees ));
s = sin( radians( degreesY ));
}
break;
}
float3 huecolor = 0.0f;
float3 temp = 0.0f;
float o1 = 7.0f;
float o2 = 0.0f;
float3 d = 0.0f;
// Scale CA (hackjob!)
float caWidth = CA * ( max( BUFFER_WIDTH, BUFFER_HEIGHT ) / 1920.0f ); // Scaled for 1920, raising resolution in X or Y should raise scale
float offsetX = px * c * caintensity.x;
float offsetY = py * s * caintensity.x;
for( float i = 0; i < 8; ++i )
{
huecolor.xyz = HUEToRGB( i / 8.0f );
o2 = lerp( -caWidth, caWidth, i / o1 );
temp.xyz = tex2D( samplerBloomAll, texcoord.xy + float2( o2 * offsetX, o2 * offsetY )).xyz;
color.xyz += temp.xyz * huecolor.xyz;
d.xyz += huecolor.xyz;
}
color.xyz /= dot( d.xyz, 0.333333f ); // seems so-so OK
color.xyz = lerp( orig.xyz, color.xyz, CA_strength );
color.xyz = lerp( color.xyz, color.xyz - orig.xyz, use_only_ca );
return float4( color.xyz, 1.0f );
}
#endif
float4 PS_Gaussian(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
#if( !BLOOM_ENABLE_CA )
float4 bloom = tex2D( samplerBloomAll, texcoord );
#endif
#if( BLOOM_ENABLE_CA )
float4 bloom = tex2D( samplerCABloom, texcoord );
#endif
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Dither
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 0, 1, dither_strength, 1, 2.0f - ( 1.0f - BloomLimit ) );
float3 steps = smoothstep( 0.0f, 0.012f, bloom.xyz );
bloom.xyz = saturate( bloom.xyz + dnoise.xyz * steps.xyz );
#if( BLOOM_ENABLE_CA == 0 )
if( enableBKelvin )
{
float3 K = KelvinToRGB( BKelvin );
float3 bLum = RGBToHSL( bloom.xyz );
float3 retHSV = RGBToHSL( bloom.xyz * K.xyz );
bloom.xyz = HSLToRGB( float3( retHSV.xy, bLum.z ));
}
#endif
// Vibrance
bloom.xyz = vib( bloom.xyz, BloomSaturation );
float3 bcolor = screen( color.xyz, bloom.xyz );
color.xyz = lerp( color.xyz, bcolor.xyz, BloomMix );
color.xyz = debugBloom ? bloom.xyz : color.xyz; // render only bloom to screen
return float4( color.xyz, 1.0f );
}
float PS_PrevAvgBLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float avgLuma = tex2D( samplerBAvgLuma, float2( 0.5f, 0.5f )).x;
return avgLuma;
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_02_Bloom
< ui_tooltip = "Bloom\n\n"
"Bloom is an effect that causes diffraction of light around bright reflective or emittive sources\n\n"
"Preprocessor Settings\n\n"
"BLOOM_ENABLE_CA: Enables a chromatic aberration effect on bloom\n\n"
"BLOOM_QUALITY_0_TO_2: Sets the quality, 0 is full (and heavy!), 2 is low and very fast,\n"
"1 is high quality and best trade off between quality and performance\n\n"
"BLOOM_LOOPCOUNT: Limit to the amount of loops of the Width effect. Wider blooms may need higher\n"
"values (eg. max width is 300, this value should be 300)\n\n"
"BLOOM_LIMITER: Limiter to the bloom. Wider blooms may need lower values or the bloom starts to look\n"
"rectangular (eg. 0.0001 (default) is good to about width 100, after that start to decrease this value)\n\n"
"BLOOM_USE_FOCUS_BLOOM: Enables another pass to add a narrow bloom on top of the wide bloom";>
{
pass BLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_WriteBLuma;
RenderTarget = texBLuma;
}
pass AvgBLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_AvgBLuma;
RenderTarget = texBAvgLuma;
}
pass PrepLod
{
VertexShader = PostProcessVS;
PixelShader = PS_PrepLOD;
RenderTarget = texPrepLOD;
}
pass BloomIn
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomIn;
RenderTarget = texBloomIn;
}
#if( BLOOM_USE_FOCUS_BLOOM )
pass GaussianH
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianH;
RenderTarget0 = texBloomH;
RenderTarget1 = texBloomHF;
}
#endif
#if( !BLOOM_USE_FOCUS_BLOOM )
pass GaussianH
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianH;
RenderTarget = texBloomH;
}
#endif
pass GaussianV
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianV;
RenderTarget = texBloom;
}
#if( BLOOM_USE_FOCUS_BLOOM )
pass GaussianVF
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianVF;
RenderTarget = texBloomF;
}
#endif
pass Combine
{
VertexShader = PostProcessVS;
PixelShader = PS_Combine;
RenderTarget = texBloomAll;
}
#if( BLOOM_ENABLE_CA == 0 )
pass GaussianBlur
{
VertexShader = PostProcessVS;
PixelShader = PS_Gaussian;
}
#endif
#if( BLOOM_ENABLE_CA == 1 )
pass AddCA
{
VertexShader = PostProcessVS;
PixelShader = PS_CA;
RenderTarget = texCABloom;
}
pass GaussianBlur
{
VertexShader = PostProcessVS;
PixelShader = PS_Gaussian;
}
#endif
pass PreviousBLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_PrevAvgBLuma;
RenderTarget = texBPrevAvgLuma;
}
}
}

View File

@ -0,0 +1,15 @@
// Easy LUT config
// Name which will display in the UI. Should be without spaces
#define PD80_Technique_Name prod80_02_Bonus_LUT_pack
// Texture name which contains the LUT(s) and the Tile Sizes, Amounts, etc.
#define PD80_LUT_File_Name "pd80_example-lut.png"
#define PD80_Tile_SizeXY 64
#define PD80_Tile_Amount 64
#define PD80_LUT_Amount 50
// Drop down menu which gives the names of the LUTs, each menu option should be followed by \0
#define PD80_Drop_Down_Menu "PD80 Cinematic 01\0PD80 Cinematic 02\0PD80 Cinematic 03\0PD80 Cinematic 04\0PD80 Cinematic 05\0PD80 Cinematic 06\0PD80 Cinematic 07\0PD80 Cinematic 08\0PD80 Cinematic 09\0PD80 Cinematic 10\0PD80 Cinematic 11\0PD80 Cinematic 12\0PD80 Cinematic 13\0PD80 Cinematic 14\0PD80 Cinematic 15\0PD80 Cinematic 16\0PD80 Cinematic 17\0PD80 Cinematic 18\0PD80 Cinematic 19\0PD80 Cinematic 20\0PD80 Cinematic 21\0PD80 Cinematic 22\0PD80 Cinematic 23\0PD80 Cinematic 24\0PD80 Cinematic 25\0PD80 Cinematic 26\0PD80 Cinematic 27\0PD80 Cinematic 28\0PD80 Cinematic 29\0PD80 Cinematic 30\0PD80 Cinematic 31\0PD80 Cinematic 32\0PD80 Cinematic 33\0PD80 Cinematic 34\0PD80 Cinematic 35\0PD80 Cinematic 36\0PD80 Cinematic 37\0PD80 Cinematic 38\0PD80 Cinematic 39\0PD80 Cinematic 40\0PD80 Cinematic 41\0PD80 Cinematic 42\0PD80 Cinematic 43\0PD80 Cinematic 44\0PD80 Cinematic 45\0PD80 Cinematic 46\0PD80 Cinematic 47\0PD80 Cinematic 48\0PD80 Cinematic 49\0PD80 Cinematic 50\0"
// Final pass to the shader
#include "PD80_LUT_v2.fxh"

View File

@ -0,0 +1,15 @@
// Easy LUT config
// Name which will display in the UI. Should be without spaces
#define PD80_Technique_Name prod80_02_Cinetools_LUT
// Texture name which contains the LUT(s) and the Tile Sizes, Amounts, etc.
#define PD80_LUT_File_Name "pd80_cinelut.png"
#define PD80_Tile_SizeXY 64
#define PD80_Tile_Amount 64
#define PD80_LUT_Amount 31
// Drop down menu which gives the names of the LUTs, each menu option should be followed by \0
#define PD80_Drop_Down_Menu "FilmicGold\0FilmicGold_Contrast\0FilmicBlue\0FilmicBlue_Contrast\0TealOrangeNeutral\0TealOrangeYCSplit\0TealOrangeWarmMatte\0CinematicColors\0UltraWarmMatte\0UltraMatte\0BW-Max\0BW-MaxSepia\0BW-MatteLooks\0AlternativeProcess-01\0AlternativeProcess-02\0SuperGreens\0ColorHarmony-01\0ColorHarmony-02\0GoingBrownAgain\0Cyanolyte\0DustyOldMan\0DustyOldMatte\0DrankAllTheRedWine\0OldEleganceClean\0OldEleganceMatte\0HundredDollarStripper\0HundredDollarStripperMatte\0ClassicTealOrange\0ClassicTealOrangeMatte\0ClassicTealOrangeYHL\0ClassicTealOrangeYHLMatte\0"
// Final pass to the shader
#include "PD80_LUT_v2.fxh"

View File

@ -0,0 +1,118 @@
/*
Description : PD80 02 LUT Creator for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
This shader overlays the screen with a 512x512 high quality LUT.
One can run effects on this LUT using Reshade and export the results in a PNG
screenshot. You can take this screenshot into your favorite image editor and
make it into a 4096x64 LUT texture that can be read by Reshade's LUT shaders.
This way you can safe performance by using a texture to apply your favorite
effects instead of Reshade's color manipulation shaders.
To use:
1. Start game with Reshade
2. Make sure PD80_03_LUT_Creator.fx is the first shader in your effect chain and any effects that shouldn't be enabled are disabled; Bloom, DoF, Noise/Grain, Dither, MXAO, SMAA, SSR, ...
3. Adjust the game coloring, contrasts, brightness, gamma, etc. to taste using whatever Reshade effects you please. Once happy make a screenshot in .png format
4. Exit game and load screenshot in Photoshop or your preferred image editing program
5. Carefully cut and paste the individual rows into a 4096x64 size image
6. Save the new image as a .png
7. Back in the game open whatever LUT shader you have available (f.e. PD80_02_MultiLUT_2.0.fx) and load your new LUT file name with the correct parameters (Tile size 64, Number of tiles 64, Number of LUTs 1)
8. Disable the effects used to make the LUT (or effects are applied twice)
Profit.
*/
// "HALD_64.png"
// "pd80_neutral-lut.png"
#include "ReShade.fxh"
#ifndef PD80_LC_TEXTURE_NAME
#define PD80_LC_TEXTURE_NAME "pd80_neutral-lut.png"
#endif
#ifndef PD80_LC_TEXTURE_WIDTH
#define PD80_LC_TEXTURE_WIDTH 512.0
#endif
#ifndef PD80_LC_TEXTURE_HEIGHT
#define PD80_LC_TEXTURE_HEIGHT 512.0
#endif
namespace pd80_lutoverlay
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texPicture < source = PD80_LC_TEXTURE_NAME; > { Width = PD80_LC_TEXTURE_WIDTH; Height = PD80_LC_TEXTURE_HEIGHT; Format = RGBA8; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerPicture {
Texture = texPicture;
AddressU = CLAMP;
AddressV = CLAMP;
AddressW = CLAMP;
};
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_OverlayLUT(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float2 coords = float2( BUFFER_WIDTH, BUFFER_HEIGHT ) / float2( PD80_LC_TEXTURE_WIDTH, PD80_LC_TEXTURE_HEIGHT );
coords.xy *= texcoord.xy;
float3 lut = tex2D( samplerPicture, coords ).xyz;
float3 color = tex2D( ReShade::BackBuffer, texcoord ).xyz;
float2 cutoff = float2( BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT ) * float2( PD80_LC_TEXTURE_WIDTH, PD80_LC_TEXTURE_HEIGHT );
color = ( texcoord.y > cutoff.y || texcoord.x > cutoff.x ) ? color : lut;
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_02_LUT_Creator
< ui_tooltip = "This shader overlays the screen with a 512x512 high quality LUT.\n"
"One can run effects on this LUT using Reshade and export the results in a PNG\n"
"screenshot. You can take this screenshot into your favorite image editor and\n"
"make it into a 4096x64 LUT texture that can be read by Reshade's LUT shaders.\n"
"This way you can safe performance by using a texture to apply your favorite\n"
"effects instead of Reshade's color manipulation shaders.";>
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_OverlayLUT;
}
}
}

View File

@ -0,0 +1,230 @@
/*
Description : PD80 03 Color Space Curves for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional Credits
http://technorgb.blogspot.com/2018/02/hyperbola-tone-mapping.html
LAB Conversion adopted from
http://www.brucelindbloom.com/
For the curves code:
Copyright (c) 2018 ishiyama, MIT License
Please see https://www.shadertoy.com/view/4tjcD1
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace pd80_cscurves
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform int color_space <
ui_type = "combo";
ui_category = "Global";
ui_label = "Color Space";
ui_tooltip = "Color Space";
ui_items = "RGB-W\0L* a* b*\0HSL\0HSV\0";
> = 1;
// Greys
uniform float pos0_shoulder_grey <
ui_type = "slider";
ui_label = "Shoulder Position X";
ui_tooltip = "Shoulder Position X";
ui_category = "Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.8;
uniform float pos1_shoulder_grey <
ui_type = "slider";
ui_label = "Shoulder Position Y";
ui_tooltip = "Shoulder Position Y";
ui_category = "Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.8;
uniform float pos0_toe_grey <
ui_type = "slider";
ui_label = "Toe Position X";
ui_tooltip = "Toe Position X";
ui_category = "Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.2;
uniform float pos1_toe_grey <
ui_type = "slider";
ui_label = "Toe Position Y";
ui_tooltip = "Toe Position Y";
ui_category = "Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.2;
// Saturation
uniform float colorsat <
ui_type = "slider";
ui_category = "Color Control";
ui_label = "Saturation";
ui_tooltip = "Saturation";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// STRUCTURES /////////////////////////////////////////////////////////////////
struct TonemapParams
{
float3 mToe;
float2 mMid;
float3 mShoulder;
float2 mBx;
};
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float3 Tonemap(const TonemapParams tc, float3 x)
{
float3 toe = - tc.mToe.x / (x + tc.mToe.y) + tc.mToe.z;
float3 mid = tc.mMid.x * x + tc.mMid.y;
float3 shoulder = - tc.mShoulder.x / (x + tc.mShoulder.y) + tc.mShoulder.z;
float3 result = ( x >= tc.mBx.x ) ? mid : toe;
result = ( x >= tc.mBx.y ) ? shoulder : result;
return result;
}
float4 setBoundaries( float tx, float ty, float sx, float sy )
{
if( tx > sx )
tx = sx;
if( ty > sy )
ty = sy;
return float4( tx, ty, sx, sy );
}
void PrepareTonemapParams(float2 p1, float2 p2, float2 p3, out TonemapParams tc)
{
float denom = p2.x - p1.x;
denom = abs(denom) > 1e-5 ? denom : 1e-5;
float slope = (p2.y - p1.y) / denom;
{
tc.mMid.x = slope;
tc.mMid.y = p1.y - slope * p1.x;
}
{
float denom = p1.y - slope * p1.x;
denom = abs(denom) > 1e-5 ? denom : 1e-5;
tc.mToe.x = slope * p1.x * p1.x * p1.y * p1.y / (denom * denom);
tc.mToe.y = slope * p1.x * p1.x / denom;
tc.mToe.z = p1.y * p1.y / denom;
}
{
float denom = slope * (p2.x - p3.x) - p2.y + p3.y;
denom = abs(denom) > 1e-5 ? denom : 1e-5;
tc.mShoulder.x = slope * pow(p2.x - p3.x, 2.0) * pow(p2.y - p3.y, 2.0) / (denom * denom);
tc.mShoulder.y = (slope * p2.x * (p3.x - p2.x) + p3.x * (p2.y - p3.y) ) / denom;
tc.mShoulder.z = (-p2.y * p2.y + p3.y * (slope * (p2.x - p3.x) + p2.y) ) / denom;
}
tc.mBx = float2(p1.x, p2.x);
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_CSCurves(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 1, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.xyz );
// Prepare curves
float4 grey = setBoundaries( pos0_toe_grey, pos1_toe_grey, pos0_shoulder_grey, pos1_shoulder_grey );
TonemapParams tc;
PrepareTonemapParams( grey.xy, grey.zw, float2( 1.0f, 1.0f ), tc );
// RGBW
float rgb_luma = min( min( color.x, color.y ), color.z );
float temp_luma = rgb_luma;
float3 rgb_chroma = color.xyz - rgb_luma;
rgb_luma = Tonemap( tc, rgb_luma.xxx ).x;
rgb_chroma *= ( colorsat + 1.0f );
// LAB
float3 lab_color = pd80_srgb_to_lab( color.xyz );
lab_color.x = Tonemap( tc, lab_color.xxx ).x;
lab_color.yz *= ( colorsat + 1.0f );
// HSL
float3 hsl_color = RGBToHSL( color.xyz );
hsl_color.z = Tonemap( tc, hsl_color.zzz ).z;
hsl_color.y *= ( colorsat + 1.0f );
// HSV
float3 hsv_color = RGBToHSV( color.xyz );
hsv_color.z = Tonemap( tc, hsv_color.zzz ).z;
hsv_color.y *= ( colorsat + 1.0f );
switch( color_space )
{
case 0: { color.xyz = saturate( rgb_chroma.xyz + rgb_luma ); } break;
case 1: { color.xyz = pd80_lab_to_srgb( lab_color.xyz ); } break;
case 2: { color.xyz = HSLToRGB( saturate( hsl_color.xyz )); } break;
case 3: { color.xyz = HSVToRGB( saturate( hsv_color.xyz )); } break;
}
color.xyz = saturate( color.xyz + dnoise.wxy );
return float4(color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_03_Color_Space_Curves
{
pass prod80_CCpass0
{
VertexShader = PostProcessVS;
PixelShader = PS_CSCurves;
}
}
}

View File

@ -0,0 +1,570 @@
/*
Description : PD80 03 Contrast Curve for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional Credits
http://technorgb.blogspot.com/2018/02/hyperbola-tone-mapping.html
For the curves code:
Copyright (c) 2018 ishiyama, MIT License
Please see https://www.shadertoy.com/view/4tjcD1
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
namespace pd80_curvedlevels
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
#ifndef CURVEDCONTRASTS_ENABLE_RGB
#define CURVEDCONTRASTS_ENABLE_RGB 0
#endif
#ifndef CURVEDCONTRASTS_VISUALIZE
#define CURVEDCONTRASTS_VISUALIZE 0 // 0 = disabled, 1 = enabled
#endif
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
// Greys
uniform float black_in_grey <
ui_type = "slider";
ui_label = "Grey: Black Point";
ui_tooltip = "Grey: Black Point";
ui_category = "Grey: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_in_grey <
ui_type = "slider";
ui_label = "Grey: White Point";
ui_tooltip = "Grey: White Point";
ui_category = "Grey: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
uniform float pos0_shoulder_grey <
ui_type = "slider";
ui_label = "Grey: Shoulder Position X";
ui_tooltip = "Grey: Shoulder Position X";
ui_category = "Grey: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos1_shoulder_grey <
ui_type = "slider";
ui_label = "Grey: Shoulder Position Y";
ui_tooltip = "Grey: Shoulder Position Y";
ui_category = "Grey: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos0_toe_grey <
ui_type = "slider";
ui_label = "Grey: Toe Position X";
ui_tooltip = "Grey: Toe Position X";
ui_category = "Grey: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float pos1_toe_grey <
ui_type = "slider";
ui_label = "Grey: Toe Position Y";
ui_tooltip = "Grey: Toe Position Y";
ui_category = "Grey: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float black_out_grey <
ui_type = "slider";
ui_label = "Grey: Black Point Offset";
ui_tooltip = "Grey: Black Point Offset";
ui_category = "Grey: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_out_grey <
ui_type = "slider";
ui_label = "Grey: White Point Offset";
ui_tooltip = "Grey: White Point Offset";
ui_category = "Grey: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
#if( CURVEDCONTRASTS_ENABLE_RGB )
// Reds
uniform float black_in_red <
ui_type = "slider";
ui_label = "Red: Black Point";
ui_tooltip = "Red: Black Point";
ui_category = "Red: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_in_red <
ui_type = "slider";
ui_label = "Red: White Point";
ui_tooltip = "Red: White Point";
ui_category = "Red: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
uniform float pos0_shoulder_red <
ui_type = "slider";
ui_label = "Red: Shoulder Position X";
ui_tooltip = "Red: Shoulder Position X";
ui_category = "Red: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos1_shoulder_red <
ui_type = "slider";
ui_label = "Red: Shoulder Position Y";
ui_tooltip = "Red: Shoulder Position Y";
ui_category = "Red: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos0_toe_red <
ui_type = "slider";
ui_label = "Red: Toe Position X";
ui_tooltip = "Red: Toe Position X";
ui_category = "Red: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float pos1_toe_red <
ui_type = "slider";
ui_label = "Red: Toe Position Y";
ui_tooltip = "Red: Toe Position Y";
ui_category = "Red: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float black_out_red <
ui_type = "slider";
ui_label = "Red: Black Point Offset";
ui_tooltip = "Red: Black Point Offset";
ui_category = "Red: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_out_red <
ui_type = "slider";
ui_label = "Red: White Point Offset";
ui_tooltip = "Red: White Point Offset";
ui_category = "Red: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
// Greens
uniform float black_in_green <
ui_type = "slider";
ui_label = "Green: Black Point";
ui_tooltip = "Green: Black Point";
ui_category = "Green: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_in_green <
ui_type = "slider";
ui_label = "Green: White Point";
ui_tooltip = "Green: White Point";
ui_category = "Green: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
uniform float pos0_shoulder_green <
ui_type = "slider";
ui_label = "Green: Shoulder Position X";
ui_tooltip = "Green: Shoulder Position X";
ui_category = "Green: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos1_shoulder_green <
ui_type = "slider";
ui_label = "Green: Shoulder Position Y";
ui_tooltip = "Green: Shoulder Position Y";
ui_category = "Green: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos0_toe_green <
ui_type = "slider";
ui_label = "Green: Toe Position X";
ui_tooltip = "Green: Toe Position X";
ui_category = "Green: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float pos1_toe_green <
ui_type = "slider";
ui_label = "Green: Toe Position Y";
ui_tooltip = "Green: Toe Position Y";
ui_category = "Green: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float black_out_green <
ui_type = "slider";
ui_label = "Green: Black Point Offset";
ui_tooltip = "Green: Black Point Offset";
ui_category = "Green: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_out_green <
ui_type = "slider";
ui_label = "Green: White Point Offset";
ui_tooltip = "Green: White Point Offset";
ui_category = "Green: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
// Blues
uniform float black_in_blue <
ui_type = "slider";
ui_label = "Blue: Black Point";
ui_tooltip = "Blue: Black Point";
ui_category = "Blue: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_in_blue <
ui_type = "slider";
ui_label = "Blue: White Point";
ui_tooltip = "Blue: White Point";
ui_category = "Blue: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
uniform float pos0_shoulder_blue <
ui_type = "slider";
ui_label = "Blue: Shoulder Position X";
ui_tooltip = "Blue: Shoulder Position X";
ui_category = "Blue: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos1_shoulder_blue <
ui_type = "slider";
ui_label = "Blue: Shoulder Position Y";
ui_tooltip = "Blue: Shoulder Position Y";
ui_category = "Blue: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.75;
uniform float pos0_toe_blue <
ui_type = "slider";
ui_label = "Blue: Toe Position X";
ui_tooltip = "Blue: Toe Position X";
ui_category = "Blue: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float pos1_toe_blue <
ui_type = "slider";
ui_label = "Blue: Toe Position Y";
ui_tooltip = "Blue: Toe Position Y";
ui_category = "Blue: Contrast Curves";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.25;
uniform float black_out_blue <
ui_type = "slider";
ui_label = "Blue: Black Point Offset";
ui_tooltip = "Blue: Black Point Offset";
ui_category = "Blue: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 0.0;
uniform float white_out_blue <
ui_type = "slider";
ui_label = "Blue: White Point Offset";
ui_tooltip = "Blue: White Point Offset";
ui_category = "Blue: Contrast Curves";
ui_min = 0;
ui_max = 255;
ui_step = 1;
> = 255.0;
#endif
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// STRUCTURES /////////////////////////////////////////////////////////////////
struct TonemapParams
{
float3 mToe;
float2 mMid;
float3 mShoulder;
float2 mBx;
};
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float3 Tonemap(const TonemapParams tc, float3 x)
{
float3 toe = - tc.mToe.x / (x + tc.mToe.y) + tc.mToe.z;
float3 mid = tc.mMid.x * x + tc.mMid.y;
float3 shoulder = - tc.mShoulder.x / (x + tc.mShoulder.y) + tc.mShoulder.z;
float3 result = ( x >= tc.mBx.x ) ? mid : toe;
result = ( x >= tc.mBx.y ) ? shoulder : result;
return result;
}
float blackwhiteIN( float c, float b, float w )
{
return saturate( c - b )/max( w - b, 0.000001f );
}
float blackwhiteOUT( float c, float b, float w )
{
return c * saturate( w - b ) + b;
}
float3 blackwhiteIN( float3 c, float b, float w )
{
return saturate( c.xyz - b )/max( w - b, 0.000001f );
}
float3 blackwhiteOUT( float3 c, float b, float w )
{
return c.xyz * saturate( w - b ) + b;
}
float4 setBoundaries( float tx, float ty, float sx, float sy )
{
if( tx > sx )
tx = sx;
if( ty > sy )
ty = sy;
return float4( tx, ty, sx, sy );
}
void PrepareTonemapParams(float2 p1, float2 p2, float2 p3, out TonemapParams tc)
{
float denom = p2.x - p1.x;
denom = abs(denom) > 1e-5 ? denom : 1e-5;
float slope = (p2.y - p1.y) / denom;
{
tc.mMid.x = slope;
tc.mMid.y = p1.y - slope * p1.x;
}
{
float denom = p1.y - slope * p1.x;
denom = abs(denom) > 1e-5 ? denom : 1e-5;
tc.mToe.x = slope * p1.x * p1.x * p1.y * p1.y / (denom * denom);
tc.mToe.y = slope * p1.x * p1.x / denom;
tc.mToe.z = p1.y * p1.y / denom;
}
{
float denom = slope * (p2.x - p3.x) - p2.y + p3.y;
denom = abs(denom) > 1e-5 ? denom : 1e-5;
tc.mShoulder.x = slope * pow(p2.x - p3.x, 2.0) * pow(p2.y - p3.y, 2.0) / (denom * denom);
tc.mShoulder.y = (slope * p2.x * (p3.x - p2.x) + p3.x * (p2.y - p3.y) ) / denom;
tc.mShoulder.z = (-p2.y * p2.y + p3.y * (slope * (p2.x - p3.x) + p2.y) ) / denom;
}
tc.mBx = float2(p1.x, p2.x);
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_CurvedLevels(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float2 coords = float2(( texcoord.x - 0.75f ) * 4.0f, ( 1.0f - texcoord.y ) * 4.0f ); // For vizualization
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 1, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.yzx );
#if( CURVEDCONTRASTS_VISUALIZE == 1 )
int def_bi = 0;
int def_wi = 255;
float def_toe0 = 0.25f;
float def_toe1 = 0.25f;
float def_sho0 = 0.75f;
float def_sho1 = 0.75f;
int def_bo = 0;
int def_wo = 255;
float3 showcurve = 0.0f;
#endif
TonemapParams tc;
// Grey apply black/white points and curves
float bigr = saturate( black_in_grey/255.0f + dnoise.w );
float wigr = saturate( white_in_grey/255.0f + dnoise.w );
float bogr = saturate( black_out_grey/255.0f + dnoise.w );
float wogr = saturate( white_out_grey/255.0f + dnoise.w );
float4 grey = setBoundaries( pos0_toe_grey, pos1_toe_grey, pos0_shoulder_grey, pos1_shoulder_grey );
PrepareTonemapParams( grey.xy, grey.zw, float2( 1.0f, 1.0f ), tc );
color.xyz = blackwhiteIN( color.xyz, bigr, wigr );
color.xyz = Tonemap( tc, color.xyz );
color.xyz = blackwhiteOUT( color.xyz, bogr, wogr );
// Visual
#if( CURVEDCONTRASTS_VISUALIZE )
// Draw a bunch of lines
float4 bandwidth = float4( 0.002f, 0.002f, 0.0002f, 0.0002f );
bandwidth.y *= ( BUFFER_WIDTH * BUFFER_RCP_HEIGHT );
bandwidth.w *= ( BUFFER_WIDTH * BUFFER_RCP_HEIGHT );
if( texcoord.x > 0.75 - bandwidth.x && texcoord.x < 0.75 && 1.0f - texcoord.y < 0.25 )
color.xyz = float3( 0.7f, 0.7f, 0.7f );
if( 1.0f - texcoord.y > 0.25 && 1.0f - texcoord.y < 0.25 + bandwidth.y && texcoord.x > 0.75 - bandwidth.x )
color.xyz = float3( 0.7f, 0.7f, 0.7f );
if( texcoord.x > 0.875 - bandwidth.z && texcoord.x < 0.875 + bandwidth.z && 1.0f - texcoord.y < 0.25 )
color.xyz = float3( 1.4f, 1.4f, 1.4f );
if( 1.0f - texcoord.y > 0.125f - bandwidth.w && 1.0f - texcoord.y < 0.125 + bandwidth.w && texcoord.x > 0.75 )
color.xyz = float3( 1.4f, 1.4f, 1.4f );
if( texcoord.x > 0.75 && texcoord.y > 0.75 )
{
color.xyz *= 0.5f;
color.xyz = lerp( float3( 0.7f, 0.7f, 0.7f ), color.xyz, smoothstep( 0.0f, 10.0f * BUFFER_RCP_HEIGHT, abs( coords.y - coords.x )));
showcurve.xyz = blackwhiteIN( coords.xxx, black_in_grey/255.0f, white_in_grey/255.0f );
showcurve.xyz = Tonemap( tc, showcurve.xyz );
showcurve.xyz = blackwhiteOUT( showcurve.xyz, black_out_grey/255.0f, white_out_grey/255.0f );
color.xyz = lerp( float3( 1.0f, 1.0f, 1.0f ), color.xyz, smoothstep( 0.0f, 20.0f * BUFFER_RCP_HEIGHT, abs( coords.y - showcurve.x )));
}
#endif
#if( CURVEDCONTRASTS_ENABLE_RGB )
// Red
float bir = saturate( black_in_red/255.0f + dnoise.x );
float wir = saturate( white_in_red/255.0f + dnoise.x );
float bor = saturate( black_out_red/255.0f + dnoise.x );
float wor = saturate( white_out_red/255.0f + dnoise.x );
float4 red = setBoundaries( pos0_toe_red, pos1_toe_red, pos0_shoulder_red, pos1_shoulder_red );
PrepareTonemapParams( red.xy, red.zw, float2( 1.0f, 1.0f ), tc );
color.x = blackwhiteIN( color.x, bir, wir );
color.x = Tonemap( tc, color.xxx ).x;
color.x = blackwhiteOUT( color.x, bor, wor );
#if( CURVEDCONTRASTS_VISUALIZE )
if( any( float4( def_toe0 - pos0_toe_red, def_toe1 - pos1_toe_red, def_sho0 - pos0_shoulder_red, def_sho1 - pos1_shoulder_red )) ||
any( int4( def_bi - black_in_red, def_wi - white_in_red, def_bo - black_out_red, def_wo - white_out_red )))
{
if( texcoord.x > 0.75 && texcoord.y > 0.75 )
{
showcurve.x = blackwhiteIN( showcurve.xxx, black_in_red/255.0f, white_in_red/255.0f ).x;
showcurve.x = Tonemap( tc, showcurve.xxx ).x;
showcurve.x = blackwhiteOUT( showcurve.xxx, black_out_red/255.0f, white_out_red/255.0f ).x;
color.xyz = lerp( float3( 1.0f, 0.0f, 0.0f ), color.xyz, smoothstep( 0.0f, 20.0f * BUFFER_RCP_HEIGHT, abs( coords.y - showcurve.x )));
}
}
#endif
// Green
float big = saturate( black_in_green/255.0f + dnoise.y );
float wig = saturate( white_in_green/255.0f + dnoise.y );
float bog = saturate( black_out_green/255.0f + dnoise.y );
float wog = saturate( white_out_green/255.0f + dnoise.y );
float4 green = setBoundaries( pos0_toe_green, pos1_toe_green, pos0_shoulder_green, pos1_shoulder_green );
PrepareTonemapParams( green.xy, green.zw, float2( 1.0f, 1.0f ), tc );
color.y = blackwhiteIN( color.y, big, wig );
color.y = Tonemap( tc, color.yyy ).y;
color.y = blackwhiteOUT( color.y, bog, wog );
#if( CURVEDCONTRASTS_VISUALIZE )
if( any( float4( def_toe0 - pos0_toe_green, def_toe1 - pos1_toe_green, def_sho0 - pos0_shoulder_green, def_sho1 - pos1_shoulder_green )) ||
any( int4( def_bi - black_in_green, def_wi - white_in_green, def_bo - black_out_green, def_wo - white_out_green )))
{
if( texcoord.x > 0.75 && texcoord.y > 0.75 )
{
showcurve.y = blackwhiteIN( showcurve.yyy, black_in_green/255.0f, white_in_green/255.0f ).y;
showcurve.y = Tonemap( tc, showcurve.yyy ).y;
showcurve.y = blackwhiteOUT( showcurve.yyy, black_out_green/255.0f, white_out_green/255.0f ).y;
color.xyz = lerp( float3( 0.0f, 1.0f, 0.0f ), color.xyz, smoothstep( 0.0f, 20.0f * BUFFER_RCP_HEIGHT, abs( coords.y - showcurve.y )));
}
}
#endif
// Blue
float bib = saturate( black_in_blue/255.0f + dnoise.z );
float wib = saturate( white_in_blue/255.0f + dnoise.z );
float bob = saturate( black_out_blue/255.0f + dnoise.z );
float wob = saturate( white_out_blue/255.0f + dnoise.z );
float4 blue = setBoundaries( pos0_toe_blue, pos1_toe_blue, pos0_shoulder_blue, pos1_shoulder_blue );
PrepareTonemapParams( blue.xy, blue.zw, float2( 1.0f, 1.0f ), tc );
color.z = blackwhiteIN( color.z, bib, wib );
color.z = Tonemap( tc, color.zzz ).z;
color.z = blackwhiteOUT( color.z, bob, wob );
#if( CURVEDCONTRASTS_VISUALIZE )
if( any( float4( def_toe0 - pos0_toe_blue, def_toe1 - pos1_toe_blue, def_sho0 - pos0_shoulder_blue, def_sho1 - pos1_shoulder_blue )) ||
any( int4( def_bi - black_in_blue, def_wi - white_in_blue, def_bo - black_out_blue, def_wo - white_out_blue )))
{
if( texcoord.x > 0.75 && texcoord.y > 0.75 )
{
showcurve.z = blackwhiteIN( showcurve.zzz, black_in_blue/255.0f, white_in_blue/255.0f ).z;
showcurve.z = Tonemap( tc, showcurve.zzz ).z;
showcurve.z = blackwhiteOUT( showcurve.zzz, black_out_blue/255.0f, white_out_blue/255.0f ).z;
color.xyz = lerp( float3( 0.0f, 0.0f, 1.0f ), color.xyz, smoothstep( 0.0f, 20.0f * BUFFER_RCP_HEIGHT, abs( coords.y - showcurve.z )));
}
}
#endif
#endif
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_03_CurvedLevels
{
pass prod80_CCpass0
{
VertexShader = PostProcessVS;
PixelShader = PS_CurvedLevels;
}
}
}

View File

@ -0,0 +1,170 @@
/*
Description : PD80 03 Filmic Adaptation for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits (exposure)
- Padraic Hennessy for the logic
https://placeholderart.wordpress.com/2014/11/21/implementing-a-physically-based-camera-manual-exposure/
- Padraic Hennessy for the logic
https://placeholderart.wordpress.com/2014/12/15/implementing-a-physically-based-camera-automatic-exposure/
- MJP and David Neubelt for the method
https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/Exposure.hlsl
License: MIT, Copyright (c) 2016 MJP
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_filmicadaptation
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float adj_shoulder <
ui_label = "Adjust Highlights";
ui_tooltip = "Adjust Highlights";
ui_category = "Tonemapping";
ui_type = "slider";
ui_min = 1.0;
ui_max = 5.0;
> = 1.0;
uniform float adj_linear <
ui_label = "Adjust Linearity";
ui_tooltip = "Adjust Linearity";
ui_category = "Tonemapping";
ui_type = "slider";
ui_min = 1.0;
ui_max = 10.0;
> = 1.0;
uniform float adj_toe <
ui_label = "Adjust Shadows";
ui_tooltip = "Adjust Shadows";
ui_category = "Tonemapping";
ui_type = "slider";
ui_min = 1.0;
ui_max = 5.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texLuma { Width = 256; Height = 256; Format = R16F; MipLevels = 9; };
texture texAvgLuma { Format = R16F; };
texture texPrevAvgLuma { Format = R16F; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerLinColor { Texture = ReShade::BackBufferTex; SRGBTexture = true; };
sampler samplerLuma { Texture = texLuma; };
sampler samplerAvgLuma { Texture = texAvgLuma; };
sampler samplerPrevAvgLuma { Texture = texPrevAvgLuma; };
//// DEFINES ////////////////////////////////////////////////////////////////////
#define LumCoeff float3(0.212656, 0.715158, 0.072186)
uniform float Frametime < source = "frametime"; >;
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, LumCoeff );
}
float3 Filmic( in float3 Fc, in float FA, in float FB, in float FC, in float FD, in float FE, in float FF, in float FWhite )
{
float3 num = (( Fc * ( FA * Fc + FC * FB ) + FD * FE ) / ( Fc * ( FA * Fc + FB ) + FD * FF )) - FE / FF;
float3 denom = (( FWhite * ( FA * FWhite + FC * FB ) + FD * FE ) / ( FWhite * ( FA * FWhite + FB ) + FD * FF )) - FE / FF;
return num / denom;
//return num / denom;
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float PS_WriteLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerLinColor, texcoord );
float luma = getLuminance( color.xyz );
luma = max( luma, 0.06f ); // give it a min value so that too dark scenes don't count too much against average
return log2( luma ); //writes to 256x256 texture
}
float PS_AvgLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float luma = tex2Dlod( samplerLuma, float4(0.5f, 0.5f, 0, 8 )).x;
luma = exp2( luma );
float prevluma = tex2D( samplerPrevAvgLuma, float2( 0.5f, 0.5f )).x;
float fps = 1000.0f / Frametime;
float delay = fps; //* 0.5f
float avgLuma = lerp( prevluma, luma, 1.0f / delay );
return avgLuma;
}
float4 PS_Tonemap(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
// Filmic operators, most fixed with no GUI
float A = 0.65f * adj_shoulder;
float B = 0.085f * adj_linear;
float C = 1.83f;
float D = 0.55f * adj_toe;
float E = 0.05f;
float F = 0.57f;
float W = 1.0f; // working in LDR space, white should be 1.0
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float luma = tex2D( samplerAvgLuma, float2( 0.5f, 0.5f )).x;
float exp = lerp( 1.0f, 8.0f, luma ); // Increase Toe when brightness goes up (increase contrast)
float toe = max( D * exp, D ); // Increase toe, effect is mild even though there's a potential 8x increase here
color.xyz = Filmic( color.xyz, A, B, C, toe, E, F, W );
return float4( color.xyz, 1.0f );
}
float PS_PrevAvgLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float avgLuma = tex2D( samplerAvgLuma, float2( 0.5f, 0.5f )).x;
return avgLuma;
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_03_FilmicTonemap
{
pass Luma
{
VertexShader = PostProcessVS;
PixelShader = PS_WriteLuma;
RenderTarget = texLuma;
}
pass AvgLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_AvgLuma;
RenderTarget = texAvgLuma;
}
pass Tonemapping
{
VertexShader = PostProcessVS;
PixelShader = PS_Tonemap;
}
pass PreviousLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_PrevAvgLuma;
RenderTarget = texPrevAvgLuma;
}
}
}

View File

@ -0,0 +1,220 @@
/*
Description : PD80 03 Levels for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
namespace pd80_levels
{
/*
Using depth texture to manipulate levels:
This feature is very dodgy, so hidden by default
It's added for people specilized in screenshots and able to understand
that using depth buffer can be odd on something like Levels
Uncomment ( remove "//" ) the line below to enable this feature
*/
#ifndef LEVELS_USE_DEPTH
#define LEVELS_USE_DEPTH 0 //0 = disable, 1 = enable
#endif
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform float3 ib <
ui_type = "color";
ui_label = "Black IN Level";
ui_tooltip = "Black IN Level";
ui_category = "Levels";
> = float3(0.0, 0.0, 0.0);
uniform float3 iw <
ui_type = "color";
ui_label = "White IN Level";
ui_tooltip = "White IN Level";
ui_category = "Levels";
> = float3(1.0, 1.0, 1.0);
uniform float3 ob <
ui_type = "color";
ui_label = "Black OUT Level";
ui_tooltip = "Black OUT Level";
ui_category = "Levels";
> = float3(0.0, 0.0, 0.0);
uniform float3 ow <
ui_type = "color";
ui_label = "White OUT Level";
ui_tooltip = "White OUT Level";
ui_category = "Levels";
> = float3(1.0, 1.0, 1.0);
uniform float ig <
ui_label = "Gamma Adjustment";
ui_tooltip = "Gamma Adjustment";
ui_category = "Levels";
ui_type = "slider";
ui_min = 0.05;
ui_max = 10.0;
> = 1.0;
#if( LEVELS_USE_DEPTH == 1 )
uniform bool display_depth <
ui_label = "Show depth texture.\nThe below adjustments only apply to white areas.\0Make sure you have your depth texture setup correctly.";
ui_tooltip = "Show depth texture";
ui_category = "Levels: Depth";
> = false;
uniform float depthStart <
ui_type = "slider";
ui_label = "Change Depth Start Plane";
ui_tooltip = "Change Depth Start Plane";
ui_category = "Levels: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.0;
uniform float depthEnd <
ui_type = "slider";
ui_label = "Change Depth End Plane";
ui_tooltip = "Change Depth End Plane";
ui_category = "Levels: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.1;
uniform float depthCurve <
ui_label = "Depth Curve Adjustment";
ui_tooltip = "Depth Curve Adjustment";
ui_category = "Levels: Depth";
ui_type = "slider";
ui_min = 0.05;
ui_max = 8.0;
> = 1.0;
uniform float3 ibd <
ui_type = "color";
ui_label = "Black IN Level Far";
ui_tooltip = "Black IN Level Far";
ui_category = "Levels: Far";
> = float3(0.0, 0.0, 0.0);
uniform float3 iwd <
ui_type = "color";
ui_label = "White IN Level Far";
ui_tooltip = "White IN Level Far";
ui_category = "Levels: Far";
> = float3(1.0, 1.0, 1.0);
uniform float3 obd <
ui_type = "color";
ui_label = "Black OUT Level Far";
ui_tooltip = "Black OUT Level Far";
ui_category = "Levels: Far";
> = float3(0.0, 0.0, 0.0);
uniform float3 owd <
ui_type = "color";
ui_label = "White OUT Level Far";
ui_tooltip = "White OUT Level Far";
ui_category = "Levels: Far";
> = float3(1.0, 1.0, 1.0);
uniform float igd <
ui_label = "Gamma Adjustment Far";
ui_tooltip = "Gamma Adjustment Far";
ui_category = "Levels: Far";
ui_type = "slider";
ui_min = 0.05;
ui_max = 10.0;
> = 1.0;
#endif
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float2 pingpong < source = "pingpong"; min = 0; max = 128; step = 1; >;
float3 levels( float3 color, float3 blackin, float3 whitein, float gamma, float3 outblack, float3 outwhite )
{
float3 ret = saturate( color.xyz - blackin.xyz ) / max( whitein.xyz - blackin.xyz, 0.000001f );
ret.xyz = pow( ret.xyz, gamma );
ret.xyz = ret.xyz * saturate( outwhite.xyz - outblack.xyz ) + outblack.xyz;
return ret;
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_Levels(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 2, enable_dither, dither_strength, 1, 0.5f );
#if( LEVELS_USE_DEPTH == 1 )
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
depth = smoothstep( depthStart, depthEnd, depth );
depth = pow( depth, depthCurve );
depth = saturate( depth + dnoise.w );
#endif
color.xyz = saturate( color.xyz + dnoise.w );
float3 dcolor = color.xyz;
color.xyz = levels( color.xyz, saturate( ib.xyz + dnoise.xyz ),
saturate( iw.xyz + dnoise.yzx ),
ig,
saturate( ob.xyz + dnoise.zxy ),
saturate( ow.xyz + dnoise.wxz ));
#if( LEVELS_USE_DEPTH == 1 )
dcolor.xyz = levels( dcolor.xyz, saturate( ibd.xyz + dnoise.xyz ),
saturate( iwd.xyz + dnoise.yzx ),
igd,
saturate( obd.xyz + dnoise.zxy ),
saturate( owd.xyz + dnoise.wxz ));
color.xyz = lerp( color.xyz, dcolor.xyz, depth );
color.xyz = lerp( color.xyz, depth.xxx, display_depth );
#endif
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_03_Levels
{
pass DoLevels
{
VertexShader = PostProcessVS;
PixelShader = PS_Levels;
}
}
}

View File

@ -0,0 +1,412 @@
/*
Description : PD80 03 Shadows Midtones Highlights for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Blend_Modes.fxh"
#include "PD80_00_Base_Effects.fxh"
namespace pd80_SMH
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int luma_mode < __UNIFORM_COMBO_INT1
ui_label = "Luma Mode";
ui_tooltip = "Luma Mode";
ui_category = "Global";
ui_items = "Use Average\0Use Perceived Luma\0Use Max Value\0";
> = 2;
uniform int separation_mode < __UNIFORM_COMBO_INT1
ui_label = "Luma Separation Mode";
ui_tooltip = "Luma Separation Mode";
ui_category = "Global";
ui_items = "Harsh Separation\0Smooth Separation\0";
> = 0;
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 2.0;
uniform float exposure_s <
ui_label = "Exposure";
ui_tooltip = "Shadow Exposure";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = -4.0;
ui_max = 4.0;
> = 0.0;
uniform float contrast_s <
ui_label = "Contrast";
ui_tooltip = "Shadow Contrast";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float brightness_s <
ui_label = "Brightness";
ui_tooltip = "Shadow Brightness";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float3 blendcolor_s <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Shadow Color";
ui_category = "Shadow Adjustments";
> = float3( 0.0, 0.365, 1.0 );
uniform int blendmode_s < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Shadow Blendmode";
ui_category = "Shadow Adjustments";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 0;
uniform float opacity_s <
ui_label = "Opacity";
ui_tooltip = "Shadow Opacity";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float tint_s <
ui_label = "Tint";
ui_tooltip = "Shadow Tint";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float saturation_s <
ui_label = "Saturation";
ui_tooltip = "Shadow Saturation";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float vibrance_s <
ui_label = "Vibrance";
ui_tooltip = "Shadow Vibrance";
ui_category = "Shadow Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float exposure_m <
ui_label = "Exposure";
ui_tooltip = "Midtone Exposure";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = -4.0;
ui_max = 4.0;
> = 0.0;
uniform float contrast_m <
ui_label = "Contrast";
ui_tooltip = "Midtone Contrast";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float brightness_m <
ui_label = "Brightness";
ui_tooltip = "Midtone Brightness";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float3 blendcolor_m <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Midtone Color";
ui_category = "Midtone Adjustments";
> = float3( 0.98, 0.588, 0.0 );
uniform int blendmode_m < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Midtone Blendmode";
ui_category = "Midtone Adjustments";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 0;
uniform float opacity_m <
ui_label = "Opacity";
ui_tooltip = "Midtone Opacity";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float tint_m <
ui_label = "Tint";
ui_tooltip = "Midtone Tint";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float saturation_m <
ui_label = "Saturation";
ui_tooltip = "Midtone Saturation";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float vibrance_m <
ui_label = "Vibrance";
ui_tooltip = "Midtone Vibrance";
ui_category = "Midtone Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float exposure_h <
ui_label = "Exposure";
ui_tooltip = "Highlight Exposure";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = -4.0;
ui_max = 4.0;
> = 0.0;
uniform float contrast_h <
ui_label = "Contrast";
ui_tooltip = "Highlight Contrast";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float brightness_h <
ui_label = "Brightness";
ui_tooltip = "Highlight Brightness";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float3 blendcolor_h <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Highlight Color";
ui_category = "Highlight Adjustments";
> = float3( 1.0, 1.0, 1.0 );
uniform int blendmode_h < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Highlight Blendmode";
ui_category = "Highlight Adjustments";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 0;
uniform float opacity_h <
ui_label = "Opacity";
ui_tooltip = "Highlight Opacity";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float tint_h <
ui_label = "Tint";
ui_tooltip = "Highlight Tint";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float saturation_h <
ui_label = "Saturation";
ui_tooltip = "Highlight Saturation";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float vibrance_h <
ui_label = "Vibrance";
ui_tooltip = "Highlight Vibrance";
ui_category = "Highlight Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float2 pingpong < source = "pingpong"; min = 0; max = 128; step = 1; >;
float getLuminance( in float3 x )
{
return dot( x, float3( 0.212656, 0.715158, 0.072186 ));
}
float curve( float x )
{
return x * x * x * ( x * ( x * 6.0f - 15.0f ) + 10.0f );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_SMH(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
color.xyz = saturate( color.xyz );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 3, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.xyz );
float pLuma = 0.0f;
switch( luma_mode )
{
case 0: // Use average
{
pLuma = dot( color.xyz, float3( 0.333333f, 0.333334f, 0.333333f ));
}
break;
case 1: // Use perceived luma
{
pLuma = getLuminance( color.xyz );
}
break;
case 2: // Use max
{
pLuma = max( max( color.x, color.y ), color.z );
}
break;
}
float weight_s; float weight_h; float weight_m;
switch( separation_mode )
{
/*
Clear cutoff between shadows and highlights
Maximizes precision at the loss of harsher transitions between contrasts
Curves look like:
Shadows Highlights Midtones
‾‾‾—_ _—‾‾‾ _——‾‾‾——_
‾‾——__________ __________——‾‾ ___—‾ ‾—___
0.0.....0.5.....1.0 0.0.....0.5.....1.0 0.0.....0.5.....1.0
*/
case 0:
{
weight_s = curve( max( 1.0f - pLuma * 2.0f, 0.0f ));
weight_h = curve( max(( pLuma - 0.5f ) * 2.0f, 0.0f ));
weight_m = saturate( 1.0f - weight_s - weight_h );
} break;
/*
Higher degree of blending between individual curves
F.e. shadows will still have a minimal weight all the way into highlight territory
Ensures smoother transition areas between contrasts
Curves look like:
Shadows Highlights Midtones
‾‾‾—_ _—‾‾‾ __---__
‾‾———————_____ _____———————‾‾ ___-‾‾ ‾‾-___
0.0.....0.5.....1.0 0.0.....0.5.....1.0 0.0.....0.5.....1.0
*/
case 1:
{
weight_s = pow( 1.0f - pLuma, 4.0f );
weight_h = pow( pLuma, 4.0f );
weight_m = saturate( 1.0f - weight_s - weight_h );
} break;
}
float3 cold = float3( 0.0f, 0.365f, 1.0f ); //LBB
float3 warm = float3( 0.98f, 0.588f, 0.0f ); //LBA
// Shadows
color.xyz = exposure( color.xyz, exposure_s * weight_s );
color.xyz = con( color.xyz, contrast_s * weight_s );
color.xyz = bri( color.xyz, brightness_s * weight_s );
color.xyz = blendmode( color.xyz, blendcolor_s.xyz, blendmode_s, opacity_s * weight_s );
if( tint_s < 0.0f )
color.xyz = lerp( color.xyz, softlight( color.xyz, cold.xyz ), abs( tint_s * weight_s ));
else
color.xyz = lerp( color.xyz, softlight( color.xyz, warm.xyz ), tint_s * weight_s );
color.xyz = sat( color.xyz, saturation_s * weight_s );
color.xyz = vib( color.xyz, vibrance_s * weight_s );
// Midtones
color.xyz = exposure( color.xyz, exposure_m * weight_m );
color.xyz = con( color.xyz, contrast_m * weight_m );
color.xyz = bri( color.xyz, brightness_m * weight_m );
color.xyz = blendmode( color.xyz, blendcolor_m.xyz, blendmode_m, opacity_m * weight_m );
if( tint_m < 0.0f )
color.xyz = lerp( color.xyz, softlight( color.xyz, cold.xyz ), abs( tint_m * weight_m ));
else
color.xyz = lerp( color.xyz, softlight( color.xyz, warm.xyz ), tint_m * weight_m );
color.xyz = sat( color.xyz, saturation_m * weight_m );
color.xyz = vib( color.xyz, vibrance_m * weight_m );
// Highlights
color.xyz = exposure( color.xyz, exposure_h * weight_h );
color.xyz = con( color.xyz, contrast_h * weight_h );
color.xyz = bri( color.xyz, brightness_h * weight_h );
color.xyz = blendmode( color.xyz, blendcolor_h.xyz, blendmode_h, opacity_h * weight_h );
if( tint_h < 0.0f )
color.xyz = lerp( color.xyz, softlight( color.xyz, cold.xyz ), abs( tint_h * weight_h ));
else
color.xyz = lerp( color.xyz, softlight( color.xyz, warm.xyz ), tint_h * weight_h );
color.xyz = sat( color.xyz, saturation_h * weight_h );
color.xyz = vib( color.xyz, vibrance_h * weight_h );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_03_Shadows_Midtones_Highlights
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_SMH;
}
}
}

View File

@ -0,0 +1,378 @@
/*
Description : PD80 04 Black & White for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace pd80_blackandwhite
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform float curve_str <
ui_type = "slider";
ui_label = "Contrast Smoothness";
ui_tooltip = "Contrast Smoothness";
ui_category = "Global";
ui_min = 1.0f;
ui_max = 4.0f;
> = 1.5f;
uniform bool show_clip <
ui_label = "Show Clipping Mask";
ui_tooltip = "Show Clipping Mask";
ui_category = "Global";
> = false;
uniform int bw_mode < __UNIFORM_COMBO_INT1
ui_label = "Black & White Conversion";
ui_tooltip = "Black & White Conversion";
ui_category = "Black & White Techniques";
ui_items = "Red Filter\0Green Filter\0Blue Filter\0High Contrast Red Filter\0High Contrast Green Filter\0High Contrast Blue Filter\0Infrared\0Maximum Black\0Maximum White\0Preserve Luminosity\0Neutral Green Filter\0Maintain Contrasts\0High Contrast\0Custom\0";
> = 13;
uniform float redchannel <
ui_type = "slider";
ui_label = "Custom: Red Weight";
ui_tooltip = "Custom: Red Weight";
ui_category = "Black & White Techniques";
ui_min = -2.0f;
ui_max = 3.0f;
> = 0.2f;
uniform float yellowchannel <
ui_type = "slider";
ui_label = "Custom: Yellow Weight";
ui_tooltip = "Custom: Yellow Weight";
ui_category = "Black & White Techniques";
ui_min = -2.0f;
ui_max = 3.0f;
> = 0.4f;
uniform float greenchannel <
ui_type = "slider";
ui_label = "Custom: Green Weight";
ui_tooltip = "Custom: Green Weight";
ui_category = "Black & White Techniques";
ui_min = -2.0f;
ui_max = 3.0f;
> = 0.6f;
uniform float cyanchannel <
ui_type = "slider";
ui_label = "Custom: Cyan Weight";
ui_tooltip = "Custom: Cyan Weight";
ui_category = "Black & White Techniques";
ui_min = -2.0f;
ui_max = 3.0f;
> = 0.0f;
uniform float bluechannel <
ui_type = "slider";
ui_label = "Custom: Blue Weight";
ui_tooltip = "Custom: Blue Weight";
ui_category = "Black & White Techniques";
ui_min = -2.0f;
ui_max = 3.0f;
> = -0.6f;
uniform float magentachannel <
ui_type = "slider";
ui_label = "Custom: Magenta Weight";
ui_tooltip = "Custom: Magenta Weight";
ui_category = "Black & White Techniques";
ui_min = -2.0f;
ui_max = 3.0f;
> = -0.2f;
uniform bool use_tint <
ui_label = "Enable Tinting";
ui_tooltip = "Enable Tinting";
ui_category = "Tint";
> = false;
uniform float tinthue <
ui_type = "slider";
ui_label = "Tint Hue";
ui_tooltip = "Tint Hue";
ui_category = "Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.083f;
uniform float tintsat <
ui_type = "slider";
ui_label = "Tint Saturation";
ui_tooltip = "Tint Saturation";
ui_category = "Tint";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.12f;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float2 pingpong < source = "pingpong"; min = 0; max = 128; step = 1; >;
// Credit to user 'iq' from shadertoy
// See https://www.shadertoy.com/view/MdBfR1
float curve( float x, float k )
{
float s = sign( x - 0.5f );
float o = ( 1.0f + s ) / 2.0f;
return o - 0.5f * s * pow( max( 2.0f * ( o - s * x ), 0.0f ), k );
}
float3 ProcessBW( float3 col, float r, float y, float g, float c, float b, float m )
{
float3 hsl = RGBToHSL( col.xyz );
// Inverse of luma channel to no apply boosts to intensity on already intense brightness (and blow out easily)
float lum = 1.0f - hsl.z;
// Calculate the individual weights per color component in RGB and CMY
// Sum of all the weights for a given hue is 1.0
float weight_r = curve( max( 1.0f - abs( hsl.x * 6.0f ), 0.0f ), curve_str ) +
curve( max( 1.0f - abs(( hsl.x - 1.0f ) * 6.0f ), 0.0f ), curve_str );
float weight_y = curve( max( 1.0f - abs(( hsl.x - 0.166667f ) * 6.0f ), 0.0f ), curve_str );
float weight_g = curve( max( 1.0f - abs(( hsl.x - 0.333333f ) * 6.0f ), 0.0f ), curve_str );
float weight_c = curve( max( 1.0f - abs(( hsl.x - 0.5f ) * 6.0f ), 0.0f ), curve_str );
float weight_b = curve( max( 1.0f - abs(( hsl.x - 0.666667f ) * 6.0f ), 0.0f ), curve_str );
float weight_m = curve( max( 1.0f - abs(( hsl.x - 0.833333f ) * 6.0f ), 0.0f ), curve_str );
// No saturation (greyscale) should not influence B&W image
float sat = hsl.y * ( 1.0f - hsl.y ) + hsl.y;
float ret = hsl.z;
ret += ( hsl.z * ( weight_r * r ) * sat * lum );
ret += ( hsl.z * ( weight_y * y ) * sat * lum );
ret += ( hsl.z * ( weight_g * g ) * sat * lum );
ret += ( hsl.z * ( weight_c * c ) * sat * lum );
ret += ( hsl.z * ( weight_b * b ) * sat * lum );
ret += ( hsl.z * ( weight_m * m ) * sat * lum );
return saturate( ret );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_BlackandWhite(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
color.xyz = saturate( color.xyz );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 4, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.zyx );
float red; float yellow; float green;
float cyan; float blue; float magenta;
switch( bw_mode )
{
case 0: // Red Filter
{
red = 0.2f;
yellow = 0.5f;
green = -0.2f;
cyan = -0.6f;
blue = -1.0f;
magenta = -0.2f;
}
break;
case 1: // Green Filter
{
red = -0.5f;
yellow = 0.5f;
green = 1.2f;
cyan = -0.2f;
blue = -1.0f;
magenta = -0.5f;
}
break;
case 2: // Blue Filter
{
red = -0.2f;
yellow = 0.4f;
green = -0.6f;
cyan = 0.5f;
blue = 1.0f;
magenta = -0.2f;
}
break;
case 3: // High Contrast Red Filter
{
red = 0.5f;
yellow = 1.2f;
green = -0.5f;
cyan = -1.0f;
blue = -1.5f;
magenta = -1.0f;
}
break;
case 4: // High Contrast Green Filter
{
red = -1.0f;
yellow = 1.0f;
green = 1.2f;
cyan = -0.2f;
blue = -1.5f;
magenta = -1.0f;
}
break;
case 5: // High Contrast Blue Filter
{
red = -0.7f;
yellow = 0.4f;
green = -1.2f;
cyan = 0.7f;
blue = 1.2f;
magenta = -0.2f;
}
break;
case 6: // Infrared
{
red = -1.35f;
yellow = 2.35f;
green = 1.35f;
cyan = -1.35f;
blue = -1.6f;
magenta = -1.07f;
}
break;
case 7: // Maximum Black
{
red = -1.0f;
yellow = -1.0f;
green = -1.0f;
cyan = -1.0f;
blue = -1.0f;
magenta = -1.0f;
}
break;
case 8: // Maximum White
{
red = 1.0f;
yellow = 1.0f;
green = 1.0f;
cyan = 1.0f;
blue = 1.0f;
magenta = 1.0f;
}
break;
case 9: // Preserve Luminosity
{
red = -0.7f;
yellow = 0.9f;
green = 0.6f;
cyan = 0.1f;
blue = -0.4f;
magenta = -0.4f;
}
break;
case 10: // Neutral Green Filter
{
red = 0.2f;
yellow = 0.4f;
green = 0.6f;
cyan = 0.0f;
blue = -0.6f;
magenta = -0.2f;
}
break;
case 11: // Maintain Contrasts
{
red = -0.3f;
yellow = 1.0f;
green = -0.3f;
cyan = -0.6f;
blue = -1.0f;
magenta = -0.6f;
}
break;
case 12: // High Contrast
{
red = -0.3f;
yellow = 2.6f;
green = -0.3f;
cyan = -1.2f;
blue = -0.6f;
magenta = -0.4f;
}
break;
case 13: // Custom Filter
{
red = redchannel;
yellow = yellowchannel;
green = greenchannel;
cyan = cyanchannel;
blue = bluechannel;
magenta = magentachannel;
}
break;
default:
{
red = redchannel;
yellow = yellowchannel;
green = greenchannel;
cyan = cyanchannel;
blue = bluechannel;
magenta = magentachannel;
}
break;
}
// Do the Black & White
color.xyz = ProcessBW( color.xyz, red, yellow, green, cyan, blue, magenta );
// Do the tinting
color.xyz = lerp( color.xyz, HSLToRGB( float3( tinthue, tintsat, color.x )), use_tint );
if( show_clip )
{
float h = 0.98f;
float l = 0.01f;
color.xyz = min( min( color.x, color.y ), color.z ) >= h ? lerp( color.xyz, float3( 1.0f, 0.0f, 0.0f ), smoothstep( h, 1.0f, min( min( color.x, color.y ), color.z ))) : color.xyz;
color.xyz = max( max( color.x, color.y ), color.z ) <= l ? lerp( float3( 0.0f, 0.0f, 1.0f ), color.xyz, smoothstep( 0.0f, l, max( max( color.x, color.y ), color.z ))) : color.xyz;
}
color.xyz = saturate( color.xyz + dnoise.xyz );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_Black_and_White
{
pass prod80_BlackandWhite
{
VertexShader = PostProcessVS;
PixelShader = PS_BlackandWhite;
}
}
}

View File

@ -0,0 +1,221 @@
/*
Description : PD80 04 Color Balance for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_colorbalance
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENS /////////////////////////////////////////////////////////////////
uniform bool preserve_luma <
ui_label = "Preserve Luminosity";
ui_tooltip = "Preserve Luminosity";
ui_category = "Color Balance";
> = true;
uniform int separation_mode < __UNIFORM_COMBO_INT1
ui_label = "Luma Separation Mode";
ui_tooltip = "Luma Separation Mode";
ui_category = "Color Balance";
ui_items = "Harsh Separation\0Smooth Separation\0";
> = 0;
uniform float s_RedShift <
ui_label = "Cyan <--> Red";
ui_tooltip = "Shadows: Cyan <--> Red";
ui_category = "Shadows";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float s_GreenShift <
ui_label = "Magenta <--> Green";
ui_tooltip = "Shadows: Magenta <--> Green";
ui_category = "Shadows";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float s_BlueShift <
ui_label = "Yellow <--> Blue";
ui_tooltip = "Shadows: Yellow <--> Blue";
ui_category = "Shadows";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float m_RedShift <
ui_label = "Cyan <--> Red";
ui_tooltip = "Midtones: Cyan <--> Red";
ui_category = "Midtones";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float m_GreenShift <
ui_label = "Magenta <--> Green";
ui_tooltip = "Midtones: Magenta <--> Green";
ui_category = "Midtones";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float m_BlueShift <
ui_label = "Yellow <--> Blue";
ui_tooltip = "Midtones: Yellow <--> Blue";
ui_category = "Midtones";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float h_RedShift <
ui_label = "Cyan <--> Red";
ui_tooltip = "Highlights: Cyan <--> Red";
ui_category = "Highlights";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float h_GreenShift <
ui_label = "Magenta <--> Green";
ui_tooltip = "Highlights: Magenta <--> Green";
ui_category = "Highlights";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float h_BlueShift <
ui_label = "Yellow <--> Blue";
ui_tooltip = "Highlights: Yellow <--> Blue";
ui_category = "Highlights";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
#define ES_RGB float3( 1.0 - float3( 0.299, 0.587, 0.114 ))
#define ES_CMY float3( dot( ES_RGB.yz, 0.5 ), dot( ES_RGB.xz, 0.5 ), dot( ES_RGB.xy, 0.5 ))
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float3 curve( float3 x )
{
return x * x * ( 3.0f - 2.0f * x );
}
float3 ColorBalance( float3 c, float3 shadows, float3 midtones, float3 highlights )
{
// For highlights
float luma = dot( c.xyz, float3( 0.333333f, 0.333334f, 0.333333f ));
// Determine the distribution curves between shadows, midtones, and highlights
float3 dist_s; float3 dist_h;
switch( separation_mode )
{
/*
Clear cutoff between shadows and highlights
Maximizes precision at the loss of harsher transitions between contrasts
Curves look like:
Shadows Highlights Midtones
‾‾‾—_ _—‾‾‾ _——‾‾‾——_
‾‾——__________ __________——‾‾ ___—‾ ‾—___
0.0.....0.5.....1.0 0.0.....0.5.....1.0 0.0.....0.5.....1.0
*/
case 0:
{
dist_s.xyz = curve( max( 1.0f - c.xyz * 2.0f, 0.0f ));
dist_h.xyz = curve( max(( c.xyz - 0.5f ) * 2.0f, 0.0f ));
} break;
/*
Higher degree of blending between individual curves
F.e. shadows will still have a minimal weight all the way into highlight territory
Ensures smoother transition areas between contrasts
Curves look like:
Shadows Highlights Midtones
‾‾‾—_ _—‾‾‾ __---__
‾‾———————_____ _____———————‾‾ ___-‾‾ ‾‾-___
0.0.....0.5.....1.0 0.0.....0.5.....1.0 0.0.....0.5.....1.0
*/
case 1:
{
dist_s.xyz = pow( 1.0f - c.xyz, 4.0f );
dist_h.xyz = pow( c.xyz, 4.0f );
} break;
}
// Get luminosity offsets
// One could omit this whole code part in case no luma should be preserved
float3 s_rgb = 1.0f;
float3 m_rgb = 1.0f;
float3 h_rgb = 1.0f;
if( preserve_luma )
{
s_rgb = shadows > 0.0f ? ES_RGB * shadows : ES_CMY * abs( shadows );
m_rgb = midtones > 0.0f ? ES_RGB * midtones : ES_CMY * abs( midtones );
h_rgb = highlights > 0.0f ? ES_RGB * highlights : ES_CMY * abs( highlights );
}
float3 mids = saturate( 1.0f - dist_s.xyz - dist_h.xyz );
float3 highs = dist_h.xyz * ( highlights.xyz * h_rgb.xyz * ( 1.0f - luma ));
float3 newc = c.xyz * ( dist_s.xyz * shadows.xyz * s_rgb.xyz + mids.xyz * midtones.xyz * m_rgb.xyz ) * ( 1.0f - c.xyz ) + highs.xyz;
return saturate( c.xyz + newc.xyz );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_ColorBalance(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
color.xyz = saturate( color.xyz );
color.xyz = ColorBalance( color.xyz, float3( s_RedShift, s_GreenShift, s_BlueShift ),
float3( m_RedShift, m_GreenShift, m_BlueShift ),
float3( h_RedShift, h_GreenShift, h_BlueShift ));
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_ColorBalance
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_ColorBalance;
}
}
}

View File

@ -0,0 +1,362 @@
/*
Description : PD80 04 Color Gradients for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Blend_Modes.fxh"
namespace pd80_ColorGradients
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int luma_mode < __UNIFORM_COMBO_INT1
ui_label = "Luma Mode";
ui_tooltip = "Luma Mode";
ui_category = "Global";
ui_items = "Use Average\0Use Perceived Luma\0Use Max Value\0";
> = 0;
uniform int separation_mode < __UNIFORM_COMBO_INT1
ui_label = "Luma Separation Mode";
ui_tooltip = "Luma Separation Mode";
ui_category = "Global";
ui_items = "Harsh Separation\0Smooth Separation\0";
> = 0;
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform float CGdesat <
ui_label = "Desaturate Base Image";
ui_tooltip = "Desaturate Base Image";
ui_category = "Mixing Values";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float finalmix <
ui_label = "Mix with Original";
ui_tooltip = "Mix with Original";
ui_category = "Mixing Values";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.333;
// Light Scene
uniform float3 blendcolor_ls_m <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Light Scene: Midtone Color";
ui_category = "Light Scene: Midtone Color";
> = float3( 0.98, 0.588, 0.0 );
uniform int blendmode_ls_m < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Light Scene: Midtone Color Blendmode";
ui_category = "Light Scene: Midtone Color";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 10;
uniform float opacity_ls_m <
ui_label = "Opacity";
ui_tooltip = "Light Scene: Midtone Color Opacity";
ui_category = "Light Scene: Midtone Color";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
uniform float3 blendcolor_ls_s <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Light Scene: Shadow Color";
ui_category = "Light Scene: Shadow Color";
> = float3( 0.0, 0.365, 1.0 );
uniform int blendmode_ls_s < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Light Scene: Shadow Color Blendmode";
ui_category = "Light Scene: Shadow Color";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 5;
uniform float opacity_ls_s <
ui_label = "Opacity";
ui_tooltip = "Light Scene: Shadow Color Opacity";
ui_category = "Light Scene: Shadow Color";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.3;
// Dark Scene
uniform bool enable_ds <
ui_text = "-------------------------------------\n"
"Enables transitions of gradients\n"
"depending on average scene luminance.\n"
"To simulate Day-Night color grading.\n"
"-------------------------------------";
ui_label = "Enable Color Transitions";
ui_tooltip = "Enable Color Transitions";
ui_category = "Enable Color Transitions";
> = true;
uniform float3 blendcolor_ds_m <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Dark Scene: Midtone Color";
ui_category = "Dark Scene: Midtone Color";
> = float3( 0.0, 0.365, 1.0 );
uniform int blendmode_ds_m < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Dark Scene: Midtone Color Blendmode";
ui_category = "Dark Scene: Midtone Color";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 10;
uniform float opacity_ds_m <
ui_label = "Opacity";
ui_tooltip = "Dark Scene: Midtone Color Opacity";
ui_category = "Dark Scene: Midtone Color";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
uniform float3 blendcolor_ds_s <
ui_type = "color";
ui_label = "Color";
ui_tooltip = "Dark Scene: Shadow Color";
ui_category = "Dark Scene: Shadow Color";
> = float3( 0.0, 0.039, 0.588 );
uniform int blendmode_ds_s < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Dark Scene: Shadow Color Blendmode";
ui_category = "Dark Scene: Shadow Color";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 10;
uniform float opacity_ds_s <
ui_label = "Opacity";
ui_tooltip = "Dark Scene: Shadow Color Opacity";
ui_category = "Dark Scene: Shadow Color";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
uniform float minlevel <
ui_label = "Pure Dark Scene Level";
ui_tooltip = "Pure Dark Scene Level";
ui_category = "Scene Luminance Adaptation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.125;
uniform float maxlevel <
ui_label = "Pure Light Scene Level";
ui_tooltip = "Pure Light Scene Level";
ui_category = "Scene Luminance Adaptation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.3;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texLuma { Width = 256; Height = 256; Format = R16F; MipLevels = 8; };
texture texAvgLuma { Format = R16F; };
texture texPrevAvgLuma { Format = R16F; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerLuma { Texture = texLuma; };
sampler samplerAvgLuma { Texture = texAvgLuma; };
sampler samplerPrevAvgLuma { Texture = texPrevAvgLuma; };
//// DEFINES ////////////////////////////////////////////////////////////////////
#define LumCoeff float3(0.212656, 0.715158, 0.072186)
uniform float Frametime < source = "frametime"; >;
uniform float2 pingpong < source = "pingpong"; min = 0; max = 128; step = 1; >;
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, LumCoeff );
}
float curve( float x )
{
return x * x * ( 3.0f - 2.0f * x );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float PS_WriteLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float luma = max( max( color.x, color.y ), color.z );
return luma; //writes to texLuma
}
float PS_AvgLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float luma = tex2Dlod( samplerLuma, float4( 0.5f, 0.5f, 0, 8 )).x;
float prevluma = tex2D( samplerPrevAvgLuma, float2( 0.5f, 0.5f )).x;
float avgLuma = lerp( prevluma, luma, saturate( Frametime * 0.003f ));
return avgLuma; //writes to texAvgLuma
}
float4 PS_ColorGradients(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float sceneluma = tex2D( samplerAvgLuma, float2( 0.5f, 0.5f )).x;
float ml = ( minlevel >= maxlevel ) ? maxlevel - 0.01f : minlevel;
sceneluma = smoothstep( ml, maxlevel, sceneluma );
color.xyz = saturate( color.xyz );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 5, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.xyz );
// Weights
float cWeight;
switch( luma_mode )
{
case 0: // Use average
{
cWeight = dot( color.xyz, float3( 0.333333f, 0.333334f, 0.333333f ));
}
break;
case 1: // Use perceived luma
{
cWeight = dot( color.xyz, float3( 0.212656f, 0.715158f, 0.072186f ));
}
break;
case 2: // Use max
{
cWeight = max( max( color.x, color.y ), color.z );
}
break;
}
float w_s; float w_h; float w_m;
switch( separation_mode )
{
/*
Clear cutoff between shadows and highlights
Maximizes precision at the loss of harsher transitions between contrasts
Curves look like:
Shadows Highlights Midtones
‾‾‾—_ _—‾‾‾ _——‾‾‾——_
‾‾——__________ __________——‾‾ ___—‾ ‾—___
0.0.....0.5.....1.0 0.0.....0.5.....1.0 0.0.....0.5.....1.0
*/
case 0:
{
w_s = curve( max( 1.0f - cWeight * 2.0f, 0.0f ));
w_h = curve( max(( cWeight - 0.5f ) * 2.0f, 0.0f ));
w_m = saturate( 1.0f - w_s - w_h );
} break;
/*
Higher degree of blending between individual curves
F.e. shadows will still have a minimal weight all the way into highlight territory
Ensures smoother transition areas between contrasts
Curves look like:
Shadows Highlights Midtones
‾‾‾—_ _—‾‾‾ __---__
‾‾———————_____ _____———————‾‾ ___-‾‾ ‾‾-___
0.0.....0.5.....1.0 0.0.....0.5.....1.0 0.0.....0.5.....1.0
*/
case 1:
{
w_s = pow( 1.0f - cWeight, 4.0f );
w_h = pow( cWeight, 4.0f );
w_m = saturate( 1.0f - w_s - w_h );
} break;
}
// Desat original
// float pLuma = getLuminance( color.xyz );
color.xyz = lerp( color.xyz, cWeight, CGdesat );
// Coloring
float3 LS_col;
float3 DS_col;
// Light scene
float3 LS_b_s = blendmode( color.xyz, blendcolor_ls_s.xyz, blendmode_ls_s, opacity_ls_s );
float3 LS_b_m = blendmode( color.xyz, blendcolor_ls_m.xyz, blendmode_ls_m, opacity_ls_m );
LS_col.xyz = LS_b_s.xyz * w_s + LS_b_m.xyz * w_m + w_h;
// Dark Scene
float3 DS_b_s = blendmode( color.xyz, blendcolor_ds_s.xyz, blendmode_ds_s, opacity_ds_s );
float3 DS_b_m = blendmode( color.xyz, blendcolor_ds_m.xyz, blendmode_ds_m, opacity_ds_m );
DS_col.xyz = DS_b_s.xyz * w_s + DS_b_m.xyz * w_m + w_h;
// Mix
float3 new_c = lerp( DS_col.xyz, LS_col.xyz, sceneluma );
new_c.xyz = ( enable_ds ) ? new_c.xyz : LS_col.xyz;
color.xyz = lerp( color.xyz, new_c.xyz, finalmix );
return float4( color.xyz, 1.0f );
}
float PS_PrevAvgLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float avgLuma = tex2D( samplerAvgLuma, float2( 0.5f, 0.5f )).x;
return avgLuma; //writes to texPrevAvgLuma
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_ColorGradient
{
pass Luma
{
VertexShader = PostProcessVS;
PixelShader = PS_WriteLuma;
RenderTarget = texLuma;
}
pass AvgLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_AvgLuma;
RenderTarget = texAvgLuma;
}
pass ColorGradients
{
VertexShader = PostProcessVS;
PixelShader = PS_ColorGradients;
}
pass PreviousLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_PrevAvgLuma;
RenderTarget = texPrevAvgLuma;
}
}
}

View File

@ -0,0 +1,117 @@
/*
Description : PD80 04 Color Isolation for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace pd80_ColorIsolation
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float hueMid <
ui_label = "Hue Selection (Middle)";
ui_category = "Color Isolation";
ui_tooltip = "0 = Red, 0.167 = Yellow, 0.333 = Green, 0.5 = Cyan, 0.666 = Blue, 0.833 = Magenta";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float hueRange <
ui_label = "Hue Range Selection";
ui_tooltip = "Hue Range Selection";
ui_category = "Color Isolation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.167;
uniform float satLimit <
ui_label = "Saturation Output";
ui_tooltip = "Saturation Output";
ui_category = "Color Isolation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
uniform float fxcolorMix <
ui_label = "Mix with Original";
ui_tooltip = "Mix with Original";
ui_category = "Color Isolation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
#define LumCoeff float3(0.212656, 0.715158, 0.072186)
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, LumCoeff );
}
float smootherstep( float x )
{
return x * x * x * ( x * ( x * 6.0f - 15.0f ) + 10.0f );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_ColorIso(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
color.xyz = saturate( color.xyz ); //Can't work with HDR
float grey = getLuminance( color.xyz );
float hue = RGBToHSV( color.xyz ).x;
float r = rcp( hueRange );
float3 w = max( 1.0f - abs(( hue - hueMid ) * r ), 0.0f );
w.y = max( 1.0f - abs(( hue + 1.0f - hueMid ) * r ), 0.0f );
w.z = max( 1.0f - abs(( hue - 1.0f - hueMid ) * r ), 0.0f );
float weight = dot( w.xyz, 1.0f );
float3 newc = lerp( grey, color.xyz, smootherstep( weight ) * satLimit );
color.xyz = lerp( color.xyz, newc.xyz, fxcolorMix );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_ColorIsolation
{
pass ColorIso
{
VertexShader = PostProcessVS;
PixelShader = PS_ColorIso;
}
}
}

View File

@ -0,0 +1,95 @@
/*
Description : PD80 04 Color Temperature for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits
- Taller Helland
http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
- Renaud Bédard https://www.shadertoy.com/view/lsSXW1
License: https://creativecommons.org/licenses/by/3.0/
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace pd80_colortemp
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform uint Kelvin <
ui_label = "Color Temp (K)";
ui_tooltip = "Color Temp (K)";
ui_category = "Kelvin";
ui_type = "slider";
ui_min = 1000;
ui_max = 40000;
> = 6500;
uniform float LumPreservation <
ui_label = "Luminance Preservation";
ui_tooltip = "Luminance Preservation";
ui_category = "Kelvin";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
uniform float kMix <
ui_label = "Mix with Original";
ui_tooltip = "Mix with Original";
ui_category = "Kelvin";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_ColorTemp(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float3 kColor = KelvinToRGB( Kelvin );
float3 oLum = RGBToHSL( color.xyz );
float3 blended = lerp( color.xyz, color.xyz * kColor.xyz, kMix );
float3 resHSV = RGBToHSL( blended.xyz );
float3 resRGB = HSLToRGB( float3( resHSV.xy, oLum.z ));
color.xyz = lerp( blended.xyz, resRGB.xyz, LumPreservation );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_ColorTemperature
{
pass ColorTemp
{
VertexShader = PostProcessVS;
PixelShader = PS_ColorTemp;
}
}
}

View File

@ -0,0 +1,371 @@
/*
Description : PD80 04 Contrast Brightness Saturation for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Color_Spaces.fxh"
#include "PD80_00_Blend_Modes.fxh"
#include "PD80_00_Base_Effects.fxh"
namespace pd80_conbrisat
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Global";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Global";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform float tint <
ui_label = "Tint";
ui_tooltip = "Tint";
ui_category = "Final Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float exposureN <
ui_label = "Exposure";
ui_tooltip = "Exposure";
ui_category = "Final Adjustments";
ui_type = "slider";
ui_min = -4.0;
ui_max = 4.0;
> = 0.0;
uniform float contrast <
ui_label = "Contrast";
ui_tooltip = "Contrast";
ui_category = "Final Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float brightness <
ui_label = "Brightness";
ui_tooltip = "Brightness";
ui_category = "Final Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float saturation <
ui_label = "Saturation";
ui_tooltip = "Saturation";
ui_category = "Final Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float vibrance <
ui_label = "Vibrance";
ui_tooltip = "Vibrance";
ui_category = "Final Adjustments";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float huemid <
ui_label = "Color Hue";
ui_tooltip = "Custom Color Hue";
ui_category = "Custom Saturation Adjustments";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float huerange <
ui_label = "Hue Range Selection";
ui_tooltip = "Custom Hue Range Selection";
ui_category = "Custom Saturation Adjustments";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.167;
uniform float sat_custom <
ui_label = "Custom Saturation Level";
ui_tooltip = "Custom Saturation Level";
ui_category = "Custom Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_r <
ui_label = "Red Saturation";
ui_tooltip = "Red Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_y <
ui_label = "Yellow Saturation";
ui_tooltip = "Yellow Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_g <
ui_label = "Green Saturation";
ui_tooltip = "Green Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_a <
ui_label = "Aqua Saturation";
ui_tooltip = "Aqua Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_b <
ui_label = "Blue Saturation";
ui_tooltip = "Blue Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_p <
ui_label = "Purple Saturation";
ui_tooltip = "Purple Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform float sat_m <
ui_label = "Magenta Saturation";
ui_tooltip = "Magenta Saturation";
ui_category = "Color Saturation Adjustments";
ui_type = "slider";
ui_min = -2.0;
ui_max = 2.0;
> = 0.0;
uniform bool enable_depth <
ui_label = "Enable depth based adjustments.\nMake sure you have setup your depth buffer correctly.";
ui_tooltip = "Enable depth based adjustments";
ui_category = "Final Adjustments: Depth";
> = false;
uniform bool display_depth <
ui_label = "Show depth texture";
ui_tooltip = "Show depth texture";
ui_category = "Final Adjustments: Depth";
> = false;
uniform float depthStart <
ui_type = "slider";
ui_label = "Change Depth Start Plane";
ui_tooltip = "Change Depth Start Plane";
ui_category = "Final Adjustments: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.0;
uniform float depthEnd <
ui_type = "slider";
ui_label = "Change Depth End Plane";
ui_tooltip = "Change Depth End Plane";
ui_category = "Final Adjustments: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.1;
uniform float depthCurve <
ui_label = "Depth Curve Adjustment";
ui_tooltip = "Depth Curve Adjustment";
ui_category = "Final Adjustments: Depth";
ui_type = "slider";
ui_min = 0.05;
ui_max = 8.0;
> = 1.0;
uniform float exposureD <
ui_label = "Exposure Far";
ui_tooltip = "Exposure Far";
ui_category = "Final Adjustments: Far";
ui_type = "slider";
ui_min = -4.0;
ui_max = 4.0;
> = 0.0;
uniform float contrastD <
ui_label = "Contrast Far";
ui_tooltip = "Contrast Far";
ui_category = "Final Adjustments: Far";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float brightnessD <
ui_label = "Brightness Far";
ui_tooltip = "Brightness Far";
ui_category = "Final Adjustments: Far";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.5;
> = 0.0;
uniform float saturationD <
ui_label = "Saturation Far";
ui_tooltip = "Saturation Far";
ui_category = "Final Adjustments: Far";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float vibranceD <
ui_label = "Vibrance Far";
ui_tooltip = "Vibrance Far";
ui_category = "Final Adjustments: Far";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, float3( 0.212656, 0.715158, 0.072186 ));
}
float curve( float x )
{
return x * x * ( 3.0 - 2.0 * x );
}
float3 channelsat( float3 col, float r, float y, float g, float a, float b, float p, float m, float hue )
{
float desat = getLuminance( col.xyz );
// Red : 0.0
// Orange : 0.083
// Yellow : 0.167
// Green : 0.333
// Cyan/Aqua : 0.5
// Blue : 0.667
// Purple : 0.75
// Magenta : 0.833
float weight_r = curve( max( 1.0f - abs( hue * 6.0f ), 0.0f )) +
curve( max( 1.0f - abs(( hue - 1.0f ) * 6.0f ), 0.0f ));
float weight_y = curve( max( 1.0f - abs(( hue - 0.166667f ) * 6.0f ), 0.0f ));
float weight_g = curve( max( 1.0f - abs(( hue - 0.333333f ) * 6.0f ), 0.0f ));
float weight_a = curve( max( 1.0f - abs(( hue - 0.5f ) * 6.0f ), 0.0f ));
float weight_b = curve( max( 1.0f - abs(( hue - 0.666667f ) * 6.0f ), 0.0f ));
float weight_p = curve( max( 1.0f - abs(( hue - 0.75f ) * 6.0f ), 0.0f ));
float weight_m = curve( max( 1.0f - abs(( hue - 0.833333f ) * 6.0f ), 0.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + r * weight_r, 0.0f, 2.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + y * weight_y, 0.0f, 2.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + g * weight_g, 0.0f, 2.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + a * weight_a, 0.0f, 2.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + b * weight_b, 0.0f, 2.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + p * weight_p, 0.0f, 2.0f ));
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + m * weight_m, 0.0f, 2.0f ));
return saturate( col.xyz );
}
float3 customsat( float3 col, float h, float range, float sat, float hue )
{
float desat = getLuminance( col.xyz );
float r = rcp( range );
float3 w = max( 1.0f - abs(( hue - h ) * r ), 0.0f );
w.y = max( 1.0f - abs(( hue + 1.0f - h ) * r ), 0.0f );
w.z = max( 1.0f - abs(( hue - 1.0f - h ) * r ), 0.0f );
float weight = curve( dot( w.xyz, 1.0f )) * sat;
col.xyz = lerp( desat, col.xyz, clamp( 1.0f + weight, 0.0f, 2.0f ));
return saturate( col.xyz );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_CBS(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 6, enable_dither, dither_strength, 1, 0.5f );
color.xyz = saturate( color.xyz + dnoise.xyz );
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
depth = smoothstep( depthStart, depthEnd, depth );
depth = pow( depth, depthCurve );
float4 dnoise2 = dither( samplerGaussNoise, texcoord.xy, 0, 1, 1.0f, 0, 1.0f );
depth = saturate( depth + dnoise2.x );
float3 cold = float3( 0.0f, 0.365f, 1.0f ); //LBB
float3 warm = float3( 0.98f, 0.588f, 0.0f ); //LBA
color.xyz = ( tint < 0.0f ) ? lerp( color.xyz, blendLuma( cold.xyz, color.xyz ), abs( tint )) :
lerp( color.xyz, blendLuma( warm.xyz, color.xyz ), tint );
float3 dcolor = color.xyz;
color.xyz = exposure( color.xyz, exposureN );
color.xyz = con( color.xyz, contrast );
color.xyz = bri( color.xyz, brightness );
color.xyz = sat( color.xyz, saturation );
color.xyz = vib( color.xyz, vibrance );
dcolor.xyz = exposure( dcolor.xyz, exposureD );
dcolor.xyz = con( dcolor.xyz, contrastD );
dcolor.xyz = bri( dcolor.xyz, brightnessD );
dcolor.xyz = sat( dcolor.xyz, saturationD );
dcolor.xyz = vib( dcolor.xyz, vibranceD );
color.xyz = lerp( color.xyz, dcolor.xyz, enable_depth * depth ); // apply based on depth
float chue = RGBToHSL( color.xyz ).x;
color.xyz = channelsat( color.xyz, sat_r, sat_y, sat_g, sat_a, sat_b, sat_p, sat_m, chue );
color.xyz = customsat( color.xyz, huemid, huerange, sat_custom, chue );
color.xyz = display_depth ? depth.xxx : color.xyz; // show depth
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_ContrastBrightnessSaturation
{
pass ConBriSat
{
VertexShader = PostProcessVS;
PixelShader = PS_CBS;
}
}
}

View File

@ -0,0 +1,364 @@
/*
Description : PD80 04 Magical Rectangle for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Blend_Modes.fxh"
#include "PD80_00_Color_Spaces.fxh"
#include "PD80_00_Base_Effects.fxh"
namespace pd80_magicalrectangle
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int shape < __UNIFORM_COMBO_INT1
ui_label = "Shape";
ui_tooltip = "Shape";
ui_category = "Shape Manipulation";
ui_items = "Square\0Circle\0";
> = 0;
uniform bool invert_shape <
ui_label = "Invert Shape";
ui_tooltip = "Invert Shape";
ui_category = "Shape Manipulation";
> = false;
uniform uint rotation <
ui_type = "slider";
ui_label = "Rotation Factor";
ui_tooltip = "Rotation Factor";
ui_category = "Shape Manipulation";
ui_min = 0;
ui_max = 360;
> = 45;
uniform float2 center <
ui_type = "slider";
ui_label = "Center";
ui_tooltip = "Center";
ui_category = "Shape Manipulation";
ui_min = 0.0;
ui_max = 1.0;
> = float2( 0.5, 0.5 );
uniform float ret_size_x <
ui_type = "slider";
ui_label = "Horizontal Size";
ui_tooltip = "Horizontal Size";
ui_category = "Shape Manipulation";
ui_min = 0.0;
ui_max = 0.5;
> = 0.125;
uniform float ret_size_y <
ui_type = "slider";
ui_label = "Vertical Size";
ui_tooltip = "Vertical Size";
ui_category = "Shape Manipulation";
ui_min = 0.0;
ui_max = 0.5;
> = 0.125;
uniform float depthpos <
ui_type = "slider";
ui_label = "Depth Position";
ui_tooltip = "Depth Position";
ui_category = "Shape Manipulation";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float smoothing <
ui_type = "slider";
ui_label = "Edge Smoothing";
ui_tooltip = "Edge Smoothing";
ui_category = "Shape Manipulation";
ui_min = 0.0;
ui_max = 1.0;
> = 0.01;
uniform float depth_smoothing <
ui_type = "slider";
ui_label = "Depth Smoothing";
ui_tooltip = "Depth Smoothing";
ui_category = "Shape Manipulation";
ui_min = 0.0;
ui_max = 1.0;
> = 0.002;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Shape Manipulation";
ui_min = 0.0f;
ui_max = 10.0f;
> = 0.0;
uniform float3 reccolor <
ui_text = "-------------------------------------\n"
"Use Opacity and Blend Mode to adjust\n"
"Shape controls the Shape coloring\n"
"Image controls the underlying picture\n"
"-------------------------------------";
ui_type = "color";
ui_label = "Shape: Color";
ui_tooltip = "Shape: Color";
ui_category = "Shape Coloration";
> = float3( 0.5, 0.5, 0.5 );
uniform float mr_exposure <
ui_type = "slider";
ui_label = "Image: Exposure";
ui_tooltip = "Image: Exposure";
ui_category = "Shape Coloration";
ui_min = -4.0;
ui_max = 4.0;
> = 0.0;
uniform float mr_contrast <
ui_type = "slider";
ui_label = "Image: Contrast";
ui_tooltip = "Image: Contrast";
ui_category = "Shape Coloration";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float mr_brightness <
ui_type = "slider";
ui_label = "Image: Brightness";
ui_tooltip = "Image: Brightness";
ui_category = "Shape Coloration";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float mr_hue <
ui_type = "slider";
ui_label = "Image: Hue";
ui_tooltip = "Image: Hue";
ui_category = "Shape Coloration";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float mr_saturation <
ui_type = "slider";
ui_label = "Image: Saturation";
ui_tooltip = "Image: Saturation";
ui_category = "Shape Coloration";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform float mr_vibrance <
ui_type = "slider";
ui_label = "Image: Vibrance";
ui_tooltip = "Image: Vibrance";
ui_category = "Shape Coloration";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;
uniform bool enable_gradient <
ui_label = "Enable Gradient";
ui_tooltip = "Enable Gradient";
ui_category = "Shape Gradient";
> = false;
uniform bool gradient_type <
ui_label = "Gradient Type";
ui_tooltip = "Gradient Type";
ui_category = "Shape Gradient";
> = false;
uniform float gradient_curve <
ui_type = "slider";
ui_label = "Gradient Curve";
ui_tooltip = "Gradient Curve";
ui_category = "Shape Gradient";
ui_min = 0.001;
ui_max = 2.0;
> = 0.25;
uniform float intensity_boost <
ui_type = "slider";
ui_label = "Intensity Boost";
ui_tooltip = "Intensity Boost";
ui_category = "Intensity Boost";
ui_min = 1.0;
ui_max = 4.0;
> = 1.0;
uniform int blendmode_1 < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Blendmode";
ui_category = "Shape Blending";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 0;
uniform float opacity <
ui_type = "slider";
ui_label = "Opacity";
ui_tooltip = "Opacity";
ui_category = "Shape Blending";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texMagicRectangle { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerMagicRectangle { Texture = texMagicRectangle; };
//// DEFINES ////////////////////////////////////////////////////////////////////
#define ASPECT_RATIO float( BUFFER_WIDTH * BUFFER_RCP_HEIGHT )
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform bool hasdepth < source = "bufready_depth"; >;
float3 hue( float3 res, float shift, float x )
{
float3 hsl = RGBToHSL( res.xyz );
hsl.x = frac( hsl.x + ( shift + 1.0f ) / 2.0f - 0.5f );
hsl.xyz = HSLToRGB( hsl.xyz );
return lerp( res.xyz, hsl.xyz, x );
}
float curve( float x )
{
return x * x * x * ( x * ( x * 6.0f - 15.0f ) + 10.0f );
}
//// VERTEX SHADER //////////////////////////////////////////////////////////////
/*
Adding texcoord2 in vextex shader which is a rotated texcoord
*/
void PPVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out float2 texcoord2 : TEXCOORD2)
{
PostProcessVS(id, position, texcoord);
float2 uv;
uv.x = ( id == 2 ) ? 2.0 : 0.0;
uv.y = ( id == 1 ) ? 2.0 : 0.0;
uv.xy -= center.xy;
uv.y /= ASPECT_RATIO;
float dim = ceil( sqrt( BUFFER_WIDTH * BUFFER_WIDTH + BUFFER_HEIGHT * BUFFER_HEIGHT )); // Diagonal size
float maxlen = min( BUFFER_WIDTH, BUFFER_HEIGHT );
dim = dim / maxlen; // Scalar
uv.xy /= dim;
float sin = sin( radians( rotation ));
float cos = cos( radians( rotation ));
texcoord2.x = ( uv.x * cos ) + ( uv.y * (-sin));
texcoord2.y = ( uv.x * sin ) + ( uv.y * cos );
texcoord2.xy += float2( 0.5f, 0.5f ); // Transform back
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_Layer_1( float4 pos : SV_Position, float2 texcoord : TEXCOORD, float2 texcoord2 : TEXCOORD2 ) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Depth stuff
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
// Sizing
float dim = ceil( sqrt( BUFFER_WIDTH * BUFFER_WIDTH + BUFFER_HEIGHT * BUFFER_HEIGHT )); // Diagonal size
float maxlen = max( BUFFER_WIDTH, BUFFER_HEIGHT );
dim = dim / maxlen; // Scalar with screen diagonal
float2 uv = texcoord2.xy;
uv.xy = uv.xy * 2.0f - 1.0f; // rescale to -1..0..1 range
uv.xy /= ( float2( ret_size_x + ret_size_x * smoothing, ret_size_y + ret_size_y * smoothing ) * dim ); // scale rectangle
switch( shape )
{
case 0: // square
{ uv.xy = uv.xy; } break;
case 1: // circle
{ uv.xy = lerp( dot( uv.xy, uv.xy ), dot( uv.xy, -uv.xy ), gradient_type ); } break;
}
uv.xy = ( uv.xy + 1.0f ) / 2.0f; // scale back to 0..1 range
// Using smoothstep to create values from 0 to 1, 1 being the drawn shape around center
// First makes bottom and left side, then flips coord to make top and right side: x | 1 - x
// Do some funky stuff with gradients
// Finally make a depth fade
float2 bl = smoothstep( 0.0f, 0.0f + smoothing, uv.xy );
float2 tr = smoothstep( 0.0f, 0.0f + smoothing, 1.0f - uv.xy );
if( enable_gradient )
{
if( gradient_type )
{
bl = smoothstep( 0.0f, 0.0f + smoothing, uv.xy ) * pow( abs( uv.y ), gradient_curve );
}
tr = smoothstep( 0.0f, 0.0f + smoothing, 1.0f - uv.xy ) * pow( abs( uv.x ), gradient_curve );
}
float depthfade = smoothstep( depthpos - depth_smoothing, depthpos + depth_smoothing, depth );
depthfade = lerp( 1.0f, depthfade, hasdepth );
// Combine them all
float R = bl.x * bl.y * tr.x * tr.y * depthfade;
R = ( invert_shape ) ? 1.0f - R : R;
// Blend the borders
float intensity = RGBToHSV( reccolor.xyz ).z;
color.xyz = lerp( color.xyz, saturate( color.xyz * saturate( 1.0f - R ) + R * intensity ), R );
// Add to color, use R for Alpha
return float4( color.xyz, R );
}
float4 PS_Blend(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 orig = tex2D( ReShade::BackBuffer, texcoord );
float3 color;
float4 layer_1 = saturate( tex2D( samplerMagicRectangle, texcoord ));
// Dither
// Input: sampler, texcoord, variance(int), enable_dither(bool), dither_strength(float), motion(bool), swing(float)
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 7, 1, dither_strength, 1, 0.5f );
layer_1.xyz = saturate( layer_1.xyz + dnoise.xyz );
orig.xyz = exposure( orig.xyz, mr_exposure * layer_1.w );
orig.xyz = con( orig.xyz, mr_contrast * layer_1.w );
orig.xyz = bri( orig.xyz, mr_brightness * layer_1.w );
orig.xyz = hue( orig.xyz, mr_hue, layer_1.w );
orig.xyz = sat( orig.xyz, mr_saturation * layer_1.w );
orig.xyz = vib( orig.xyz, mr_vibrance * layer_1.w );
orig.xyz = saturate( orig.xyz );
// Doing some HSL color space conversions to colorize
layer_1.xyz = saturate( layer_1.xyz * intensity_boost );
layer_1.xyz = RGBToHSV( layer_1.xyz );
float2 huesat = RGBToHSV( reccolor.xyz ).xy;
layer_1.xyz = HSVToRGB( float3( huesat.xy, layer_1.z ));
layer_1.xyz = saturate( layer_1.xyz );
// Blend mode with background
color.xyz = blendmode( orig.xyz, layer_1.xyz, blendmode_1, saturate( layer_1.w ) * opacity );
// Output to screen
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_Magical_Rectangle
< ui_tooltip = "The Magical Rectangle\n\n"
"This shader gives you a rectangular shape on your screen that you can manipulate in 3D space.\n"
"It can blend on depth, blur edges, change color, change blending, change shape, and so on.\n"
"It will allow you to manipulate parts of the scene in various ways. Not withstanding; add mist,\n"
"remove mist, change clouds, create backgrounds, draw flares, add contrasts, change hues, etc. in ways\n"
"another shader will not be able to do.\n\n"
"This shader requires access to depth buffer for full functionality!";>
{
pass prod80_pass0
{
VertexShader = PPVS;
PixelShader = PS_Layer_1;
RenderTarget = texMagicRectangle;
}
pass prod80_pass1
{
VertexShader = PPVS;
PixelShader = PS_Blend;
}
}
}

View File

@ -0,0 +1,71 @@
/*
Description : PD80 04 Saturation Limit for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace pd80_satlimit
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float saturation_limit <
ui_type = "slider";
ui_label = "Saturation Limit";
ui_tooltip = "Saturation Limit";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_Satlimit(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float3 color = tex2D( ReShade::BackBuffer, texcoord ).xyz;
color.xyz = RGBToHSL( color.xyz );
color.y = min( color.y, saturation_limit );
color.xyz = HSLToRGB( color.xyz );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_Saturation_Limiter
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_Satlimit;
}
}
}

View File

@ -0,0 +1,683 @@
/*
Description : PD80 04 Selective Color for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits
- Based on the mathematical analysis provided here
http://blog.pkh.me/p/22-understanding-selective-coloring-in-adobe-photoshop.html
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Base_Effects.fxh"
namespace pd80_selectivecolor
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int corr_method < __UNIFORM_COMBO_INT1
ui_label = "Correction Method";
ui_tooltip = "Correction Method";
ui_category = "Selective Color";
ui_items = "Absolute\0Relative\0"; //Do not change order; 0=Absolute, 1=Relative
> = 1;
uniform int corr_method2 < __UNIFORM_COMBO_INT1
ui_label = "Correction Method Saturation";
ui_tooltip = "Correction Method Saturation";
ui_category = "Selective Color";
ui_items = "Absolute\0Relative\0"; //Do not change order; 0=Absolute, 1=Relative
> = 1;
// Reds
uniform float r_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Reds: Cyan";
ui_category = "Selective Color: Reds";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float r_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Reds: Magenta";
ui_category = "Selective Color: Reds";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float r_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Reds: Yellow";
ui_category = "Selective Color: Reds";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float r_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Reds: Black";
ui_category = "Selective Color: Reds";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float r_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Reds: Saturation";
ui_category = "Selective Color: Reds";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float r_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Reds: Vibrance";
ui_category = "Selective Color: Reds";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Yellows
uniform float y_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Yellows: Cyan";
ui_category = "Selective Color: Yellows";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float y_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Yellows: Magenta";
ui_category = "Selective Color: Yellows";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float y_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Yellows: Yellow";
ui_category = "Selective Color: Yellows";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float y_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Yellows: Black";
ui_category = "Selective Color: Yellows";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float y_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Yellows: Saturation";
ui_category = "Selective Color: Yellows";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float y_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Yellows: Vibrance";
ui_category = "Selective Color: Yellows";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Greens
uniform float g_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Greens: Cyan";
ui_category = "Selective Color: Greens";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float g_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Greens: Magenta";
ui_category = "Selective Color: Greens";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float g_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Greens: Yellow";
ui_category = "Selective Color: Greens";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float g_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Greens: Black";
ui_category = "Selective Color: Greens";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float g_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Greens: Saturation";
ui_category = "Selective Color: Greens";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float g_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Greens: Vibrance";
ui_category = "Selective Color: Greens";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Cyans
uniform float c_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Cyans: Cyan";
ui_category = "Selective Color: Cyans";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float c_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Cyans: Magenta";
ui_category = "Selective Color: Cyans";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float c_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Cyans: Yellow";
ui_category = "Selective Color: Cyans";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float c_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Cyans: Black";
ui_category = "Selective Color: Cyans";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float c_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Cyans: Saturation";
ui_category = "Selective Color: Cyans";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float c_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Cyans: Vibrance";
ui_category = "Selective Color: Cyans";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Blues
uniform float b_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Blues: Cyan";
ui_category = "Selective Color: Blues";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float b_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Blues: Magenta";
ui_category = "Selective Color: Blues";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float b_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Blues: Yellow";
ui_category = "Selective Color: Blues";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float b_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Blues: Black";
ui_category = "Selective Color: Blues";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float b_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Blues: Saturation";
ui_category = "Selective Color: Blues";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float b_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Blues: Vibrance";
ui_category = "Selective Color: Blues";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Magentas
uniform float m_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Magentas: Cyan";
ui_category = "Selective Color: Magentas";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float m_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Magentas: Magenta";
ui_category = "Selective Color: Magentas";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float m_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Magentas: Yellow";
ui_category = "Selective Color: Magentas";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float m_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Magentas: Black";
ui_category = "Selective Color: Magentas";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float m_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Magentas: Saturation";
ui_category = "Selective Color: Magentas";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float m_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Magentas: Vibrance";
ui_category = "Selective Color: Magentas";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Whites
uniform float w_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Whites: Cyan";
ui_category = "Selective Color: Whites";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float w_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Whites: Magenta";
ui_category = "Selective Color: Whites";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float w_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Whites: Yellow";
ui_category = "Selective Color: Whites";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float w_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Whites: Black";
ui_category = "Selective Color: Whites";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float w_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Whites: Saturation";
ui_category = "Selective Color: Whites";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float w_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Whites: Vibrance";
ui_category = "Selective Color: Whites";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Neutrals
uniform float n_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Neutrals: Cyan";
ui_category = "Selective Color: Neutrals";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float n_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Neutrals: Magenta";
ui_category = "Selective Color: Neutrals";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float n_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Neutrals: Yellow";
ui_category = "Selective Color: Neutrals";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float n_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Neutrals: Black";
ui_category = "Selective Color: Neutrals";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float n_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Neutrals: Saturation";
ui_category = "Selective Color: Neutrals";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float n_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Neutrals: Vibrance";
ui_category = "Selective Color: Neutrals";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
// Blacks
uniform float bk_adj_cya <
ui_type = "slider";
ui_label = "Cyan";
ui_tooltip = "Selective Color Blacks: Cyan";
ui_category = "Selective Color: Blacks";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float bk_adj_mag <
ui_type = "slider";
ui_label = "Magenta";
ui_tooltip = "Selective Color Blacks: Magenta";
ui_category = "Selective Color: Blacks";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float bk_adj_yel <
ui_type = "slider";
ui_label = "Yellow";
ui_tooltip = "Selective Color Blacks: Yellow";
ui_category = "Selective Color: Blacks";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float bk_adj_bla <
ui_type = "slider";
ui_label = "Black";
ui_tooltip = "Selective Color Blacks: Black";
ui_category = "Selective Color: Blacks";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float bk_adj_sat <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Selective Color Blacks: Saturation";
ui_category = "Selective Color: Blacks";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float bk_adj_vib <
ui_type = "slider";
ui_label = "Vibrance";
ui_tooltip = "Selective Color Blacks: Vibrance";
ui_category = "Selective Color: Blacks";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float mid( float3 c )
{
float sum = c.x + c.y + c.z;
float mn = min( min( c.x, c.y ), c.z );
float mx = max( max( c.x, c.y ), c.z );
return sum - mn - mx;
}
float adjustcolor( float scale, float colorvalue, float adjust, float bk, int method )
{
/*
y(value, adjustment) = clamp((( -1 - adjustment ) * bk - adjustment ) * method, -value, 1 - value ) * scale
absolute: method = 1.0f - colorvalue * 0
relative: method = 1.0f - colorvalue * 1
*/
return clamp((( -1.0f - adjust ) * bk - adjust ) * ( 1.0f - colorvalue * method ), -colorvalue, 1.0f - colorvalue) * scale;
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_SelectiveColor(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Clamp 0..1
color.xyz = saturate( color.xyz );
// Need these a lot
float min_value = min( min( color.x, color.y ), color.z );
float max_value = max( max( color.x, color.y ), color.z );
float mid_value = mid( color.xyz );
// Used for determining which pixels to adjust regardless of prior changes to color
float3 orig = color.xyz;
// Scales
float sRGB = max_value - mid_value;
float sCMY = mid_value - min_value;
float sNeutrals = 1.0f - ( abs( max_value - 0.5f ) + abs( min_value - 0.5f ));
float sWhites = ( min_value - 0.5f ) * 2.0f;
float sBlacks = ( 0.5f - max_value ) * 2.0f;
/*
Create relative saturation levels.
For example when saturating red channel you will manipulate yellow and magenta channels.
So, to ensure there are no bugs and transitions are smooth, need to scale saturation with
relative saturation of nearest colors. If difference between red and green is low ( color nearly yellow )
you use this info to scale back red saturation on those pixels.
This solution is not fool proof, but gives acceptable results almost always.
*/
// Red is when maxvalue = x
float r_d_m = orig.x - orig.z;
float r_d_y = orig.x - orig.y;
// Yellow is when minvalue = z
float y_d = mid_value - orig.z;
// Green is when maxvalue = y
float g_d_y = orig.y - orig.x;
float g_d_c = orig.y - orig.z;
// Cyan is when minvalue = x
float c_d = mid_value - orig.x;
// Blue is when maxvalue = z
float b_d_c = orig.z - orig.y;
float b_d_m = orig.z - orig.x;
// Magenta is when minvalue = y
float m_d = mid_value - orig.y;
float r_delta = 1.0f;
float y_delta = 1.0f;
float g_delta = 1.0f;
float c_delta = 1.0f;
float b_delta = 1.0f;
float m_delta = 1.0f;
if( corr_method2 ) // Relative saturation
{
r_delta = min( r_d_m, r_d_y );
y_delta = y_d;
g_delta = min( g_d_y, g_d_c );
c_delta = c_d;
b_delta = min( b_d_c, b_d_m );
m_delta = m_d;
}
// Selective Color
if( max_value == orig.x )
{
color.x = color.x + adjustcolor( sRGB, color.x, r_adj_cya, r_adj_bla, corr_method );
color.y = color.y + adjustcolor( sRGB, color.y, r_adj_mag, r_adj_bla, corr_method );
color.z = color.z + adjustcolor( sRGB, color.z, r_adj_yel, r_adj_bla, corr_method );
color.xyz = sat( color.xyz, r_adj_sat * r_delta );
color.xyz = vib( color.xyz, r_adj_vib * r_delta );
}
if( min_value == orig.z )
{
color.x = color.x + adjustcolor( sCMY, color.x, y_adj_cya, y_adj_bla, corr_method );
color.y = color.y + adjustcolor( sCMY, color.y, y_adj_mag, y_adj_bla, corr_method );
color.z = color.z + adjustcolor( sCMY, color.z, y_adj_yel, y_adj_bla, corr_method );
color.xyz = sat( color.xyz, y_adj_sat * y_delta );
color.xyz = vib( color.xyz, y_adj_vib * y_delta );
}
if( max_value == orig.y )
{
color.x = color.x + adjustcolor( sRGB, color.x, g_adj_cya, g_adj_bla, corr_method );
color.y = color.y + adjustcolor( sRGB, color.y, g_adj_mag, g_adj_bla, corr_method );
color.z = color.z + adjustcolor( sRGB, color.z, g_adj_yel, g_adj_bla, corr_method );
color.xyz = sat( color.xyz, g_adj_sat * g_delta );
color.xyz = vib( color.xyz, g_adj_vib * g_delta );
}
if( min_value == orig.x )
{
color.x = color.x + adjustcolor( sCMY, color.x, c_adj_cya, c_adj_bla, corr_method );
color.y = color.y + adjustcolor( sCMY, color.y, c_adj_mag, c_adj_bla, corr_method );
color.z = color.z + adjustcolor( sCMY, color.z, c_adj_yel, c_adj_bla, corr_method );
color.xyz = sat( color.xyz, c_adj_sat * c_delta );
color.xyz = vib( color.xyz, c_adj_vib * c_delta );
}
if( max_value == orig.z )
{
color.x = color.x + adjustcolor( sRGB, color.x, b_adj_cya, b_adj_bla, corr_method );
color.y = color.y + adjustcolor( sRGB, color.y, b_adj_mag, b_adj_bla, corr_method );
color.z = color.z + adjustcolor( sRGB, color.z, b_adj_yel, b_adj_bla, corr_method );
color.xyz = sat( color.xyz, b_adj_sat * b_delta );
color.xyz = vib( color.xyz, b_adj_vib * b_delta );
}
if( min_value == orig.y )
{
color.x = color.x + adjustcolor( sCMY, color.x, m_adj_cya, m_adj_bla, corr_method );
color.y = color.y + adjustcolor( sCMY, color.y, m_adj_mag, m_adj_bla, corr_method );
color.z = color.z + adjustcolor( sCMY, color.z, m_adj_yel, m_adj_bla, corr_method );
color.xyz = sat( color.xyz, m_adj_sat * m_delta );
color.xyz = vib( color.xyz, m_adj_vib * m_delta );
}
if( min_value >= 0.5f )
{
color.x = color.x + adjustcolor( sWhites, color.x, w_adj_cya, w_adj_bla, corr_method );
color.y = color.y + adjustcolor( sWhites, color.y, w_adj_mag, w_adj_bla, corr_method );
color.z = color.z + adjustcolor( sWhites, color.z, w_adj_yel, w_adj_bla, corr_method );
color.xyz = sat( color.xyz, w_adj_sat * smoothstep( 0.5f, 1.0f, min_value ));
color.xyz = vib( color.xyz, w_adj_vib * smoothstep( 0.5f, 1.0f, min_value ));
}
if( max_value > 0.0f && min_value < 1.0f )
{
color.x = color.x + adjustcolor( sNeutrals, color.x, n_adj_cya, n_adj_bla, corr_method );
color.y = color.y + adjustcolor( sNeutrals, color.y, n_adj_mag, n_adj_bla, corr_method );
color.z = color.z + adjustcolor( sNeutrals, color.z, n_adj_yel, n_adj_bla, corr_method );
color.xyz = sat( color.xyz, n_adj_sat );
color.xyz = vib( color.xyz, n_adj_vib );
}
if( max_value < 0.5f )
{
color.x = color.x + adjustcolor( sBlacks, color.x, bk_adj_cya, bk_adj_bla, corr_method );
color.y = color.y + adjustcolor( sBlacks, color.y, bk_adj_mag, bk_adj_bla, corr_method );
color.z = color.z + adjustcolor( sBlacks, color.z, bk_adj_yel, bk_adj_bla, corr_method );
color.xyz = sat( color.xyz, bk_adj_sat * smoothstep( 0.5f, 0.0f, max_value ));
color.xyz = vib( color.xyz, bk_adj_vib * smoothstep( 0.5f, 0.0f, max_value ));
}
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_SelectiveColor
{
pass prod80_sc
{
VertexShader = PostProcessVS;
PixelShader = PS_SelectiveColor;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
/*
Description : PD80 04 Technicolor for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits
- Using Hue Shift algorythm from Vibhore Tanwer (stockexchange)
No particular reason, just found it interesting
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_technicolor
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float3 Red2strip <
ui_type = "color";
ui_label = "Red Dye Color";
ui_tooltip = "Red Color used to create Cyan (contemporary)";
ui_category = "Technicolor 2 strip";
> = float3(1.0, 0.098, 0.0);
uniform float3 Cyan2strip <
ui_type = "color";
ui_label = "Cyan Dye Color";
ui_tooltip = "Cyan Color used to create Red (contemporary)";
ui_category = "Technicolor 2 strip";
> = float3(0.0, 0.988, 1.0);
uniform float3 colorKey <
ui_type = "color";
ui_label = "Funky Color Adjustment";
ui_tooltip = "3rd Layer for Fun, lower values increase contrast";
ui_category = "Technicolor 2 strip";
> = float3(1.0, 1.0, 1.0);
uniform float Saturation2 <
ui_min = 1.0;
ui_max = 2.0;
ui_type = "slider";
ui_label = "Saturation Adjustment";
ui_tooltip = "Additional saturation control as 2 Strip Process is not very saturated by itself";
ui_category = "Technicolor 2 strip";
> = 1.5;
uniform bool enable3strip <
ui_label = "Enable Technicolor 3 strip";
ui_tooltip = "Enable Technicolor 3 strip";
ui_category = "Technicolor 3 strip";
> = false;
uniform float3 ColorStrength <
ui_type = "color";
ui_tooltip = "Higher means darker and more intense colors.";
ui_category = "Technicolor 3 strip";
> = float3(0.2, 0.2, 0.2);
uniform float Brightness <
ui_type = "slider";
ui_label = "Brightness Adjustment";
ui_min = 0.5;
ui_max = 1.5;
ui_tooltip = "Higher means brighter image.";
ui_category = "Technicolor 3 strip";
> = 1.0;
uniform float Saturation <
ui_type = "slider";
ui_label = "Saturation Adjustment";
ui_min = 0.0;
ui_max = 1.5;
ui_tooltip = "Additional saturation control since this effect tends to oversaturate the image.";
ui_category = "Technicolor 3 strip";
> = 1.0;
uniform float Strength <
ui_type = "slider";
ui_label = "Effect Strength";
ui_min = 0.0;
ui_max = 1.0;
ui_tooltip = "Adjust the strength of the effect.";
ui_category = "Technicolor 3 strip";
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, float3( 0.212656f, 0.715158f, 0.072186f ));
}
// Code from Vibhore Tanwer
float3x3 QuaternionToMatrix( float4 quat )
{
float3 cross = quat.yzx * quat.zxy;
float3 square= quat.xyz * quat.xyz;
float3 wimag = quat.w * quat.xyz;
square = square.xyz + square.yzx;
float3 diag = 0.5f - square;
float3 a = (cross + wimag);
float3 b = (cross - wimag);
return float3x3(
2.0f * float3(diag.x, b.z, a.y),
2.0f * float3(a.z, diag.y, b.x),
2.0f * float3(b.y, a.x, diag.z));
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_Technicolor(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
color.xyz = saturate( color.xyz );
float3 root3 = 0.57735f;
float3 keyC = 0.0f;
float half_angle = 0.0f;
float4 rot_quat = 0.0f;
float3x3 rot_Mat;
float HueAdj = 0.52f; //0.5 is too strong in reds and doesn't work well with skin color
float3 orig = color.xyz;
float negR = 1.0f - color.x;
float negG = 1.0f - color.y;
float3 newR = 1.0f - negR * Cyan2strip;
float3 newC = 1.0f - negG * Red2strip;
half_angle = 0.5f * radians( 180.0f ); // Hue is radians of 0 to 360 degrees
rot_quat = float4(( root3 * sin( half_angle )), cos( half_angle ));
rot_Mat = QuaternionToMatrix( rot_quat );
float3 key = colorKey.xyz;
key.xyz = mul( rot_Mat, key.xyz );
key.xyz = max( color.yyy, key.xyz );
color.xyz = newR.xyz * newC.xyz * key.xyz; // 2 strip image
// Fix hue
half_angle = 0.5f * radians( HueAdj * 360.0f ); // Hue is radians of 0 to 360 degrees
rot_quat = float4(( root3 * sin( half_angle )), cos( half_angle ));
rot_Mat = QuaternionToMatrix( rot_quat );
color.xyz = mul( rot_Mat, color.xyz );
// Add saturation to taste
color.xyz = lerp( getLuminance( color.xyz ), color.xyz, Saturation2 );
if( enable3strip ) {
float3 temp = 1.0 - orig.xyz;
float3 target = temp.grg;
float3 target2 = temp.bbr;
float3 temp2 = orig.xyz * target.xyz;
temp2.xyz *= target2.xyz;
temp.xyz = temp2.xyz * ColorStrength;
temp2.xyz *= Brightness;
target.xyz = temp.yxy;
target2.xyz = temp.zzx;
temp.xyz = orig.xyz - target.xyz;
temp.xyz += temp2.xyz;
temp2.xyz = temp.xyz - target2.xyz;
color.xyz = lerp( orig.xyz, temp2.xyz, Strength );
color.xyz = lerp( getLuminance( color.xyz ), color.xyz, Saturation);
}
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_Technicolor
{
pass prod80_TC
{
VertexShader = PostProcessVS;
PixelShader = PS_Technicolor;
}
}
}

View File

@ -0,0 +1,276 @@
/*
Description : PD80 05 Sharpening for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_lumasharpen
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enableShowEdges <
ui_label = "Show only Sharpening Texture";
ui_tooltip = "Show only Sharpening Texture";
ui_category = "Sharpening";
> = false;
uniform float BlurSigma <
ui_label = "Sharpening Width";
ui_tooltip = "Sharpening Width";
ui_category = "Sharpening";
ui_type = "slider";
ui_min = 0.3;
ui_max = 1.2;
> = 0.45;
uniform float Sharpening <
ui_label = "Sharpening Strength";
ui_tooltip = "Sharpening Strength";
ui_category = "Sharpening";
ui_type = "slider";
ui_min = 0.0;
ui_max = 5.0;
> = 1.7;
uniform float Threshold <
ui_label = "Sharpening Threshold";
ui_tooltip = "Sharpening Threshold";
ui_category = "Sharpening";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float limiter <
ui_label = "Sharpening Highlight Limiter";
ui_tooltip = "Sharpening Highlight Limiter";
ui_category = "Sharpening";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.03;
uniform bool enable_depth <
ui_label = "Enable depth based adjustments.\nMake sure you have setup your depth buffer correctly.";
ui_tooltip = "Enable depth based adjustments";
ui_category = "Sharpening: Depth";
> = false;
uniform bool enable_reverse <
ui_label = "Reverses the effect (sharpen close, or sharpen far)";
ui_tooltip = "Reverses the effect";
ui_category = "Sharpening: Depth";
> = false;
uniform bool display_depth <
ui_label = "Show depth texture";
ui_tooltip = "Show depth texture";
ui_category = "Sharpening: Depth";
> = false;
uniform float depthStart <
ui_type = "slider";
ui_label = "Change Depth Start Plane";
ui_tooltip = "Change Depth Start Plane";
ui_category = "Sharpening: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.0;
uniform float depthEnd <
ui_type = "slider";
ui_label = "Change Depth End Plane";
ui_tooltip = "Change Depth End Plane";
ui_category = "Sharpening: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.1;
uniform float depthCurve <
ui_label = "Depth Curve Adjustment";
ui_tooltip = "Depth Curve Adjustment";
ui_category = "Sharpening: Depth";
ui_type = "slider";
ui_min = 0.05;
ui_max = 8.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texGaussianH { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture texGaussian { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerGaussianH { Texture = texGaussianH; };
sampler samplerGaussian { Texture = texGaussian; };
//// DEFINES ////////////////////////////////////////////////////////////////////
#define PI 3.141592f
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float getLuminance( in float3 x )
{
return dot( x, float3( 0.212656, 0.715158, 0.072186 ));
}
float getAvgColor( float3 col )
{
return dot( col.xyz, float3( 0.333333f, 0.333334f, 0.333333f ));
}
// nVidia blend modes
// Source: https://www.khronos.org/registry/OpenGL/extensions/NV/NV_blend_equation_advanced.txt
float3 ClipColor( float3 color )
{
float lum = getAvgColor( color.xyz );
float mincol = min( min( color.x, color.y ), color.z );
float maxcol = max( max( color.x, color.y ), color.z );
color.xyz = ( mincol < 0.0f ) ? lum + (( color.xyz - lum ) * lum ) / ( lum - mincol ) : color.xyz;
color.xyz = ( maxcol > 1.0f ) ? lum + (( color.xyz - lum ) * ( 1.0f - lum )) / ( maxcol - lum ) : color.xyz;
return color;
}
// Luminosity: base, blend
// Color: blend, base
float3 blendLuma( float3 base, float3 blend )
{
float lumbase = getAvgColor( base.xyz );
float lumblend = getAvgColor( blend.xyz );
float ldiff = lumblend - lumbase;
float3 col = base.xyz + ldiff;
return ClipColor( col.xyz );
}
float3 screen(float3 c, float3 b) { return 1.0f-(1.0f-c)*(1.0f-b);}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_GaussianH(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float px = BUFFER_RCP_WIDTH;
float SigmaSum = 0.0f;
float pxlOffset = 1.0f;
float loops = max( BUFFER_WIDTH, BUFFER_HEIGHT ) / 1920.0f * 4.0f;
//Gaussian Math
float3 Sigma;
float bSigma = BlurSigma * ( max( BUFFER_WIDTH, BUFFER_HEIGHT ) / 1920.0f ); // Scalar
Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
//Center Weight
color.xyz *= Sigma.x;
//Adding to total sum of distributed weights
SigmaSum += Sigma.x;
//Setup next weight
Sigma.xy *= Sigma.yz;
[loop]
for( int i = 0; i < loops; ++i )
{
color += tex2Dlod( ReShade::BackBuffer, float4( texcoord.xy + float2( pxlOffset*px, 0.0f ), 0.0, 0.0 )) * Sigma.x;
color += tex2Dlod( ReShade::BackBuffer, float4( texcoord.xy - float2( pxlOffset*px, 0.0f ), 0.0, 0.0 )) * Sigma.x;
SigmaSum += ( 2.0f * Sigma.x );
pxlOffset += 1.0f;
Sigma.xy *= Sigma.yz;
}
color.xyz /= SigmaSum;
return float4( color.xyz, 1.0f );
}
float4 PS_GaussianV(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerGaussianH, texcoord );
float py = BUFFER_RCP_HEIGHT;
float SigmaSum = 0.0f;
float pxlOffset = 1.0f;
float loops = max( BUFFER_WIDTH, BUFFER_HEIGHT ) / 1920.0f * 4.0f;
//Gaussian Math
float3 Sigma;
float bSigma = BlurSigma * ( max( BUFFER_WIDTH, BUFFER_HEIGHT ) / 1920.0f ); // Scalar
Sigma.x = 1.0f / ( sqrt( 2.0f * PI ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
//Center Weight
color.xyz *= Sigma.x;
//Adding to total sum of distributed weights
SigmaSum += Sigma.x;
//Setup next weight
Sigma.xy *= Sigma.yz;
[loop]
for( int i = 0; i < loops; ++i )
{
color += tex2Dlod( samplerGaussianH, float4( texcoord.xy + float2( 0.0f, pxlOffset*py ), 0.0, 0.0 )) * Sigma.x;
color += tex2Dlod( samplerGaussianH, float4( texcoord.xy - float2( 0.0f, pxlOffset*py ), 0.0, 0.0 )) * Sigma.x;
SigmaSum += ( 2.0f * Sigma.x );
pxlOffset += 1.0f;
Sigma.xy *= Sigma.yz;
}
color.xyz /= SigmaSum;
return float4( color.xyz, 1.0f );
}
float4 PS_LumaSharpen(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 orig = tex2D( ReShade::BackBuffer, texcoord );
float4 gaussian = tex2D( samplerGaussian, texcoord );
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
depth = smoothstep( depthStart, depthEnd, depth );
depth = pow( depth, depthCurve );
depth = enable_reverse ? 1.0f - depth : depth;
float3 edges = max( saturate( orig.xyz - gaussian.xyz ) - Threshold, 0.0f );
float3 invGauss = saturate( 1.0f - gaussian.xyz );
float3 oInvGauss = saturate( orig.xyz + invGauss.xyz );
float3 invOGauss = max( saturate( 1.0f - oInvGauss.xyz ) - Threshold, 0.0f );
edges = max(( saturate( Sharpening * edges.xyz )) - ( saturate( Sharpening * invOGauss.xyz )), 0.0f );
float3 blend = screen( orig.xyz, lerp( min( edges.xyz, limiter ), 0.0f, enable_depth * depth ));
float3 color = blendLuma( orig.xyz, blend.xyz );
color.xyz = enableShowEdges ? lerp( min( edges.xyz, limiter ), min( edges.xyz, limiter ) * depth, enable_depth ) : color.xyz;
color.xyz = display_depth ? depth.xxx : color.xyz;
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_05_LumaSharpen
{
pass GaussianH
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianH;
RenderTarget = texGaussianH;
}
pass GaussianV
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianV;
RenderTarget = texGaussian;
}
pass LumaSharpen
{
VertexShader = PostProcessVS;
PixelShader = PS_LumaSharpen;
}
}
}

View File

@ -0,0 +1,306 @@
/*
Description : PD80 06 Chromatic Aberration for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#if __RENDERER__ == 0x9000
#ifndef CA_sampleSTEPS
#define CA_sampleSTEPS 24 // [0 to 96]
#endif
#define CA_DX9_MODE 1
#else
#define CA_DX9_MODE 0
#endif
namespace pd80_ca
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int CA_type < __UNIFORM_COMBO_INT1
ui_label = "Chromatic Aberration Type";
ui_tooltip = "Chromatic Aberration Type";
ui_category = "Chromatic Aberration";
ui_items = "Center Weighted Radial\0Center Weighted Longitudinal\0Full screen Radial\0Full screen Longitudinal\0";
> = 0;
uniform int degrees <
ui_type = "slider";
ui_label = "CA Rotation Offset";
ui_tooltip = "CA Rotation Offset";
ui_category = "Chromatic Aberration";
ui_min = 0;
ui_max = 360;
ui_step = 1;
> = 135;
uniform float CA <
ui_type = "slider";
ui_label = "CA Global Width";
ui_tooltip = "CA Global Width";
ui_category = "Chromatic Aberration";
ui_min = -150.0f;
ui_max = 150.0f;
> = -12.0;
#if CA_DX9_MODE == 0
uniform int sampleSTEPS <
ui_type = "slider";
ui_label = "Number of Hues";
ui_tooltip = "Number of Hues";
ui_category = "Chromatic Aberration";
ui_min = 8;
ui_max = 96;
ui_step = 1;
> = 24;
#endif
uniform float CA_strength <
ui_type = "slider";
ui_label = "CA Effect Strength";
ui_tooltip = "CA Effect Strength";
ui_category = "Chromatic Aberration";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform bool show_CA <
ui_label = "CA Show Center / Vignette";
ui_tooltip = "CA Show Center / Vignette";
ui_category = "CA: Center Weighted";
> = false;
uniform float3 vignetteColor <
ui_type = "color";
ui_label = "Vignette Color";
ui_tooltip = "Vignette Color";
ui_category = "CA: Center Weighted";
> = float3(0.0, 0.0, 0.0);
uniform float CA_width <
ui_type = "slider";
ui_label = "CA Width";
ui_tooltip = "CA Width";
ui_category = "CA: Center Weighted";
ui_min = 0.0f;
ui_max = 5.0f;
> = 1.0;
uniform float CA_curve <
ui_type = "slider";
ui_label = "CA Curve";
ui_tooltip = "CA Curve";
ui_category = "CA: Center Weighted";
ui_min = 0.1f;
ui_max = 12.0f;
> = 1.0;
uniform float oX <
ui_type = "slider";
ui_label = "CA Center (X)";
ui_tooltip = "CA Center (X)";
ui_category = "CA: Center Weighted";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float oY <
ui_type = "slider";
ui_label = "CA Center (Y)";
ui_tooltip = "CA Center (Y)";
ui_category = "CA: Center Weighted";
ui_min = -1.0f;
ui_max = 1.0f;
> = 0.0;
uniform float CA_shapeX <
ui_type = "slider";
ui_label = "CA Shape (X)";
ui_tooltip = "CA Shape (X)";
ui_category = "CA: Center Weighted";
ui_min = 0.2f;
ui_max = 6.0f;
> = 1.0;
uniform float CA_shapeY <
ui_type = "slider";
ui_label = "CA Shape (Y)";
ui_tooltip = "CA Shape (Y)";
ui_category = "CA: Center Weighted";
ui_min = 0.2f;
ui_max = 6.0f;
> = 1.0;
uniform bool enable_depth_int <
ui_label = "Intensity: Enable depth based adjustments.\nMake sure you have setup your depth buffer correctly.";
ui_tooltip = "Intensity: Enable depth based adjustments";
ui_category = "Final Adjustments: Depth";
> = false;
uniform bool enable_depth_width <
ui_label = "Width: Enable depth based adjustments.\nMake sure you have setup your depth buffer correctly.";
ui_tooltip = "Width: Enable depth based adjustments";
ui_category = "Final Adjustments: Depth";
> = false;
uniform bool display_depth <
ui_label = "Show depth texture";
ui_tooltip = "Show depth texture";
ui_category = "Final Adjustments: Depth";
> = false;
uniform float depthStart <
ui_type = "slider";
ui_label = "Change Depth Start Plane";
ui_tooltip = "Change Depth Start Plane";
ui_category = "Final Adjustments: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.0;
uniform float depthEnd <
ui_type = "slider";
ui_label = "Change Depth End Plane";
ui_tooltip = "Change Depth End Plane";
ui_category = "Final Adjustments: Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.1;
uniform float depthCurve <
ui_label = "Depth Curve Adjustment";
ui_tooltip = "Depth Curve Adjustment";
ui_category = "Final Adjustments: Depth";
ui_type = "slider";
ui_min = 0.05;
ui_max = 8.0;
> = 1.0;
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float3 HUEToRGB( float H )
{
return saturate( float3( abs( H * 6.0f - 3.0f ) - 1.0f,
2.0f - abs( H * 6.0f - 2.0f ),
2.0f - abs( H * 6.0f - 4.0f )));
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_CA(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = 0.0f;
float px = BUFFER_RCP_WIDTH;
float py = BUFFER_RCP_HEIGHT;
float aspect = float( BUFFER_WIDTH * BUFFER_RCP_HEIGHT );
float3 orig = tex2D( ReShade::BackBuffer, texcoord ).xyz;
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
depth = smoothstep( depthStart, depthEnd, depth );
depth = pow( depth, depthCurve );
float CA_width_n = CA_width;
if( enable_depth_width )
CA_width_n *= depth;
//float2 coords = clamp( texcoord.xy * 2.0f - float2( oX + 1.0f, oY + 1.0f ), -1.0f, 1.0f );
float2 coords = texcoord.xy * 2.0f - float2( oX + 1.0f, oY + 1.0f ); // Let it ripp, and not clamp!
float2 uv = coords.xy;
coords.xy /= float2( CA_shapeX / aspect, CA_shapeY );
float2 caintensity= length( coords.xy ) * CA_width_n;
caintensity.y = caintensity.x * caintensity.x + 1.0f;
caintensity.x = 1.0f - ( 1.0f / ( caintensity.y * caintensity.y ));
caintensity.x = pow( caintensity.x, CA_curve );
int degreesY = degrees;
float c = 0.0f;
float s = 0.0f;
switch( CA_type )
{
// Radial: Y + 90 w/ multiplying with uv.xy
case 0:
{
degreesY = degrees + 90 > 360 ? degreesY = degrees + 90 - 360 : degrees + 90;
c = cos( radians( degrees )) * uv.x;
s = sin( radians( degreesY )) * uv.y;
}
break;
// Longitudinal: X = Y w/o multiplying with uv.xy
case 1:
{
c = cos( radians( degrees ));
s = sin( radians( degreesY ));
}
break;
// Full screen Radial
case 2:
{
degreesY = degrees + 90 > 360 ? degreesY = degrees + 90 - 360 : degrees + 90;
caintensity.x = 1.0f;
c = cos( radians( degrees )) * uv.x;
s = sin( radians( degreesY )) * uv.y;
}
break;
// Full screen Longitudinal
case 3:
{
caintensity.x = 1.0f;
c = cos( radians( degrees ));
s = sin( radians( degreesY ));
}
break;
}
//Apply based on scene depth
if( enable_depth_int )
caintensity.x *= depth;
float3 huecolor = 0.0f;
float3 temp = 0.0f;
#if CA_DX9_MODE == 1
float o1 = CA_sampleSTEPS - 1.0f;
#else
float o1 = sampleSTEPS - 1.0f;
#endif
float o2 = 0.0f;
float3 d = 0.0f;
// Scale CA (hackjob!)
float caWidth = CA * ( max( BUFFER_WIDTH, BUFFER_HEIGHT ) / 1920.0f ); // Scaled for 1920, raising resolution in X or Y should raise scale
float offsetX = px * c * caintensity.x;
float offsetY = py * s * caintensity.x;
#if CA_DX9_MODE == 1
float sampst = CA_sampleSTEPS;
for( float i = 0; i < CA_sampleSTEPS; i++ )
#else
float sampst = sampleSTEPS;
for( float i = 0; i < sampleSTEPS; i++ )
#endif
{
huecolor.xyz = HUEToRGB( i / sampst );
o2 = lerp( -caWidth, caWidth, i / o1 );
temp.xyz = tex2D( ReShade::BackBuffer, texcoord.xy + float2( o2 * offsetX, o2 * offsetY )).xyz;
color.xyz += temp.xyz * huecolor.xyz;
d.xyz += huecolor.xyz;
}
//color.xyz /= ( sampleSTEPS / 3.0f * 2.0f ); // Too crude and doesn't work with low sampleSTEPS ( too dim )
color.xyz /= dot( d.xyz, 0.333333f ); // seems so-so OK
color.xyz = lerp( orig.xyz, color.xyz, CA_strength );
color.xyz = lerp( color.xyz, vignetteColor.xyz * caintensity.x + ( 1.0f - caintensity.x ) * color.xyz, show_CA );
color.xyz = display_depth ? depth.xxx : color.xyz;
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_06_ChromaticAberration
{
pass prod80_CA
{
VertexShader = PostProcessVS;
PixelShader = PS_CA;
}
}
}

View File

@ -0,0 +1,149 @@
/*
Description : PD80 04 Magical Rectangle for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Blend_Modes.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace pd80_depthslicer
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float depth_near <
ui_type = "slider";
ui_label = "Depth Near Plane";
ui_tooltip = "Depth Near Plane";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float depthpos <
ui_type = "slider";
ui_label = "Depth Position";
ui_tooltip = "Depth Position";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.015;
uniform float depth_far <
ui_type = "slider";
ui_label = "Depth Far Plane";
ui_tooltip = "Depth Far Plane";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float depth_smoothing <
ui_type = "slider";
ui_label = "Depth Smoothing";
ui_tooltip = "Depth Smoothing";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.005;
uniform float intensity <
ui_type = "slider";
ui_label = "Lightness";
ui_tooltip = "Lightness";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform float hue <
ui_type = "slider";
ui_label = "Hue";
ui_tooltip = "Hue";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.083;
uniform float saturation <
ui_type = "slider";
ui_label = "Saturation";
ui_tooltip = "Saturation";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
uniform int blendmode_1 < __UNIFORM_COMBO_INT1
ui_label = "Blendmode";
ui_tooltip = "Blendmode";
ui_category = "Depth Slicer";
ui_items = "Default\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0Hardmix\0Reflect\0Glow\0Hue\0Saturation\0Color\0Luminosity\0";
> = 0;
uniform float opacity <
ui_type = "slider";
ui_label = "Opacity";
ui_tooltip = "Opacity";
ui_category = "Depth Slicer";
ui_min = 0.0;
ui_max = 1.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
//// SAMPLERS ///////////////////////////////////////////////////////////////////
//// DEFINES ////////////////////////////////////////////////////////////////////
//// FUNCTIONS //////////////////////////////////////////////////////////////////
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_DepthSlice(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
float depth_np = depthpos - depth_near;
float depth_fp = depthpos + depth_far;
float dn = smoothstep( depth_np - depth_smoothing, depth_np, depth );
float df = 1.0f - smoothstep( depth_fp, depth_fp + depth_smoothing, depth );
float colorize = 1.0f - ( dn * df );
float a = colorize;
colorize *= intensity;
float3 b = HSVToRGB( float3( hue, saturation, colorize ));
color.xyz = blendmode( color.xyz, b.xyz, blendmode_1, opacity * a );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_06_Depth_Slicer
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_DepthSlice;
}
}
}

View File

@ -0,0 +1,474 @@
/*
Description : PD80 06 Film Grain for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits
- Noise/Grain code adopted, modified, and adjusted from Stefan Gustavson.
License: MIT, Copyright (c) 2011 stegu
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Color_Spaces.fxh"
#ifndef FG_GRAIN_SMOOTHING
#define FG_GRAIN_SMOOTHING 0
#endif
namespace pd80_filmgrain
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform bool enable_test <
ui_label = "Enable Setup Mode";
ui_tooltip = "Enable Setup Mode";
ui_category = "Film Grain (simplex)";
> = false;
uniform int grainMotion < __UNIFORM_COMBO_INT1
ui_label = "Grain Motion";
ui_tooltip = "Grain Motion";
ui_category = "Film Grain (simplex)";
ui_items = "Disabled\0Enabled\0";
> = 1;
uniform float grainAdjust <
ui_type = "slider";
ui_label = "Grain Pattern Adjust (for still noise)";
ui_tooltip = "Grain Pattern Adjust (for still noise)";
ui_category = "Film Grain (simplex)";
ui_min = 1.0f;
ui_max = 2.0f;
> = 1.0;
uniform int grainSize <
ui_type = "slider";
ui_label = "Grain Size";
ui_tooltip = "Grain Size";
ui_category = "Film Grain (simplex)";
ui_min = 1;
ui_max = 4;
> = 1;
#if( FG_GRAIN_SMOOTHING )
uniform float grainBlur <
ui_type = "slider";
ui_label = "Grain Smoothness";
ui_tooltip = "Grain Smoothness";
ui_category = "Film Grain (simplex)";
ui_min = 0.005f;
ui_max = 0.7f;
> = 0.5;
#endif
uniform int grainOrigColor < __UNIFORM_COMBO_INT1
ui_label = "Use Original Color";
ui_tooltip = "Use Original Color";
ui_category = "Film Grain (simplex)";
ui_items = "Use Random Color\0Use Original Color\0";
> = 1;
uniform bool use_negnoise <
ui_label = "Use Negative Noise (highlights)";
ui_tooltip = "Use Negative Noise (highlights)";
ui_category = "Film Grain (simplex)";
> = false;
uniform float grainColor <
ui_type = "slider";
ui_label = "Grain Color Amount";
ui_tooltip = "Grain Color Amount";
ui_category = "Film Grain (simplex)";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform float grainAmount <
ui_type = "slider";
ui_label = "Grain Amount";
ui_tooltip = "Grain Amount";
ui_category = "Film Grain (simplex)";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.333;
uniform float grainIntensity <
ui_type = "slider";
ui_label = "Grain Intensity";
ui_tooltip = "Grain Intensity";
ui_category = "Film Grain (simplex)";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.65;
uniform float grainDensity <
ui_type = "slider";
ui_label = "Grain Density";
ui_tooltip = "Grain Density";
ui_category = "Film Grain (simplex)";
ui_min = 0.0f;
ui_max = 10.0f;
> = 10.0;
uniform float grainIntHigh <
ui_type = "slider";
ui_label = "Grain Intensity Highlights";
ui_tooltip = "Grain Intensity Highlights";
ui_category = "Film Grain (simplex)";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform float grainIntLow <
ui_type = "slider";
ui_label = "Grain Intensity Shadows";
ui_tooltip = "Grain Intensity Shadows";
ui_category = "Film Grain (simplex)";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform bool enable_depth <
ui_label = "Enable depth based adjustments.\nMake sure you have setup your depth buffer correctly.";
ui_tooltip = "Enable depth based adjustments";
ui_category = "Film Grain (simplex): Depth";
> = false;
uniform bool display_depth <
ui_label = "Show depth texture";
ui_tooltip = "Show depth texture";
ui_category = "Film Grain (simplex): Depth";
> = false;
uniform float depthStart <
ui_type = "slider";
ui_label = "Change Depth Start Plane";
ui_tooltip = "Change Depth Start Plane";
ui_category = "Film Grain (simplex): Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.0;
uniform float depthEnd <
ui_type = "slider";
ui_label = "Change Depth End Plane";
ui_tooltip = "Change Depth End Plane";
ui_category = "Film Grain (simplex): Depth";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.1;
uniform float depthCurve <
ui_label = "Depth Curve Adjustment";
ui_tooltip = "Depth Curve Adjustment";
ui_category = "Film Grain (simplex): Depth";
ui_type = "slider";
ui_min = 0.05;
ui_max = 8.0;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texPerm < source = "pd80_permtexture.png"; > { Width = 256; Height = 256; Format = RGBA8; };
texture texNoise { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
#if( FG_GRAIN_SMOOTHING )
texture texNoiseH { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
texture texNoiseV { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; };
#endif
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerPermTex { Texture = texPerm; };
sampler samplerNoise { Texture = texNoise; };
#if( FG_GRAIN_SMOOTHING )
sampler samplerNoiseH { Texture = texNoiseH; };
sampler samplerNoiseV { Texture = texNoiseV; };
#endif
//// DEFINES ////////////////////////////////////////////////////////////////////
#define permTexSize 256
#define permONE 1.0f / 256.0f
#define permHALF 0.5f * permONE
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float Timer < source = "timer"; >;
float4 rnm( float2 tc, float t )
{
float noise = sin( dot( tc, float2( 12.9898, 78.233 ))) * ( 43758.5453 + t );
float noiseR = frac( noise * grainAdjust ) * 2.0 - 1.0;
float noiseG = frac( noise * 1.2154 * grainAdjust ) * 2.0 - 1.0;
float noiseB = frac( noise * 1.3453 * grainAdjust ) * 2.0 - 1.0;
float noiseA = frac( noise * 1.3647 * grainAdjust ) * 2.0 - 1.0;
return float4( noiseR, noiseG, noiseB, noiseA );
}
float fade( float t )
{
return t * t * t * ( t * ( t * 6.0 - 15.0 ) + 10.0 );
}
float curve( float x )
{
return x * x * ( 3.0 - 2.0 * x );
}
float pnoise3D( float3 p, float t )
{
float3 pi = permONE * floor( p ) + permHALF;
pi.xy *= permTexSize;
pi.xy = round(( pi.xy - permHALF ) / grainSize ) * grainSize;
pi.xy /= permTexSize;
float3 pf = frac( p );
// Noise contributions from (x=0, y=0), z=0 and z=1
float perm00 = rnm( pi.xy, t ).x;
float3 grad000 = tex2D( samplerPermTex, float2( perm00, pi.z )).xyz * 4.0 - 1.0;
float n000 = dot( grad000, pf );
float3 grad001 = tex2D( samplerPermTex, float2( perm00, pi.z + permONE )).xyz * 4.0 - 1.0;
float n001 = dot( grad001, pf - float3( 0.0, 0.0, 1.0 ));
// Noise contributions from (x=0, y=1), z=0 and z=1
float perm01 = rnm( pi.xy + float2( 0.0, permONE ), t ).y ;
float3 grad010 = tex2D( samplerPermTex, float2( perm01, pi.z )).xyz * 4.0 - 1.0;
float n010 = dot( grad010, pf - float3( 0.0, 1.0, 0.0 ));
float3 grad011 = tex2D( samplerPermTex, float2( perm01, pi.z + permONE )).xyz * 4.0 - 1.0;
float n011 = dot( grad011, pf - float3( 0.0, 1.0, 1.0 ));
// Noise contributions from (x=1, y=0), z=0 and z=1
float perm10 = rnm( pi.xy + float2( permONE, 0.0 ), t ).z ;
float3 grad100 = tex2D( samplerPermTex, float2( perm10, pi.z )).xyz * 4.0 - 1.0;
float n100 = dot( grad100, pf - float3( 1.0, 0.0, 0.0 ));
float3 grad101 = tex2D( samplerPermTex, float2( perm10, pi.z + permONE )).xyz * 4.0 - 1.0;
float n101 = dot( grad101, pf - float3( 1.0, 0.0, 1.0 ));
// Noise contributions from (x=1, y=1), z=0 and z=1
float perm11 = rnm( pi.xy + float2( permONE, permONE ), t ).w ;
float3 grad110 = tex2D( samplerPermTex, float2( perm11, pi.z )).xyz * 4.0 - 1.0;
float n110 = dot( grad110, pf - float3( 1.0, 1.0, 0.0 ));
float3 grad111 = tex2D( samplerPermTex, float2( perm11, pi.z + permONE )).xyz * 4.0 - 1.0;
float n111 = dot( grad111, pf - float3( 1.0, 1.0, 1.0 ));
// Blend contributions along x
float4 n_x = lerp( float4( n000, n001, n010, n011 ), float4( n100, n101, n110, n111 ), fade( pf.x ));
// Blend contributions along y
float2 n_xy = lerp( n_x.xy, n_x.zw, fade( pf.y ));
// Blend contributions along z
float n_xyz = lerp( n_xy.x, n_xy.y, fade( pf.z ));
// We're done, return the final noise value
return n_xyz;
}
float getAvgColor( float3 col )
{
return dot( col.xyz, float3( 0.333333f, 0.333334f, 0.333333f ));
}
// nVidia blend modes
// Source: https://www.khronos.org/registry/OpenGL/extensions/NV/NV_blend_equation_advanced.txt
float3 ClipColor( float3 color )
{
float lum = getAvgColor( color.xyz );
float mincol = min( min( color.x, color.y ), color.z );
float maxcol = max( max( color.x, color.y ), color.z );
color.xyz = ( mincol < 0.0f ) ? lum + (( color.xyz - lum ) * lum ) / ( lum - mincol ) : color.xyz;
color.xyz = ( maxcol > 1.0f ) ? lum + (( color.xyz - lum ) * ( 1.0f - lum )) / ( maxcol - lum ) : color.xyz;
return color;
}
// Luminosity: base, blend
// Color: blend, base
float3 blendLuma( float3 base, float3 blend )
{
float lumbase = getAvgColor( base.xyz );
float lumblend = getAvgColor( blend.xyz );
float ldiff = lumblend - lumbase;
float3 col = base.xyz + ldiff;
return ClipColor( col.xyz );
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_FilmGrain(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
// Noise
float timer = 1.0f;
if( grainMotion )
timer = Timer % 1000.0f;
float2 uv = texcoord.xy * float2( BUFFER_WIDTH, BUFFER_HEIGHT );
float3 noise = pnoise3D( float3( uv.xy, 1 ), timer );
noise.y = pnoise3D( float3( uv.xy, 2 ), timer );
noise.z = pnoise3D( float3( uv.xy, 3 ), timer );
// Intensity
noise.xyz *= grainIntensity;
// Noise color
noise.xyz = lerp( noise.xxx, noise.xyz, grainColor );
// Control noise density
noise.xyz = pow( abs( noise.xyz ), max( 11.0f - grainDensity, 0.1f )) * sign( noise.xyz );
// Pack noise that has range -1..0..1 into 0..1 range for blurring passes
// After blurring passes unpack again noise * 2 - 1
noise.xyz = saturate(( noise.xyz + 1.0f ) * 0.5f );
return float4( noise.xyz, 1.0f );
}
#if( FG_GRAIN_SMOOTHING )
float4 PS_BlurH(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 noise = tex2D( samplerNoise, texcoord );
// Blur
float SigmaSum = 0.0f;
float pxlOffset = 1.0f;
float Blur = grainBlur * grainSize;
float3 Sigma;
Sigma.x = 1.0f / ( sqrt( 6.283184f ) * Blur );
Sigma.y = exp( -0.5f / ( Blur * Blur ));
Sigma.z = Sigma.y * Sigma.y;
noise.xyz *= Sigma.x;
SigmaSum += Sigma.x;
Sigma.xy *= Sigma.yz;
float px = BUFFER_RCP_WIDTH;
[loop]
for( int i = 0; i < 5 && Sigma.x > 0.001f; ++i )
{
noise += tex2Dlod( samplerNoise, float4( texcoord.xy + float2( pxlOffset * px, 0.0f ), 0.0, 0.0 )) * Sigma.x;
noise += tex2Dlod( samplerNoise, float4( texcoord.xy - float2( pxlOffset * px, 0.0f ), 0.0, 0.0 )) * Sigma.x;
SigmaSum += ( 2.0f * Sigma.x );
pxlOffset += 1.0f;
Sigma.xy *= Sigma.yz;
}
noise.xyz /= SigmaSum;
return float4( noise.xyz, 1.0f );
}
float4 PS_BlurV(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 noise = tex2D( samplerNoiseH, texcoord );
// Blur
float SigmaSum = 0.0f;
float pxlOffset = 1.0f;
float Blur = grainBlur * grainSize;
float3 Sigma;
Sigma.x = 1.0f / ( sqrt( 6.283184f ) * Blur );
Sigma.y = exp( -0.5f / ( Blur * Blur ));
Sigma.z = Sigma.y * Sigma.y;
noise.xyz *= Sigma.x;
SigmaSum += Sigma.x;
Sigma.xy *= Sigma.yz;
float py = BUFFER_RCP_HEIGHT;
[loop]
for( int i = 0; i < 5 && Sigma.x > 0.001f; ++i )
{
noise += tex2Dlod( samplerNoiseH, float4( texcoord.xy + float2( 0.0f, pxlOffset * py ), 0.0, 0.0 )) * Sigma.x;
noise += tex2Dlod( samplerNoiseH, float4( texcoord.xy - float2( 0.0f, pxlOffset * py ), 0.0, 0.0 )) * Sigma.x;
SigmaSum += ( 2.0f * Sigma.x );
pxlOffset += 1.0f;
Sigma.xy *= Sigma.yz;
}
noise.xyz /= SigmaSum;
return float4( noise.xyz, 1.0f );
}
#endif
float4 PS_MergeNoise(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
#if( FG_GRAIN_SMOOTHING )
float4 noise = tex2D( samplerNoiseV, texcoord );
#else
float4 noise = tex2D( samplerNoise, texcoord );
#endif
float4 color = tex2D( ReShade::BackBuffer, texcoord );
// Unpack noise
noise.xyz = noise.xyz * 2.0f - 1.0f;
// Depth
float depth = ReShade::GetLinearizedDepth( texcoord ).x;
depth = smoothstep( depthStart, depthEnd, depth );
depth = pow( depth, depthCurve );
float d = enable_depth ? depth : 1.0f;
// Test setup
float3 testenv = ( texcoord.y < 0.25f ) ? texcoord.xxx : ( texcoord.y < 0.5f ) ? float3( texcoord.x, 0.0f, 0.0f ) :
( texcoord.y < 0.75f ) ? float3( 0.0f, texcoord.x, 0.0f ) : float3( 0.0f, 0.0f, texcoord.x );
color.xyz = enable_test ? testenv.xyz : color.xyz;
// Store some values
float3 origHSV = RGBToHSV( color.xyz );
float3 orig = color.xyz;
float maxc = max( max( color.x, color.y ), color.z );
float minc = min( min( color.x, color.y ), color.z );
// Mixing options
float lum = maxc;
noise.xyz = lerp( noise.xyz * grainIntLow, noise.xyz * grainIntHigh, fade( lum )); // Noise adjustments based on average intensity
float3 negnoise = -abs( noise.xyz );
lum *= lum;
// Apply only negative noise in highlights/whites as positive will be clipped out
// Swizzle the components of negnoise to avoid middle intensity regions of no noise ( x - x = 0 )
negnoise.xyz = lerp( noise.xyz, negnoise.zxy * 0.5f, lum );
noise.xyz = use_negnoise ? negnoise.xyz : noise.xyz;
// Noise coloring
// Issue, when changing hue to original Red, Bblue channels work fine, but humans more sensitive to Yellow/Green
// In perceived luminosity R and B channel are very close, will assume they are equal as they are close enough
// "weight" is my poor attemp to match human vision, bit heavier on the yellow-green than green
float factor = 1.2f;
float weight = max( 1.0f - abs(( origHSV.x - 0.166667f ) * 6.0f ), 0.0f ) * factor;
weight += max( 1.0f - abs(( origHSV.x - 0.333333f ) * 6.0f ), 0.0f ) / factor;
weight = saturate( curve( weight / factor ));
// Account for saturation
weight *= saturate(( maxc + 1.0e-10 - minc ) / maxc + 1.0e-10 );
// Account for intensity. Highest reduction at 0.2 intensity
// No change in blacks and brights
float adj = saturate(( maxc - 0.2f ) * 1.25f ) + saturate( 1.0f - maxc * 5.0f );
adj = 1.0f - curve( adj );
weight *= adj;
// Create a factor to adjust noise intensity based on weight
float adjNoise = lerp( 1.0f, 0.5f, grainOrigColor * weight );
color.xyz = lerp( color.xyz, color.xyz + ( noise.xyz * d ), grainAmount * adjNoise );
color.xyz = saturate( color.xyz );
// Use original hue and saturation mixed with lightness channel of noise
float3 col = blendLuma( orig.xyz, color.xyz );
color.xyz = grainOrigColor ? col.xyz : color.xyz;
color.xyz = display_depth ? depth.xxx : color.xyz;
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_06_FilmGrain
{
pass prod80_WriteNoise
{
VertexShader = PostProcessVS;
PixelShader = PS_FilmGrain;
RenderTarget = texNoise;
}
#if( FG_GRAIN_SMOOTHING )
pass prod80_BlurH
{
VertexShader = PostProcessVS;
PixelShader = PS_BlurH;
RenderTarget = texNoiseH;
}
pass prod80_BlurV
{
VertexShader = PostProcessVS;
PixelShader = PS_BlurV;
RenderTarget = texNoiseV;
}
#endif
pass prod80_MixNoise
{
VertexShader = PostProcessVS;
PixelShader = PS_MergeNoise;
}
}
}

View File

@ -0,0 +1,153 @@
/*
Description : PD80 06 Luma Fade for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
namespace pd80_lumafade
{
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float transition_speed <
ui_type = "slider";
ui_label = "Time Based Fade Speed";
ui_tooltip = "Time Based Fade Speed";
ui_category = "Scene Luminance Adaptation";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.5;
uniform float minlevel <
ui_label = "Pure Dark Scene Level";
ui_tooltip = "Pure Dark Scene Level";
ui_category = "Scene Luminance Adaptation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.125;
uniform float maxlevel <
ui_label = "Pure Light Scene Level";
ui_tooltip = "Pure Light Scene Level";
ui_category = "Scene Luminance Adaptation";
ui_type = "slider";
ui_min = 0.0;
ui_max = 1.0;
> = 0.3;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texLuma { Width = 256; Height = 256; Format = R16F; MipLevels = 8; };
texture texAvgLuma { Format = R16F; };
texture texPrevAvgLuma { Format = R16F; };
texture texPrevColor { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerLuma { Texture = texLuma; };
sampler samplerAvgLuma { Texture = texAvgLuma; };
sampler samplerPrevAvgLuma { Texture = texPrevAvgLuma; };
sampler samplerPrevColor { Texture = texPrevColor; };
//// DEFINES ////////////////////////////////////////////////////////////////////
uniform float Frametime < source = "frametime"; >;
//// FUNCTIONS //////////////////////////////////////////////////////////////////
float interpolate( float o, float n, float factor, float ft )
{
return lerp( o, n, 1.0f - exp( -factor * ft ));
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float PS_WriteLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( ReShade::BackBuffer, texcoord );
return dot( color.xyz, 0.333333f );
}
float PS_AvgLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float luma = tex2Dlod( samplerLuma, float4( 0.5f, 0.5f, 0, 8 )).x;
float prevluma = tex2D( samplerPrevAvgLuma, float2( 0.5f, 0.5f )).x;
float factor = transition_speed * 4.0f + 1.0f;
return interpolate( prevluma, luma, factor, Frametime * 0.001f );
}
float4 PS_StorePrev(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D( ReShade::BackBuffer, texcoord );
}
float PS_PrevAvgLuma(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D( samplerAvgLuma, float2( 0.5f, 0.5f )).x;
}
float4 PS_LumaInterpolation(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 newcol = tex2D( ReShade::BackBuffer, texcoord );
float4 oldcol = tex2D( samplerPrevColor, texcoord );
float luma = tex2D( samplerAvgLuma, float2( 0.5f, 0.5f )).x;
return lerp( oldcol, newcol, smoothstep( minlevel, maxlevel, luma ));
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_06_LumaFade_Start
< ui_tooltip = "Luma Fading Effects\n\n"
"This shader allows you to fade in and out ReShade effects based on scene luminance.\n"
"To use: put the Start technque before the shaders you want to enable in a BRIGHT scene and\n"
"put the End technique after those shaders. Then use the UI settings to manipulate the fading.";>
{
pass Luma
{
VertexShader = PostProcessVS;
PixelShader = PS_WriteLuma;
RenderTarget = texLuma;
}
pass AvgLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_AvgLuma;
RenderTarget = texAvgLuma;
}
pass StoreColor
{
VertexShader = PostProcessVS;
PixelShader = PS_StorePrev;
RenderTarget = texPrevColor;
}
pass PreviousLuma
{
VertexShader = PostProcessVS;
PixelShader = PS_PrevAvgLuma;
RenderTarget = texPrevAvgLuma;
}
}
technique prod80_06_LumaFade_End
{
pass Combine
{
VertexShader = PostProcessVS;
PixelShader = PS_LumaInterpolation;
}
}
}

View File

@ -0,0 +1,152 @@
/*
Description : PD80 06 Posterize Pixelate for Reshade https://reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#include "PD80_00_Noise_Samplers.fxh"
namespace pd80_posterizepixelate
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform int number_of_levels <
ui_label = "Number of Levels";
ui_tooltip = "Number of Levels";
ui_category = "Posterize";
ui_type = "slider";
ui_min = 2;
ui_max = 255;
> = 255;
uniform int pixel_size <
ui_label = "Pixel Size";
ui_tooltip = "Pixel Size";
ui_category = "Pixelate";
ui_type = "slider";
ui_min = 1;
ui_max = 9;
> = 1;
uniform float effect_strength <
ui_type = "slider";
ui_label = "Effect Strength";
ui_tooltip = "Effect Strength";
ui_category = "Posterize Pixelate";
ui_min = 0.0f;
ui_max = 1.0f;
> = 1.0;
uniform float border_str <
ui_type = "slider";
ui_label = "Border Strength";
ui_tooltip = "Border Strength";
ui_category = "Posterize Pixelate";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.0;
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
ui_category = "Posterize Pixelate";
> = false;
uniform bool dither_motion <
ui_label = "Dither Motion";
ui_tooltip = "Dither Motion";
ui_category = "Posterize Pixelate";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_category = "Posterize Pixelate";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texMipMe { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; MipLevels = 9; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerMipMe
{
Texture = texMipMe;
MipFilter = POINT;
MinFilter = POINT;
MagFilter = POINT;
};
//// DEFINES ////////////////////////////////////////////////////////////////////
#define aspect float( BUFFER_WIDTH * BUFFER_RCP_HEIGHT )
//// FUNCTIONS //////////////////////////////////////////////////////////////////
uniform float2 pingpong < source = "pingpong"; min = 0; max = 128; step = 1; >;
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_MipMe(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D( ReShade::BackBuffer, texcoord );
}
float4 PS_Posterize(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float3 color = tex2Dlod( samplerMipMe, float4( texcoord.xy, 0.0f, pixel_size - 1 )).xyz;
float exp = exp2( pixel_size - 1 );
float rcp_exp = max( rcp( exp ) - 0.00001f, 0.0f ); // - 0.00001f because fp precision comes into play
float2 bwbh = float2( floor( BUFFER_WIDTH / exp ), floor( BUFFER_HEIGHT / exp ));
// Dither
float2 tx = bwbh.xy / 512.0f;
tx.xy *= texcoord.xy;
float3 dnoise = tex2D( samplerRGBNoise, tx ).xyz;
float mot = dither_motion ? pingpong.x + 9 : 1.0f;
dnoise.xyz = frac( dnoise + 0.61803398875f * mot );
dnoise.xyz = dnoise * 2.0f - 1.0f;
color.xyz = enable_dither ? saturate( color.xyz + dnoise.xyz * ( dither_strength / number_of_levels )) : color.xyz;
// Dither end
float3 orig = color.xyz;
color.xyz = floor( color.xyz * number_of_levels ) / ( number_of_levels - 1 );
float2 uv = frac( texcoord.xy * bwbh.xy );
float grade = ( uv.x <= rcp_exp ) ? 1.0 : 0.0;
grade += ( uv.y <= rcp_exp ) ? 1.0 : 0.0;
color.xyz = lerp( color.xyz, lerp( color.xyz, 0.0f, border_str * saturate( pixel_size - 1 )), saturate( grade ));
color.xyz = lerp( orig.xyz, color.xyz, effect_strength );
return float4( color.xyz, 1.0f );
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_06_Posterize_Pixelate
{
pass prod80_pass0
{
VertexShader = PostProcessVS;
PixelShader = PS_MipMe;
RenderTarget = texMipMe;
}
pass prod80_pass1
{
VertexShader = PostProcessVS;
PixelShader = PS_Posterize;
}
}
}

View File

@ -0,0 +1,148 @@
/*
* Original shader by Ganossa
*
* ReShade Community edits by:
* - MartyMcFly
* - Otis_Inf
* - prod80
*/
// Input
#define _CONCAT(a, b) a##b
#define _MERGE(a, b) _CONCAT(a, b)
#define PD80_TexName _MERGE( PD80_Technique_Name, Tex )
#define PD80_Sampler _MERGE( PD80_Technique_Name, Samp )
#define PD80_NameSpace _MERGE( PD80_Technique_Name, Name )
#include "ReShade.fxh"
#include "PD80_00_Noise_Samplers.fxh"
#include "PD80_00_Color_Spaces.fxh"
namespace PD80_NameSpace
{
//// UI Elements /////////////////////////////////////////////////
uniform bool enable_dither <
ui_label = "Enable Dithering";
ui_tooltip = "Enable Dithering";
> = true;
uniform float dither_strength <
ui_type = "slider";
ui_label = "Dither Strength";
ui_tooltip = "Dither Strength";
ui_min = 0.0f;
ui_max = 10.0f;
> = 1.0;
uniform int PD80_LutSelector <
ui_type = "combo";
ui_items= PD80_Drop_Down_Menu;
ui_label = "LUT Selection";
ui_tooltip = "The LUT to use for color transformation.";
> = 0;
uniform float PD80_MixChroma <
ui_type = "slider";
ui_min = 0.00; ui_max = 1.00;
ui_label = "LUT Chroma";
ui_tooltip = "LUT Chroma";
> = 1.00;
uniform float PD80_MixLuma <
ui_type = "slider";
ui_min = 0.00; ui_max = 1.00;
ui_label = "LUT Luma";
ui_tooltip = "LUT Luma";
> = 1.00;
uniform float PD80_Intensity <
ui_type = "slider";
ui_min = 0.00; ui_max = 1.00;
ui_label = "LUT Intensity";
ui_tooltip = "Intensity of LUT effect";
> = 1.00;
uniform float3 ib <
ui_type = "color";
ui_label = "LUT Black IN Level";
ui_tooltip = "LUT Black IN Level";
ui_category = "LUT Levels";
> = float3(0.0, 0.0, 0.0);
uniform float3 iw <
ui_type = "color";
ui_label = "LUT White IN Level";
ui_tooltip = "LUT White IN Level";
ui_category = "LUT Levels";
> = float3(1.0, 1.0, 1.0);
uniform float3 ob <
ui_type = "color";
ui_label = "LUT Black OUT Level";
ui_tooltip = "LUT Black OUT Level";
ui_category = "LUT Levels";
> = float3(0.0, 0.0, 0.0);
uniform float3 ow <
ui_type = "color";
ui_label = "LUT White OUT Level";
ui_tooltip = "LUT White OUT Level";
ui_category = "LUT Levels";
> = float3(1.0, 1.0, 1.0);
uniform float ig <
ui_label = "LUT Gamma Adjustment";
ui_tooltip = "LUT Gamma Adjustment";
ui_category = "LUT Levels";
ui_type = "slider";
ui_min = 0.05;
ui_max = 10.0;
> = 1.0;
//// Textures Samplers ///////////////////////////////////////////
texture PD80_TexName < source = PD80_LUT_File_Name; >
{
Width = PD80_Tile_SizeXY * PD80_Tile_Amount;
Height = PD80_Tile_SizeXY * PD80_LUT_Amount;
};
sampler PD80_Sampler { Texture = PD80_TexName; };
//// Functions ///////////////////////////////////////////////////
float3 levels( float3 color, float3 blackin, float3 whitein, float gamma, float3 outblack, float3 outwhite )
{
float3 ret = saturate( color.xyz - blackin.xyz ) / max( whitein.xyz - blackin.xyz, 0.000001f );
ret.xyz = pow( ret.xyz, gamma );
ret.xyz = ret.xyz * saturate( outwhite.xyz - outblack.xyz ) + outblack.xyz;
return ret;
}
//// Pixel Shader ////////////////////////////////////////////////
void PS_MultiLUT_v2( float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0 )
{
color = tex2D( ReShade::BackBuffer, texcoord.xy );
float4 dnoise = dither( samplerRGBNoise, texcoord.xy, 10, enable_dither, dither_strength, 1, 0.5f );
float2 texelsize = rcp( PD80_Tile_SizeXY );
texelsize.x /= PD80_Tile_Amount;
float3 lutcoord = float3(( color.xy * PD80_Tile_SizeXY - color.xy + 0.5f ) * texelsize.xy, color.z * PD80_Tile_SizeXY - color.z );
lutcoord.y /= PD80_LUT_Amount;
lutcoord.y += ( float( PD80_LutSelector ) / PD80_LUT_Amount );
float lerpfact = frac( lutcoord.z );
lutcoord.x += ( lutcoord.z - lerpfact ) * texelsize.y;
float3 lutcolor = lerp( tex2D( PD80_Sampler, lutcoord.xy ).xyz, tex2D( PD80_Sampler, float2( lutcoord.x + texelsize.y, lutcoord.y )).xyz, lerpfact );
lutcolor.xyz = levels( lutcolor.xyz, saturate( ib.xyz + dnoise.xyz ),
saturate( iw.xyz + dnoise.yzx ),
ig,
saturate( ob.xyz + dnoise.zxy ),
saturate( ow.xyz + dnoise.wxz ));
float3 lablut = pd80_srgb_to_lab( lutcolor.xyz );
float3 labcol = pd80_srgb_to_lab( color.xyz );
float newluma = lerp( labcol.x, lablut.x, PD80_MixLuma );
float2 newAB = lerp( labcol.yz, lablut.yz, PD80_MixChroma );
lutcolor.xyz = pd80_lab_to_srgb( float3( newluma, newAB ));
color.xyz = lerp( color.xyz, saturate( lutcolor.xyz + dnoise.wzx ), PD80_Intensity );
}
//// Technique ///////////////////////////////////////////////////
technique PD80_Technique_Name
{
pass MultiLUT_Apply
{
VertexShader = PostProcessVS;
PixelShader = PS_MultiLUT_v2;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
/*
* SPDX-License-Identifier: CC0-1.0
*/
#pragma once
#if !defined(__RESHADE__) || __RESHADE__ < 30000
#error "ReShade 3.0+ is required to use this header file"
#endif
#ifndef RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
#define RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN 0
#endif
#ifndef RESHADE_DEPTH_INPUT_IS_REVERSED
#define RESHADE_DEPTH_INPUT_IS_REVERSED 1
#endif
#ifndef RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
#define RESHADE_DEPTH_INPUT_IS_LOGARITHMIC 0
#endif
#ifndef RESHADE_DEPTH_MULTIPLIER
#define RESHADE_DEPTH_MULTIPLIER 1
#endif
#ifndef RESHADE_DEPTH_LINEARIZATION_FAR_PLANE
#define RESHADE_DEPTH_LINEARIZATION_FAR_PLANE 1000.0
#endif
// Above 1 expands coordinates, below 1 contracts and 1 is equal to no scaling on any axis
#ifndef RESHADE_DEPTH_INPUT_Y_SCALE
#define RESHADE_DEPTH_INPUT_Y_SCALE 1
#endif
#ifndef RESHADE_DEPTH_INPUT_X_SCALE
#define RESHADE_DEPTH_INPUT_X_SCALE 1
#endif
// An offset to add to the Y coordinate, (+) = move up, (-) = move down
#ifndef RESHADE_DEPTH_INPUT_Y_OFFSET
#define RESHADE_DEPTH_INPUT_Y_OFFSET 0
#endif
#ifndef RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET
#define RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET 0
#endif
// An offset to add to the X coordinate, (+) = move right, (-) = move left
#ifndef RESHADE_DEPTH_INPUT_X_OFFSET
#define RESHADE_DEPTH_INPUT_X_OFFSET 0
#endif
#ifndef RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET
#define RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET 0
#endif
#define BUFFER_PIXEL_SIZE float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define BUFFER_SCREEN_SIZE float2(BUFFER_WIDTH, BUFFER_HEIGHT)
#define BUFFER_ASPECT_RATIO (BUFFER_WIDTH * BUFFER_RCP_HEIGHT)
namespace ReShade
{
#if defined(__RESHADE_FXC__)
float GetAspectRatio() { return BUFFER_WIDTH * BUFFER_RCP_HEIGHT; }
float2 GetPixelSize() { return float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT); }
float2 GetScreenSize() { return float2(BUFFER_WIDTH, BUFFER_HEIGHT); }
#define AspectRatio GetAspectRatio()
#define PixelSize GetPixelSize()
#define ScreenSize GetScreenSize()
#else
// These are deprecated and will be removed eventually.
static const float AspectRatio = BUFFER_WIDTH * BUFFER_RCP_HEIGHT;
static const float2 PixelSize = float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT);
static const float2 ScreenSize = float2(BUFFER_WIDTH, BUFFER_HEIGHT);
#endif
// Global textures and samplers
texture BackBufferTex : COLOR;
texture DepthBufferTex : DEPTH;
sampler BackBuffer { Texture = BackBufferTex; };
sampler DepthBuffer { Texture = DepthBufferTex; };
// Helper functions
float GetLinearizedDepth(float2 texcoord)
{
#if RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
texcoord.y = 1.0 - texcoord.y;
#endif
texcoord.x /= RESHADE_DEPTH_INPUT_X_SCALE;
texcoord.y /= RESHADE_DEPTH_INPUT_Y_SCALE;
#if RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET
texcoord.x -= RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET * BUFFER_RCP_WIDTH;
#else // Do not check RESHADE_DEPTH_INPUT_X_OFFSET, since it may be a decimal number, which the preprocessor cannot handle
texcoord.x -= RESHADE_DEPTH_INPUT_X_OFFSET / 2.000000001;
#endif
#if RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET
texcoord.y += RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET * BUFFER_RCP_HEIGHT;
#else
texcoord.y += RESHADE_DEPTH_INPUT_Y_OFFSET / 2.000000001;
#endif
float depth = tex2Dlod(DepthBuffer, float4(texcoord, 0, 0)).x * RESHADE_DEPTH_MULTIPLIER;
#if RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
const float C = 0.01;
depth = (exp(depth * log(C + 1.0)) - 1.0) / C;
#endif
#if RESHADE_DEPTH_INPUT_IS_REVERSED
depth = 1.0 - depth;
#endif
const float N = 1.0;
depth /= RESHADE_DEPTH_LINEARIZATION_FAR_PLANE - depth * (RESHADE_DEPTH_LINEARIZATION_FAR_PLANE - N);
return depth;
}
}
// Vertex shader generating a triangle covering the entire screen
// See also https://www.reddit.com/r/gamedev/comments/2j17wk/a_slightly_faster_bufferless_vertex_shader_trick/
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}

View File

@ -0,0 +1,216 @@
#pragma once
#if !defined(__RESHADE__) || __RESHADE__ < 30000
#error "ReShade 3.0+ is required to use this header file"
#endif
#define RESHADE_VERSION(major,minor,build) (10000 * (major) + 100 * (minor) + (build))
#define SUPPORTED_VERSION(major,minor,build) (__RESHADE__ >= RESHADE_VERSION(major,minor,build))
// Since 3.0.0
// Commit current in-game user interface status
// https://github.com/crosire/reshade/commit/302bacc49ae394faedc2e29a296c1cebf6da6bb2#diff-82cf230afdb2a0d5174111e6f17548a5R1183
// Added various GUI related uniform variable annotations
// https://reshade.me/forum/releases/2341-3-0
#define __UNIFORM_INPUT_ANY ui_type = "input";
#define __UNIFORM_INPUT_BOOL1 __UNIFORM_INPUT_ANY // It is unsupported on all version
#define __UNIFORM_INPUT_BOOL2 __UNIFORM_INPUT_ANY // It is unsupported on all version
#define __UNIFORM_INPUT_BOOL3 __UNIFORM_INPUT_ANY // It is unsupported on all version
#define __UNIFORM_INPUT_BOOL4 __UNIFORM_INPUT_ANY // It is unsupported on all version
#define __UNIFORM_INPUT_INT1 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_INT2 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_INT3 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_INT4 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_FLOAT1 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_FLOAT2 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_FLOAT3 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_INPUT_FLOAT4 __UNIFORM_INPUT_ANY // If it was not supported in someday or now, please add information
// Since 4.0.1
// Change slider widget to be used with new "slider" instead of a "drag" type annotation
// https://github.com/crosire/reshade/commit/746229f31cd6f311a3e72a543e4f1f23faa23f11#diff-59405a313bd8cbfb0ca6dd633230e504R1701
// Changed slider widget to be used with < ui_type = "slider"; > instead of < ui_type = "drag"; >
// https://reshade.me/forum/releases/4772-4-0
#if SUPPORTED_VERSION(4,0,1)
#define __UNIFORM_DRAG_ANY ui_type = "drag";
// Since 4.0.0
// Rework statistics tab and add drag widgets back
// https://github.com/crosire/reshade/commit/1b2c38795f00efd66c007da1f483f1441b230309
// Changed drag widget to a slider widget (old one is still available via < ui_type = "drag2"; >)
// https://reshade.me/forum/releases/4772-4-0
#elif SUPPORTED_VERSION(4,0,0)
#define __UNIFORM_DRAG_ANY ui_type = "drag2";
// Since 3.0.0
// Commit current in-game user interface status
// https://github.com/crosire/reshade/commit/302bacc49ae394faedc2e29a296c1cebf6da6bb2#diff-82cf230afdb2a0d5174111e6f17548a5R1187
// Added various GUI related uniform variable annotations
// https://reshade.me/forum/releases/2341-3-0
#else
#define __UNIFORM_DRAG_ANY ui_type = "drag";
#endif
#define __UNIFORM_DRAG_BOOL1 __UNIFORM_DRAG_ANY // It is unsupported on all version
#define __UNIFORM_DRAG_BOOL2 __UNIFORM_DRAG_ANY // It is unsupported on all version
#define __UNIFORM_DRAG_BOOL3 __UNIFORM_DRAG_ANY // It is unsupported on all version
#define __UNIFORM_DRAG_BOOL4 __UNIFORM_DRAG_ANY // It is unsupported on all version
#define __UNIFORM_DRAG_INT1 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_INT2 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_INT3 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_INT4 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_FLOAT1 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_FLOAT2 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_FLOAT3 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_DRAG_FLOAT4 __UNIFORM_DRAG_ANY // If it was not supported in someday or now, please add information
// Since 4.0.1
// Change slider widget to be used with new "slider" instead of a "drag" type annotation
// https://github.com/crosire/reshade/commit/746229f31cd6f311a3e72a543e4f1f23faa23f11#diff-59405a313bd8cbfb0ca6dd633230e504R1699
// Changed slider widget to be used with < ui_type = "slider"; > instead of < ui_type = "drag"; >
// https://reshade.me/forum/releases/4772-4-0
#if SUPPORTED_VERSION(4,0,1)
#define __UNIFORM_SLIDER_ANY ui_type = "slider";
// Since 4.0.0
// Rework statistics tab and add drag widgets back
// https://github.com/crosire/reshade/commit/1b2c38795f00efd66c007da1f483f1441b230309
// Changed drag widget to a slider widget (old one is still available via < ui_type = "drag2"; >)
// https://reshade.me/forum/releases/4772-4-0
#elif SUPPORTED_VERSION(4,0,0)
#define __UNIFORM_SLIDER_ANY ui_type = "drag";
#else
#define __UNIFORM_SLIDER_ANY __UNIFORM_DRAG_ANY
#endif
#define __UNIFORM_SLIDER_BOOL1 __UNIFORM_SLIDER_ANY // It is unsupported on all version
#define __UNIFORM_SLIDER_BOOL2 __UNIFORM_SLIDER_ANY // It is unsupported on all version
#define __UNIFORM_SLIDER_BOOL3 __UNIFORM_SLIDER_ANY // It is unsupported on all version
#define __UNIFORM_SLIDER_BOOL4 __UNIFORM_SLIDER_ANY // It is unsupported on all version
#define __UNIFORM_SLIDER_INT1 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_INT2 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_INT3 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_INT4 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_FLOAT1 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_FLOAT2 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_FLOAT3 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_SLIDER_FLOAT4 __UNIFORM_SLIDER_ANY // If it was not supported in someday or now, please add information
// Since 3.0.0
// Add combo box display type for uniform variables and fix displaying of integer variable under Direct3D 9
// https://github.com/crosire/reshade/commit/b025bfae5f7343509ec0cacf6df0cff537c499f2#diff-82cf230afdb2a0d5174111e6f17548a5R1631
// Added various GUI related uniform variable annotations
// https://reshade.me/forum/releases/2341-3-0
#define __UNIFORM_COMBO_ANY ui_type = "combo";
// __UNIFORM_COMBO_BOOL1
#define __UNIFORM_COMBO_BOOL2 __UNIFORM_COMBO_ANY // It is unsupported on all version
#define __UNIFORM_COMBO_BOOL3 __UNIFORM_COMBO_ANY // It is unsupported on all version
#define __UNIFORM_COMBO_BOOL4 __UNIFORM_COMBO_ANY // It is unsupported on all version
#define __UNIFORM_COMBO_INT1 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_COMBO_INT2 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_COMBO_INT3 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_COMBO_INT4 __UNIFORM_COMBO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_COMBO_FLOAT1 __UNIFORM_COMBO_ANY // It is unsupported on all version
#define __UNIFORM_COMBO_FLOAT2 __UNIFORM_COMBO_ANY // It is unsupported on all version
#define __UNIFORM_COMBO_FLOAT3 __UNIFORM_COMBO_ANY // It is unsupported on all version
#define __UNIFORM_COMBO_FLOAT4 __UNIFORM_COMBO_ANY // It is unsupported on all version
// Since 4.0.0 (but the ui_items force set "Off\0On\0"), and if less than it force converted to checkbox
// Add option to display boolean values as combo box instead of checkbox
// https://github.com/crosire/reshade/commit/aecb757c864c9679e77edd6f85a1521c49e489c1#diff-59405a313bd8cbfb0ca6dd633230e504R1147
// https://github.com/crosire/reshade/blob/v4.0.0/source/gui.cpp
// Added option to display boolean values as combo box instead of checkbox (via < ui_type = "combo"; >)
// https://reshade.me/forum/releases/4772-4-0
#define __UNIFORM_COMBO_BOOL1 __UNIFORM_COMBO_ANY
// Since 4.0.0
// Cleanup GUI code and rearrange some widgets
// https://github.com/crosire/reshade/commit/6751f7bd50ea7c0556cf0670f10a4b4ba912ee7d#diff-59405a313bd8cbfb0ca6dd633230e504R1711
// Added radio button widget (via < ui_type = "radio"; ui_items = "Button 1\0Button 2\0...\0"; >)
// https://reshade.me/forum/releases/4772-4-0
#if SUPPORTED_VERSION(4,0,0)
#define __UNIFORM_RADIO_ANY ui_type = "radio";
#else
#define __UNIFORM_RADIO_ANY __UNIFORM_COMBO_ANY
#endif
#define __UNIFORM_RADIO_BOOL1 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_BOOL2 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_BOOL3 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_BOOL4 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_INT1 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_RADIO_INT2 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_RADIO_INT3 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_RADIO_INT4 __UNIFORM_RADIO_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_RADIO_FLOAT1 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_FLOAT2 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_FLOAT3 __UNIFORM_RADIO_ANY // It is unsupported on all version
#define __UNIFORM_RADIO_FLOAT4 __UNIFORM_RADIO_ANY // It is unsupported on all version
// Since 4.1.0
// Fix floating point uniforms with unknown "ui_type" not showing up in UI
// https://github.com/crosire/reshade/commit/50e5bf44dfc84bc4220c2b9f19d5f50c7a0fda66#diff-59405a313bd8cbfb0ca6dd633230e504R1788
// Fixed floating point uniforms with unknown "ui_type" not showing up in UI
// https://reshade.me/forum/releases/5021-4-1
#define __UNIFORM_COLOR_ANY ui_type = "color";
// Since 3.0.0
// Move technique list to preset configuration file
// https://github.com/crosire/reshade/blob/84bba3aa934c1ebe4c6419b69dfe1690d9ab9d34/source/runtime.cpp#L1328
// Added various GUI related uniform variable annotations
// https://reshade.me/forum/releases/2341-3-0
// If empty, these versions before 4.1.0 are decide that the type is color from the number of components
#define __UNIFORM_COLOR_BOOL1 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_BOOL2 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_BOOL3 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_BOOL4 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_INT1 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_INT2 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_INT3 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_INT4 __UNIFORM_COLOR_ANY // It is unsupported on all version
// __UNIFORM_COLOR_FLOAT1
#define __UNIFORM_COLOR_FLOAT2 __UNIFORM_COLOR_ANY // It is unsupported on all version
#define __UNIFORM_COLOR_FLOAT3 __UNIFORM_COLOR_ANY // If it was not supported in someday or now, please add information
#define __UNIFORM_COLOR_FLOAT4 __UNIFORM_COLOR_ANY // If it was not supported in someday or now, please add information
// Since 4.2.0
// Add alpha slider widget for single component uniform variables (#86)
// https://github.com/crosire/reshade/commit/87a740a8e3c4dcda1dd4eeec8d5cff7fa35fe829#diff-59405a313bd8cbfb0ca6dd633230e504R1820
// Added alpha slider widget for single component uniform variables
// https://reshade.me/forum/releases/5150-4-2
#if SUPPORTED_VERSION(4,2,0)
#define __UNIFORM_COLOR_FLOAT1 __UNIFORM_COLOR_ANY
#else
#define __UNIFORM_COLOR_FLOAT1 __UNIFORM_SLIDER_ANY
#endif
// Since 4.3.0
// Add new "list" GUI widget (#103)
// https://github.com/crosire/reshade/commit/515287d20ce615c19cf3d4c21b49f83896f04ddc#diff-59405a313bd8cbfb0ca6dd633230e504R1894
// Added new "list" GUI widget
// https://reshade.me/forum/releases/5417-4-3
#if SUPPORTED_VERSION(4,3,0)
#define __UNIFORM_LIST_ANY ui_type = "list";
#else
#define __UNIFORM_LIST_ANY __UNIFORM_COMBO_ANY
#endif
// __UNIFORM_LIST_BOOL1
#define __UNIFORM_LIST_BOOL2 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_BOOL3 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_BOOL4 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_INT1 __UNIFORM_LIST_ANY // Supported in 4.3.0
#define __UNIFORM_LIST_INT2 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_INT3 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_INT4 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_FLOAT1 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_FLOAT2 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_FLOAT3 __UNIFORM_LIST_ANY // Not supported in all versions
#define __UNIFORM_LIST_FLOAT4 __UNIFORM_LIST_ANY // Not supported in all versions
// For compatible with ComboBox
#define __UNIFORM_LIST_BOOL1 __UNIFORM_COMBO_ANY

View File

@ -0,0 +1,325 @@
/**
* _______ ___ ___ ___ ___
* / || \/ | / \ / \
* | (---- | \ / | / ^ \ / ^ \
* \ \ | |\/| | / /_\ \ / /_\ \
* ----) | | | | | / _____ \ / _____ \
* |_______/ |__| |__| /__/ \__\ /__/ \__\
*
* E N H A N C E D
* S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G
*
* for ReShade 3.0+
*/
//------------------- Preprocessor Settings -------------------
#if !defined(SMAA_PRESET_LOW) && !defined(SMAA_PRESET_MEDIUM) && !defined(SMAA_PRESET_HIGH) && !defined(SMAA_PRESET_ULTRA)
#define SMAA_PRESET_CUSTOM // Do not use a quality preset by default
#endif
//----------------------- UI Variables ------------------------
#include "ReShadeUI.fxh"
uniform int EdgeDetectionType < __UNIFORM_COMBO_INT1
ui_items = "Luminance edge detection\0Color edge detection\0Depth edge detection\0";
ui_label = "Edge Detection Type";
> = 1;
#ifdef SMAA_PRESET_CUSTOM
uniform float EdgeDetectionThreshold < __UNIFORM_DRAG_FLOAT1
ui_min = 0.05; ui_max = 0.20; ui_step = 0.001;
ui_tooltip = "Edge detection threshold. If SMAA misses some edges try lowering this slightly.";
ui_label = "Edge Detection Threshold";
> = 0.10;
uniform float DepthEdgeDetectionThreshold < __UNIFORM_DRAG_FLOAT1
ui_min = 0.001; ui_max = 0.10; ui_step = 0.001;
ui_tooltip = "Depth Edge detection threshold. If SMAA misses some edges try lowering this slightly.";
ui_label = "Depth Edge Detection Threshold";
> = 0.01;
uniform int MaxSearchSteps < __UNIFORM_SLIDER_INT1
ui_min = 0; ui_max = 112;
ui_label = "Max Search Steps";
ui_tooltip = "Determines the radius SMAA will search for aliased edges.";
> = 32;
uniform int MaxSearchStepsDiagonal < __UNIFORM_SLIDER_INT1
ui_min = 0; ui_max = 20;
ui_label = "Max Search Steps Diagonal";
ui_tooltip = "Determines the radius SMAA will search for diagonal aliased edges";
> = 16;
uniform int CornerRounding < __UNIFORM_SLIDER_INT1
ui_min = 0; ui_max = 100;
ui_label = "Corner Rounding";
ui_tooltip = "Determines the percent of anti-aliasing to apply to corners.";
> = 25;
uniform bool PredicationEnabled < __UNIFORM_INPUT_BOOL1
ui_label = "Enable Predicated Thresholding";
> = false;
uniform float PredicationThreshold < __UNIFORM_DRAG_FLOAT1
ui_min = 0.005; ui_max = 1.00; ui_step = 0.01;
ui_tooltip = "Threshold to be used in the additional predication buffer.";
ui_label = "Predication Threshold";
> = 0.01;
uniform float PredicationScale < __UNIFORM_SLIDER_FLOAT1
ui_min = 1; ui_max = 8;
ui_tooltip = "How much to scale the global threshold used for luma or color edge.";
ui_label = "Predication Scale";
> = 2.0;
uniform float PredicationStrength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0; ui_max = 4;
ui_tooltip = "How much to locally decrease the threshold.";
ui_label = "Predication Strength";
> = 0.4;
#endif
uniform int DebugOutput < __UNIFORM_COMBO_INT1
ui_items = "None\0View edges\0View weights\0";
ui_label = "Debug Output";
> = false;
#ifdef SMAA_PRESET_CUSTOM
#define SMAA_PREDICATION PredicationEnabled
#define SMAA_THRESHOLD EdgeDetectionThreshold
#define SMAA_DEPTH_THRESHOLD DepthEdgeDetectionThreshold
#define SMAA_MAX_SEARCH_STEPS MaxSearchSteps
#define SMAA_MAX_SEARCH_STEPS_DIAG MaxSearchStepsDiagonal
#define SMAA_CORNER_ROUNDING CornerRounding
#define SMAA_PREDICATION_THRESHOLD PredicationThreshold
#define SMAA_PREDICATION_SCALE PredicationScale
#define SMAA_PREDICATION_STRENGTH PredicationStrength
#endif
#define SMAA_RT_METRICS float4(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT, BUFFER_WIDTH, BUFFER_HEIGHT)
#define SMAA_CUSTOM_SL 1
#define SMAATexture2D(tex) sampler tex
#define SMAATexturePass2D(tex) tex
#define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, coord))
#define SMAASampleLevelZeroPoint(tex, coord) SMAASampleLevelZero(tex, coord)
#define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlodoffset(tex, float4(coord, coord), offset)
#define SMAASample(tex, coord) tex2D(tex, coord)
#define SMAASamplePoint(tex, coord) SMAASample(tex, coord)
#define SMAASampleOffset(tex, coord, offset) tex2Doffset(tex, coord, offset)
#define SMAA_BRANCH [branch]
#define SMAA_FLATTEN [flatten]
#if (__RENDERER__ == 0xb000 || __RENDERER__ == 0xb100)
#define SMAAGather(tex, coord) tex2Dgather(tex, coord, 0)
#endif
#include "SMAA.fxh"
#include "ReShade.fxh"
// Textures
texture depthTex < pooled = true; >
{
Width = BUFFER_WIDTH;
Height = BUFFER_HEIGHT;
Format = R16F;
};
texture edgesTex < pooled = true; >
{
Width = BUFFER_WIDTH;
Height = BUFFER_HEIGHT;
Format = RG8;
};
texture blendTex < pooled = true; >
{
Width = BUFFER_WIDTH;
Height = BUFFER_HEIGHT;
Format = RGBA8;
};
texture areaTex < source = "AreaTex.png"; >
{
Width = 160;
Height = 560;
Format = RG8;
};
texture searchTex < source = "SearchTex.png"; >
{
Width = 64;
Height = 16;
Format = R8;
};
// Samplers
sampler depthLinearSampler
{
Texture = depthTex;
};
sampler colorGammaSampler
{
Texture = ReShade::BackBufferTex;
AddressU = Clamp; AddressV = Clamp;
MipFilter = Point; MinFilter = Linear; MagFilter = Linear;
SRGBTexture = false;
};
sampler colorLinearSampler
{
Texture = ReShade::BackBufferTex;
AddressU = Clamp; AddressV = Clamp;
MipFilter = Point; MinFilter = Linear; MagFilter = Linear;
SRGBTexture = true;
};
sampler edgesSampler
{
Texture = edgesTex;
AddressU = Clamp; AddressV = Clamp;
MipFilter = Linear; MinFilter = Linear; MagFilter = Linear;
SRGBTexture = false;
};
sampler blendSampler
{
Texture = blendTex;
AddressU = Clamp; AddressV = Clamp;
MipFilter = Linear; MinFilter = Linear; MagFilter = Linear;
SRGBTexture = false;
};
sampler areaSampler
{
Texture = areaTex;
AddressU = Clamp; AddressV = Clamp; AddressW = Clamp;
MipFilter = Linear; MinFilter = Linear; MagFilter = Linear;
SRGBTexture = false;
};
sampler searchSampler
{
Texture = searchTex;
AddressU = Clamp; AddressV = Clamp; AddressW = Clamp;
MipFilter = Point; MinFilter = Point; MagFilter = Point;
SRGBTexture = false;
};
// Vertex shaders
void SMAAEdgeDetectionWrapVS(
in uint id : SV_VertexID,
out float4 position : SV_Position,
out float2 texcoord : TEXCOORD0,
out float4 offset[3] : TEXCOORD1)
{
PostProcessVS(id, position, texcoord);
SMAAEdgeDetectionVS(texcoord, offset);
}
void SMAABlendingWeightCalculationWrapVS(
in uint id : SV_VertexID,
out float4 position : SV_Position,
out float2 texcoord : TEXCOORD0,
out float2 pixcoord : TEXCOORD1,
out float4 offset[3] : TEXCOORD2)
{
PostProcessVS(id, position, texcoord);
SMAABlendingWeightCalculationVS(texcoord, pixcoord, offset);
}
void SMAANeighborhoodBlendingWrapVS(
in uint id : SV_VertexID,
out float4 position : SV_Position,
out float2 texcoord : TEXCOORD0,
out float4 offset : TEXCOORD1)
{
PostProcessVS(id, position, texcoord);
SMAANeighborhoodBlendingVS(texcoord, offset);
}
// Pixel shaders
float SMAADepthLinearizationPS(
float4 position : SV_Position,
float2 texcoord : TEXCOORD) : SV_Target
{
return ReShade::GetLinearizedDepth(texcoord);
}
float2 SMAAEdgeDetectionWrapPS(
float4 position : SV_Position,
float2 texcoord : TEXCOORD0,
float4 offset[3] : TEXCOORD1) : SV_Target
{
if (EdgeDetectionType == 0 && SMAA_PREDICATION == true)
return SMAALumaEdgePredicationDetectionPS(texcoord, offset, colorGammaSampler, depthLinearSampler);
else if (EdgeDetectionType == 0)
return SMAALumaEdgeDetectionPS(texcoord, offset, colorGammaSampler);
if (EdgeDetectionType == 2)
return SMAADepthEdgeDetectionPS(texcoord, offset, depthLinearSampler);
if (SMAA_PREDICATION)
return SMAAColorEdgePredicationDetectionPS(texcoord, offset, colorGammaSampler, depthLinearSampler);
else
return SMAAColorEdgeDetectionPS(texcoord, offset, colorGammaSampler);
}
float4 SMAABlendingWeightCalculationWrapPS(
float4 position : SV_Position,
float2 texcoord : TEXCOORD0,
float2 pixcoord : TEXCOORD1,
float4 offset[3] : TEXCOORD2) : SV_Target
{
return SMAABlendingWeightCalculationPS(texcoord, pixcoord, offset, edgesSampler, areaSampler, searchSampler, 0.0);
}
float3 SMAANeighborhoodBlendingWrapPS(
float4 position : SV_Position,
float2 texcoord : TEXCOORD0,
float4 offset : TEXCOORD1) : SV_Target
{
if (DebugOutput == 1)
return tex2D(edgesSampler, texcoord).rgb;
if (DebugOutput == 2)
return tex2D(blendSampler, texcoord).rgb;
return SMAANeighborhoodBlendingPS(texcoord, offset, colorLinearSampler, blendSampler).rgb;
}
// Rendering passes
technique SMAA
{
pass LinearizeDepthPass
{
VertexShader = PostProcessVS;
PixelShader = SMAADepthLinearizationPS;
RenderTarget = depthTex;
}
pass EdgeDetectionPass
{
VertexShader = SMAAEdgeDetectionWrapVS;
PixelShader = SMAAEdgeDetectionWrapPS;
RenderTarget = edgesTex;
ClearRenderTargets = true;
StencilEnable = true;
StencilPass = REPLACE;
StencilRef = 1;
}
pass BlendWeightCalculationPass
{
VertexShader = SMAABlendingWeightCalculationWrapVS;
PixelShader = SMAABlendingWeightCalculationWrapPS;
RenderTarget = blendTex;
ClearRenderTargets = true;
StencilEnable = true;
StencilPass = KEEP;
StencilFunc = EQUAL;
StencilRef = 1;
}
pass NeighborhoodBlendingPass
{
VertexShader = SMAANeighborhoodBlendingWrapVS;
PixelShader = SMAANeighborhoodBlendingWrapPS;
StencilEnable = false;
SRGBWriteEnable = true;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
#include "ReShadeUI.fxh"
uniform float3 Tint < __UNIFORM_COLOR_FLOAT3
> = float3(0.55, 0.43, 0.42);
uniform float Strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Adjust the strength of the effect.";
> = 0.58;
#include "ReShade.fxh"
float3 TintPass(float4 vois : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 col = tex2D(ReShade::BackBuffer, texcoord).rgb;
return lerp(col, col * Tint * 2.55, Strength);
}
technique Tint
{
pass
{
VertexShader = PostProcessVS;
PixelShader = TintPass;
}
}

View File

@ -0,0 +1,768 @@
////---------------//
///**Smart Sharp**///
//---------------////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Depth Based Unsharp Mask Bilateral Contrast Adaptive Sharpening v2.4
// For Reshade 3.0+
// ---------------------------------
// https://web.stanford.edu/class/cs448f/lectures/2.1/Sharpening.pdf
//
// Bilateral Filter Made by mrharicot ported over to Reshade by BSD
// GitHub Link for sorce info github.com/SableRaf/Filters4Processin
// Shadertoy Link https://www.shadertoy.com/view/4dfGDH Thank You.
//
// Everyone wants to best the bilateral filter.....
//
//
// LICENSE
// ============
// Overwatch & Code out side the work of people mention above is licenses under: Attribution-NoDerivatives 4.0 International
//
// You are free to:
// Share - copy and redistribute the material in any medium or format
// for any purpose, even commercially.
// The licensor cannot revoke these freedoms as long as you follow the license terms.
// Under the following terms:
// Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
// You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//
// NoDerivatives - If you remix, transform, or build upon the material, you may not distribute the modified material.
//
// No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//
// https://creativecommons.org/licenses/by-nd/4.0/
//
// Have fun,
// Jose Negrete AKA BlueSkyDefender
//
// https://github.com/BlueSkyDefender/Depth3D
// http://reshade.me/forum/shader-presentation/2128-sidebyside-3d-depth-map-based-stereoscopic-shader
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if exists "Overwatch.fxh" //Overwatch Intercepter//
#include "Overwatch.fxh"
#else //DA_W Depth_Linearization | DB_X Depth_Flip
static const float DA_W = 0.0, DB_X = 0;
#define NC 0
#define NP 0
#endif
// This is the practical limit for the algorithm's scaling ability. Example resolutions;
// 1280x720 -> 1080p = 2.25x area
// 1536x864 -> 1080p = 1.56x area
// 1792x1008 -> 1440p = 2.04x area
// 1920x1080 -> 1440p = 1.78x area
// 1920x1080 -> 4K = 4.0x area
// 2048x1152 -> 1440p = 1.56x area
// 2560x1440 -> 4K = 2.25x area
// 3072x1728 -> 4K = 1.56x area
// Determines the power of the Bilateral Filter and sharpening quality. Lower the setting the more performance you would get along with lower quality.
// 0 = Off
// 1 = Low
// 2 = Default
// 3 = Medium
// 4 = High
// Default is off.
#define M_Quality 0 //Manualy set shader Quality. Defaults to 2 when set to off.
//Zero is Fast, a ''Optimized'' Bilateral Filtering approach wink wink and One is a Acuurate. Acuurate is the correct way of doing Bilateral filtering.
#define B_Accuracy 0 //Bilateral Accuracy
//Use this to enable motion Sharpen option also reduces perf a bit more
#define Motion_Sharpen 0
#define SRGB 0
// It is best to run Smart Sharp after tonemapping.
#if !defined(__RESHADE__) || __RESHADE__ < 40000
#define Compatibility 1
#else
#define Compatibility 0
#endif
/*
uniform float TEST <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
> = 0.0;
*/
uniform int Depth_Map <
ui_type = "combo";
ui_items = "Normal\0Reverse\0";
ui_label = "Custom Depth Map";
ui_tooltip = "Pick your Depth Map.";
ui_category = "Depth Buffer";
> = DA_W;
uniform float Depth_Map_Adjust <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 1.0; ui_max = 1000.0; ui_step = 0.125;
ui_label = "Depth Map Adjustment";
ui_tooltip = "Adjust the depth map and sharpness distance.";
ui_category = "Depth Buffer";
> = 250.0;
uniform bool Depth_Map_Flip <
ui_label = "Depth Map Flip";
ui_tooltip = "Flip the depth map if it is upside down.";
ui_category = "Depth Buffer";
> = DB_X;
uniform bool No_Depth_Map <
ui_label = "No Depth Map";
ui_tooltip = "If you have No Depth Buffer turn this On.";
ui_category = "Depth Buffer";
> = false;
uniform float Sharpness <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_label = "Sharpening Strength";
ui_min = 0.0; ui_max = 2.0;
ui_tooltip = "Scaled by adjusting this slider from Zero to One to increase sharpness of the image.\n"
"Zero = No Sharpening, to One = Full Sharpening, and Past One = Extra Crispy.\n"
"Number 0.625 is Equal to AMD FidelityFX Contrast Adaptive Sharpening at max settings.\n"
"Number 0.625 is default.";
ui_category = "Bilateral CAS";
> = 0.625;
uniform float B_Grounding <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_label = "Coarseness";
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Like Coffee pick how rough do you want this shader to be, really just adjusts the radius of the filter.\n"
"Fine -> Medium -> Coarse too what ever you think looks good.\n"
"Let me have fun with names and tooltips........\n"
"Number 0.0 is default.";
ui_category = "Bilateral CAS";
> = 0.0;
uniform bool CAM_IOB <
ui_label = "CAM Ignore Overbright";
ui_tooltip = "Instead of of allowing Overbright in the mask this allows sharpening of this area.\n"
"I think it's more accurate to leave this on.";
ui_category = "Bilateral CAS";
> = false;
uniform bool CA_Mask_Boost <
ui_label = "CAM Boost";
ui_tooltip = "This boosts the power of Contrast Adaptive Masking part of the shader.";
ui_category = "Bilateral CAS";
> = false;
uniform bool CA_Removal <
ui_label = "CAM Removal";
ui_tooltip = "This removes the extra Contrast Adaptive Masking part of the shader.\n"
"Keep in mind This filter already has a level of Contrast Masking.\n"
"This is for people who like the Raw look of Bilateral Sharpen.\n"
"Noise reduction from the Bilateral Filter applies automatically.";
ui_category = "Bilateral CAS";
> = false;
#if Motion_Sharpen
uniform int Local_Motion <
ui_type = "combo";
ui_items = "General Motion\0Local Motion\0";
ui_label = "View Mode";
ui_tooltip = "This is used to select between General Motion & Local Motion.\n"
"Default is General Motion.";
ui_category = "Motion Bilateral CAS";
> = 0;
uniform float GMD <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_label = "General Motion Detection";
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Increase the General Motion Detection power.\n"
"This is used to boost Sharpening strength by the user selected ammount.\n"
"Number Zero is default, Off.";
ui_category = "Motion Bilateral CAS";
> = 0.0;
uniform float MDSM <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_label = "Sharpen Multiplier";
ui_min = 1.0; ui_max = 10.0;
ui_tooltip = "Motion Detection Sharpen Multiplier.\n"
"This is the user set mutliplyer for how much you want to increase the base sharpen.\n"
"A Multiplier of 5 should be fine at base sharpness, Try messing around with this.\n"
"A Sharpen Multiplier of 2 is two times the user set Sharpening Strength.\n"
"Number 1 is default.";
ui_category = "Motion Bilateral CAS";
> = 1.0;
#else
static const int Local_Motion = 0;
static const float GMD = 0.0;
static const float MDSM = 0.0;
#endif
uniform int Debug_View <
ui_type = "combo";
ui_items = "Normal\0Sharpen View\0Depth Masking\0CAS Mask\0Noise Mask\0";
ui_label = "Debug View";
ui_tooltip = "This is to DeBug Smart Sharp and lets you fine tune the shader.\n"
"Let me have fun with names and tooltips.......";
ui_category = "Debug";
> = 0;
uniform int F_DeNoise <
ui_type = "combo";
ui_items = "Off\0Level One DeNoiser\0Level Two DeNoiser\0";
ui_label = "Smart Denoiser Options";
ui_tooltip = "This Denoiser can help with Noise in the image.\n"
"LvL One DeNoiser Works with Smart Sharp Only.\n"
"LvL Two DeNoiser Works with other shaders. But, it's a little stronger.\n"
"LvL Three DeNoiser N/A Future add on.";
ui_category = "Extra Menu";
> = false;
uniform float Denoise_Power <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_label = "Denoise Power";
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Increase the Sharpening strength of the DeNoiser.\n"
"Number Zero is default, Off.";
ui_category = "Extra Menu";
> = 0.5;
uniform bool ClampSharp <
ui_label = "Clamp Sharpen";
ui_tooltip = "This Clamps the output of the Sharpen Shader.";
ui_category = "Extra Menu";
> = true;
#define Quality 2
#if M_Quality > 0
#undef Quality
#define Quality M_Quality
#endif
/////////////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define TexSize float2(BUFFER_WIDTH, BUFFER_HEIGHT)
uniform float timer < source = "timer"; >;
//Since I don't use this for the incorrect Blur I keep it here for the correct one.
#define SIGMA 15
#define BSIGMA 0.25 //Now I need to keep this one below 0.25 or Halo will happen MC and everything.
#if Quality == 1
#define MSIZE 3
#endif
#if Quality == 2
#define MSIZE 5
#endif
#if Quality == 3
#define MSIZE 7
#endif
#if Quality == 4
#define MSIZE 9
#endif
texture DepthBufferTex : DEPTH;
sampler DepthBuffer
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
#if SRGB
SRGBTexture = true;
#endif
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if Motion_Sharpen
texture CurrentBBSSTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler CBBSS
{
Texture = CurrentBBSSTex;
};
texture PastBBSSTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler PBBSS
{
Texture = PastBBSSTex;
};
texture DownSTex {Width = 256; Height = 256; Format = R8; MipLevels = 9;};
sampler DSM
{
Texture = DownSTex;
};
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Depth(in float2 texcoord : TEXCOORD0)
{
if (Depth_Map_Flip)
texcoord.y = 1 - texcoord.y;
float zBuffer = tex2Dlod(DepthBuffer, float4(texcoord,0,0)).x; //Depth Buffer
//Conversions to linear space.....
//Near & Far Adjustment
float Far = 1.0, Near = 0.125/Depth_Map_Adjust; //Division Depth Map Adjust - Near
float2 Z = float2( zBuffer, 1-zBuffer );
if (Depth_Map == 0)//DM0. Normal
zBuffer = Far * Near / (Far + Z.x * (Near - Far));
else if (Depth_Map == 1)//DM1. Reverse
zBuffer = Far * Near / (Far + Z.y * (Near - Far));
return saturate(zBuffer);
}
float3 RGBtoYCbCr(float3 rgb)
{ float C[1];//The Chronicles of Riddick: Assault on Dark Athena FIX I don't know why it works.......
float Y = .299 * rgb.x + .587 * rgb.y + .114 * rgb.z; // Luminance
float Cb = -.169 * rgb.x - .331 * rgb.y + .500 * rgb.z; // Chrominance Blue
float Cr = .500 * rgb.x - .419 * rgb.y - .081 * rgb.z; // Chrominance Red
return float3(Y,Cb + 128./255.,Cr + 128./255.);
}
float3 YCbCrtoRGB(float3 ycc)
{
float3 c = ycc - float3(0., 128./255., 128./255.);
float R = c.x + 1.400 * c.z;
float G = c.x - 0.343 * c.y - 0.711 * c.z;
float B = c.x + 1.765 * c.y;
return float3(R,G,B);
}
float Min3(float x, float y, float z)
{
return min(x, min(y, z));
}
float Max3(float x, float y, float z)
{
return max(x, max(y, z));
}
float normpdf(in float x, in float sigma)
{
return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;
}
float normpdf3(in float3 v, in float sigma)
{
return 0.39894*exp(-0.5*dot(v,v)/(sigma*sigma))/sigma;
}
float3 BB(in float2 texcoord, float2 AD)
{
return tex2Dlod(BackBuffer, float4(texcoord + AD,0,0)).rgb;
}
float LI(float3 RGB)
{
return dot(RGB,float3(0.2126, 0.7152, 0.0722));
}
float GT() { return lerp(1.0,0.5,B_Grounding);}
float MotionSharpen(float2 texcoord)
{
#if Motion_Sharpen
float2 PS = pix * 5.0;
float BlurMotion = tex2D(DSM,texcoord).x;
if(Local_Motion)
{
BlurMotion += tex2D(DSM,texcoord + float2(0,PS.y)).x;
BlurMotion += tex2D(DSM,texcoord + float2(PS.x,0)).x;
BlurMotion += tex2D(DSM,texcoord + float2(-PS.x,0)).x;
BlurMotion += tex2D(DSM,texcoord + float2(0,-PS.y)).x;
return (BlurMotion * 0.2) * 12.5;
}
else
return tex2Dlod(DSM,float4(texcoord,0,11)).x * lerp(0.0,25.0,GMD);
#else
return 0;
#endif
}
float4 GetBBfetch(float2 texcoord, int2 Offset )
{
return tex2Dfetch(BackBuffer, texcoord * TexSize + Offset );
}
void Smart_Sharp( float2 texcoord,inout float Edge, inout float3 LVB, inout float CAM)
{
//Bilateral Filter//
const int kSize = MSIZE * 0.5; // Default M-size is Quality 2 so [MSIZE 3] [MSIZE 5] [MSIZE 7] [MSIZE 9] / 2.
float mnRGB, mxRGB, t, l, r, s;
// Find Edges
t = LI(GetBBfetch(texcoord , int2( 0,-2) ).rgb);
s = LI(GetBBfetch(texcoord , int2( 0, 2) ).rgb);
l = LI(GetBBfetch(texcoord , int2(-2, 0) ).rgb);
r = LI(GetBBfetch(texcoord , int2( 2, 0) ).rgb);
float2 n = float2(t - s,-(r - l));
float nl = length(n);
//Later I will add a 3x3 Medium Filter for LVL Three WIP
float3 final_color, c = BB(texcoord.xy,0), cc;
float2 RPC_WS = pix;
float bZ = rcp(normpdf(0.0, BSIGMA)), Z, factor;
#if B_Accuracy
float kernal[MSIZE];
[unroll]
for (int o = 0; o <= kSize; ++o)
{
kernal[kSize+o] = kernal[kSize-o] = normpdf(o, SIGMA);
}
#endif
[loop]
for (int i=-kSize; i <= kSize; ++i)
{
for (int j=-kSize; j <= kSize; ++j)
{
cc = BB(texcoord.xy, float2(i,j) * RPC_WS * rcp(kSize * GT()) );
#if B_Accuracy
factor = normpdf3(cc-c, BSIGMA) * bZ * kernal[kSize+j] * kernal[kSize+i];
#else
factor = normpdf3(cc-c, BSIGMA);
#endif
Z += factor;
final_color += factor * cc;
}
}
final_color = saturate(final_color/Z);
mnRGB = min( min( LI(c), LI(final_color)), LI(cc));
mxRGB = max( max( LI(c), LI(final_color)), LI(cc));
// Smooth minimum distance to signal limit divided by smooth max.
float rcpMRGB = rcp(mxRGB), RGB_D = saturate(min(mnRGB, 1.0 - mxRGB) * rcpMRGB);
if( CAM_IOB )
RGB_D = saturate(min(mnRGB, 2.0 - mxRGB) * rcpMRGB);
// Shaping amount of sharpening masked
float CAS_Mask = RGB_D, Sharp = Sharpness, MD = MotionSharpen(texcoord);
if(GMD > 0 || Local_Motion)
Sharp = Sharpness * lerp( 1,MDSM,saturate(MD));
if(CA_Mask_Boost)
CAS_Mask = lerp(CAS_Mask,CAS_Mask * CAS_Mask,saturate(Sharp * 0.5));
if(CA_Removal)
CAS_Mask = 1;
//Edge Detection
Edge = nl;
//Low Variance Blur
LVB = final_color;
//Contrast Adaptive Masking
CAM = CAS_Mask;
}
float4 Sharpen_Out(float2 texcoord)
{
float Noise, Edge, CAM, Sharpen_Power = Sharpness, MD = MotionSharpen(texcoord);
float3 LVB;
float4 color = tex2D(BackBuffer, texcoord),Done;
Smart_Sharp( texcoord, Edge, LVB, CAM);
if(GMD > 0 || Local_Motion)
Sharpen_Power = Sharpness * lerp( 1,MDSM,saturate(MD));
if( F_DeNoise )
{ //Noise reduction for pure Bilateral Sharp
Done = color;
Done /= LVB;
Done = min( Min3(Done.r,Done.g,Done.b) ,2-Max3(Done.r,Done.g,Done.b));
Noise = saturate(length(Done > 0.950f));
}
Sharpen_Power *= 3.1;
float3 Sharpen;// = (tex2D(BackBuffer,texcoord).rgb - LVB) * Sharpen_Power ;
//RGBtoYCbCr(
//YCbCrtoRGB(
Sharpen = RGBtoYCbCr(tex2D(BackBuffer,texcoord).rgb - LVB);
Sharpen.x *= Sharpen_Power;
Sharpen = YCbCrtoRGB(Sharpen);
if (ClampSharp)
Sharpen = saturate(Sharpen);
/*
float Grayscale_Sharpen = LI(Sharpen);
if (Output_Selection == 0)
Sharpen = lerp(Grayscale_Sharpen,Sharpen,0.5);
else if (Output_Selection == 1)
Sharpen = Sharpen;
else
Sharpen = Grayscale_Sharpen;
*/
float SNoise = Noise;
Noise = saturate(lerp( 1, Noise , Denoise_Power));
Edge = saturate(Edge > 0.125);
Sharpen = lerp( max(0,lerp( 0 , Sharpen , Noise )) , Sharpen, Edge) ;
if( Debug_View == 1)
{
Sharpen = Sharpen;
}
else
{
if( F_DeNoise )
{
float3 B = LVB, C = F_DeNoise == 1 ? color.rgb : B, S = color.rgb + Sharpen;
C = RGBtoYCbCr(C); S = RGBtoYCbCr(S); B = RGBtoYCbCr(B);
C.x = lerp( C.x , S.x , Noise );
C.yz = lerp( Debug_View == 4 ? 1 : B.yz , S.yz , SNoise );
Sharpen.rgb = YCbCrtoRGB(lerp( C , S, Edge )) ;
}
else
Sharpen.rgb = color.rgb + Sharpen;
}
return float4(lerp(Debug_View == 1 ? 0 : color.rgb,Sharpen, CAM * saturate(Sharpen_Power)),CAM); //Sharpen Out
}
float3 ShaderOut(float2 texcoord)
{
float3 Out, Luma, Sharpen = Sharpen_Out(texcoord).rgb,BB = tex2D(BackBuffer,texcoord).rgb;
float DB = Depth(texcoord).r;
if(No_Depth_Map)
DB = 0.0;
if (Debug_View == 0)
Out.rgb = lerp(Sharpen, BB, DB);
else if (Debug_View == 1)
Out.rgb = Sharpen_Out(texcoord).rgb;
else if (Debug_View == 2)
Out.rgb = lerp(float3(1., 0., 1.),tex2D(BackBuffer,float2(texcoord.x,texcoord.y)).rgb,DB);
else if (Debug_View == 3)
Out.rgb = lerp(1.0,Sharpen_Out(texcoord).www,1-DB);
else if (Debug_View == 4)
Out.rgb = lerp(Sharpen, BB, DB);
#if Motion_Sharpen
if (Debug_View >= 1)
{
if(texcoord.y < 0.666 && texcoord.y > 0.333 && texcoord.x < 0.666 && texcoord.x > 0.333)
Out = lerp( 0,MDSM,MotionSharpen(texcoord * 3 - 1.0));
}
#endif
return Out;
}
#if Motion_Sharpen
float CBackBuffer_SS(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return dot(tex2D(BackBuffer,texcoord),0.333);
}
float PBackBuffer_SS(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D(CBBSS,texcoord).x;
}
float2 DownSampleMotion(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{ float Motion = abs(tex2D(CBBSS,texcoord).x - tex2D(PBBSS,texcoord).x);
return Motion;
}
#endif
////////////////////////////////////////////////////////Logo/////////////////////////////////////////////////////////////////////////
float3 Out(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{ //Overwatch integration
float PosX = 0.9525f*BUFFER_WIDTH*pix.x,PosY = 0.975f*BUFFER_HEIGHT*pix.y, Text_Timer = 12500, BT = smoothstep(0,1,sin(timer*(3.75/1000)));
float D,E,P,T,H,Three,DD,Dot,I,N,F,O,R,EE,A,DDD,HH,EEE,L,PP,NN,PPP,C,Not,No;
float3 Color = ShaderOut(texcoord).rgb;
//Color = tex2Dlod(DSM,float4(texcoord,0,11)).x * lerp(0.0,25.0,GMD);
if(NC || NP)
Text_Timer = 18750;
[branch] if(timer <= Text_Timer)
{
//DEPTH
//D
float PosXD = -0.035+PosX, offsetD = 0.001;
float OneD = all( abs(float2( texcoord.x -PosXD, texcoord.y-PosY)) < float2(0.0025,0.009));
float TwoD = all( abs(float2( texcoord.x -PosXD-offsetD, texcoord.y-PosY)) < float2(0.0025,0.007));
D = OneD-TwoD;
//E
float PosXE = -0.028+PosX, offsetE = 0.0005;
float OneE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.009));
float TwoE = all( abs(float2( texcoord.x -PosXE-offsetE, texcoord.y-PosY)) < float2(0.0025,0.007));
float ThreeE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.001));
E = (OneE-TwoE)+ThreeE;
//P
float PosXP = -0.0215+PosX, PosYP = -0.0025+PosY, offsetP = 0.001, offsetP1 = 0.002;
float OneP = all( abs(float2( texcoord.x -PosXP, texcoord.y-PosYP)) < float2(0.0025,0.009*0.775));
float TwoP = all( abs(float2( texcoord.x -PosXP-offsetP, texcoord.y-PosYP)) < float2(0.0025,0.007*0.680));
float ThreeP = all( abs(float2( texcoord.x -PosXP+offsetP1, texcoord.y-PosY)) < float2(0.0005,0.009));
P = (OneP-TwoP) + ThreeP;
//T
float PosXT = -0.014+PosX, PosYT = -0.008+PosY;
float OneT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosYT)) < float2(0.003,0.001));
float TwoT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosY)) < float2(0.000625,0.009));
T = OneT+TwoT;
//H
float PosXH = -0.0072+PosX;
float OneH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.001));
float TwoH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.009));
float ThreeH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.00325,0.009));
H = (OneH-TwoH)+ThreeH;
//Three
float offsetFive = 0.001, PosX3 = -0.001+PosX;
float OneThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.009));
float TwoThree = all( abs(float2( texcoord.x -PosX3 - offsetFive, texcoord.y-PosY)) < float2(0.003,0.007));
float ThreeThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.001));
Three = (OneThree-TwoThree)+ThreeThree;
//DD
float PosXDD = 0.006+PosX, offsetDD = 0.001;
float OneDD = all( abs(float2( texcoord.x -PosXDD, texcoord.y-PosY)) < float2(0.0025,0.009));
float TwoDD = all( abs(float2( texcoord.x -PosXDD-offsetDD, texcoord.y-PosY)) < float2(0.0025,0.007));
DD = OneDD-TwoDD;
//Dot
float PosXDot = 0.011+PosX, PosYDot = 0.008+PosY;
float OneDot = all( abs(float2( texcoord.x -PosXDot, texcoord.y-PosYDot)) < float2(0.00075,0.0015));
Dot = OneDot;
//INFO
//I
float PosXI = 0.0155+PosX, PosYI = 0.004+PosY, PosYII = 0.008+PosY;
float OneI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosY)) < float2(0.003,0.001));
float TwoI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYI)) < float2(0.000625,0.005));
float ThreeI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYII)) < float2(0.003,0.001));
I = OneI+TwoI+ThreeI;
//N
float PosXN = 0.0225+PosX, PosYN = 0.005+PosY,offsetN = -0.001;
float OneN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN)) < float2(0.002,0.004));
float TwoN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN - offsetN)) < float2(0.003,0.005));
N = OneN-TwoN;
//F
float PosXF = 0.029+PosX, PosYF = 0.004+PosY, offsetF = 0.0005, offsetF1 = 0.001;
float OneF = all( abs(float2( texcoord.x -PosXF-offsetF, texcoord.y-PosYF-offsetF1)) < float2(0.002,0.004));
float TwoF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0025,0.005));
float ThreeF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0015,0.00075));
F = (OneF-TwoF)+ThreeF;
//O
float PosXO = 0.035+PosX, PosYO = 0.004+PosY;
float OneO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.003,0.005));
float TwoO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.002,0.003));
O = OneO-TwoO;
//Text Warnings: No Profile / Not Compatible
//PosY += 0.953;
PosX -= 0.483;
float PosXNN = -0.458+PosX, offsetNN = 0.0015;
float OneNN = all( abs(float2( texcoord.x -PosXNN, texcoord.y-PosY)) < float2(0.00325,0.009));
float TwoNN = all( abs(float2( texcoord.x -PosXNN, texcoord.y-PosY-offsetNN)) < float2(0.002,0.008));
NN = OneNN-TwoNN;
//PPP
float PosXPPP = -0.451+PosX, PosYPPP = -0.0025+PosY, offsetPPP = 0.001, offsetPPP1 = 0.002;
float OnePPP = all( abs(float2( texcoord.x -PosXPPP, texcoord.y-PosYPPP)) < float2(0.0025,0.009*0.775));
float TwoPPP = all( abs(float2( texcoord.x -PosXPPP-offsetPPP, texcoord.y-PosYPPP)) < float2(0.0025,0.007*0.680));
float ThreePPP = all( abs(float2( texcoord.x -PosXPPP+offsetPPP1, texcoord.y-PosY)) < float2(0.0005,0.009));
PPP = (OnePPP-TwoPPP) + ThreePPP;
//C
float PosXC = -0.450+PosX, offsetC = 0.001;
float OneC = all( abs(float2( texcoord.x -PosXC, texcoord.y-PosY)) < float2(0.0035,0.009));
float TwoC = all( abs(float2( texcoord.x -PosXC-offsetC, texcoord.y-PosY)) < float2(0.0025,0.007));
C = OneC-TwoC;
if(NP)
No = (NN + PPP) * BT; //Blinking Text
if(NC)
Not = (NN + C) * BT; //Blinking Text
//Website
return D+E+P+T+H+Three+DD+Dot+I+N+F+O+No+Not ? (1-texcoord.y*50.0+48.85)*texcoord.y-0.500: Color;
}
else
return Color;
}
///////////////////////////////////////////////////////////ReShade.fxh/////////////////////////////////////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
//*Rendering passes*//
technique Smart_Sharp
< ui_tooltip = "Suggestion : You Can Enable 'Performance Mode Checkbox,' in the lower bottom right of the ReShade's Main UI.\n"
" Do this once you set your Smart Sharp settings of course."; >
{
#if Motion_Sharpen // Motion Sharpen makes this shader slower.
pass PBB //Done this way to keep Freestyle comp.
{
VertexShader = PostProcessVS;
PixelShader = PBackBuffer_SS;
RenderTarget = PastBBSSTex;
}
pass CBB
{
VertexShader = PostProcessVS;
PixelShader = CBackBuffer_SS;
RenderTarget = CurrentBBSSTex;
}
pass Down_Sample_Motion
{
VertexShader = PostProcessVS;
PixelShader = DownSampleMotion;
RenderTarget = DownSTex;
}
#endif
pass UnsharpMask
{
VertexShader = PostProcessVS;
PixelShader = Out;
#if SRGB
SRGBWriteEnable = true;
#endif
}
}

View File

@ -0,0 +1,176 @@
/*------------------.
| :: Description :: |
'-------------------/
Splitscreen (version 2.0)
Author: CeeJay.dk
License: MIT
About:
Displays the image before and after it has been modified by effects using a splitscreen
Ideas for future improvement:
*
History:
(*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility
Version 1.0
* Does a splitscreen before/after view
Version 2.0
* Ported to Reshade 3.x
* Added UI settings.
* Added Diagonal split mode
- Removed curvy mode. I didn't like how it looked.
- Threatened other modes to behave or they would be next.
*/
/*------------------.
| :: UI Settings :: |
'------------------*/
#include "ReShadeUI.fxh"
uniform int splitscreen_mode <
ui_type = "combo";
ui_label = "Mode";
ui_tooltip = "Choose a mode";
//ui_category = "";
ui_items =
"Vertical 50/50 split\0"
"Vertical 25/50/25 split\0"
"Angled 50/50 split\0"
"Angled 25/50/25 split\0"
"Horizontal 50/50 split\0"
"Horizontal 25/50/25 split\0"
"Diagonal split\0"
;
> = 0;
/*---------------.
| :: Includes :: |
'---------------*/
#include "ReShade.fxh"
/*-------------------------.
| :: Texture and sampler:: |
'-------------------------*/
texture Before { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
sampler Before_sampler { Texture = Before; };
/*-------------.
| :: Effect :: |
'-------------*/
float4 PS_Before(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
return tex2D(ReShade::BackBuffer, texcoord);
}
float4 PS_After(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color;
// -- Vertical 50/50 split --
[branch] if (splitscreen_mode == 0)
color = (texcoord.x < 0.5 ) ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord);
// -- Vertical 25/50/25 split --
[branch] if (splitscreen_mode == 1)
{
//Calculate the distance from center
float dist = abs(texcoord.x - 0.5);
//Further than 1/4 away from center?
dist = saturate(dist - 0.25);
color = dist ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord);
}
// -- Angled 50/50 split --
[branch] if (splitscreen_mode == 2)
{
//Calculate the distance from center
float dist = ((texcoord.x - 3.0/8.0) + (texcoord.y * 0.25));
//Further than 1/4 away from center?
dist = saturate(dist - 0.25);
color = dist ? tex2D(ReShade::BackBuffer, texcoord) : tex2D(Before_sampler, texcoord);
}
// -- Angled 25/50/25 split --
[branch] if (splitscreen_mode == 3)
{
//Calculate the distance from center
float dist = ((texcoord.x - 3.0/8.0) + (texcoord.y * 0.25));
dist = abs(dist - 0.25);
//Further than 1/4 away from center?
dist = saturate(dist - 0.25);
color = dist ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord);
}
// -- Horizontal 50/50 split --
[branch] if (splitscreen_mode == 4)
color = (texcoord.y < 0.5) ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord);
// -- Horizontal 25/50/25 split --
[branch] if (splitscreen_mode == 5)
{
//Calculate the distance from center
float dist = abs(texcoord.y - 0.5);
//Further than 1/4 away from center?
dist = saturate(dist - 0.25);
color = dist ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord);
}
// -- Diagonal split --
[branch] if (splitscreen_mode == 6)
{
//Calculate the distance from center
float dist = (texcoord.x + texcoord.y);
//Further than 1/2 away from center?
//dist = saturate(dist - 1.0);
color = (dist < 1.0) ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord);
}
return color;
}
/*-----------------.
| :: Techniques :: |
'-----------------*/
technique Before
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_Before;
RenderTarget = Before;
}
}
technique After
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_After;
}
}

View File

@ -0,0 +1,50 @@
/**
* Technicolor version 1.1
* Original by DKT70
* Optimized by CeeJay.dk
*/
#include "ReShadeUI.fxh"
uniform float Power < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 8.0;
> = 4.0;
uniform float3 RGBNegativeAmount < __UNIFORM_COLOR_FLOAT3
> = float3(0.88, 0.88, 0.88);
uniform float Strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Adjust the strength of the effect.";
> = 0.4;
#include "ReShade.fxh"
float3 TechnicolorPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
const float3 cyanfilter = float3(0.0, 1.30, 1.0);
const float3 magentafilter = float3(1.0, 0.0, 1.05);
const float3 yellowfilter = float3(1.6, 1.6, 0.05);
const float2 redorangefilter = float2(1.05, 0.620); // RG_
const float2 greenfilter = float2(0.30, 1.0); // RG_
const float2 magentafilter2 = magentafilter.rb; // R_B
float3 tcol = tex2D(ReShade::BackBuffer, texcoord).rgb;
float2 negative_mul_r = tcol.rg * (1.0 / (RGBNegativeAmount.r * Power));
float2 negative_mul_g = tcol.rg * (1.0 / (RGBNegativeAmount.g * Power));
float2 negative_mul_b = tcol.rb * (1.0 / (RGBNegativeAmount.b * Power));
float3 output_r = dot(redorangefilter, negative_mul_r).xxx + cyanfilter;
float3 output_g = dot(greenfilter, negative_mul_g).xxx + magentafilter;
float3 output_b = dot(magentafilter2, negative_mul_b).xxx + yellowfilter;
return lerp(tcol, output_r * output_g * output_b, Strength);
}
technique Technicolor
{
pass
{
VertexShader = PostProcessVS;
PixelShader = TechnicolorPass;
}
}

View File

@ -0,0 +1,62 @@
/**
* Technicolor2 version 1.0
* Original by Prod80
* Optimized by CeeJay.dk
*/
#include "ReShadeUI.fxh"
uniform float3 ColorStrength < __UNIFORM_COLOR_FLOAT3
ui_tooltip = "Higher means darker and more intense colors.";
> = float3(0.2, 0.2, 0.2);
uniform float Brightness < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.5; ui_max = 1.5;
ui_tooltip = "Higher means brighter image.";
> = 1.0;
uniform float Saturation < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.5;
ui_tooltip = "Additional saturation control since this effect tends to oversaturate the image.";
> = 1.0;
uniform float Strength < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Adjust the strength of the effect.";
> = 1.0;
#include "ReShade.fxh"
float3 TechnicolorPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = saturate(tex2D(ReShade::BackBuffer, texcoord).rgb);
float3 temp = 1.0 - color;
float3 target = temp.grg;
float3 target2 = temp.bbr;
float3 temp2 = color * target;
temp2 *= target2;
temp = temp2 * ColorStrength;
temp2 *= Brightness;
target = temp.grg;
target2 = temp.bbr;
temp = color - target;
temp += temp2;
temp2 = temp - target2;
color = lerp(color, temp2, Strength);
color = lerp(dot(color, 0.333), color, Saturation);
return color;
}
technique Technicolor2
{
pass
{
VertexShader = PostProcessVS;
PixelShader = TechnicolorPass;
}
}

View File

@ -0,0 +1,454 @@
////-------//
///**TAA**///
//-------////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Temporal AA "Epic Games" implementation + Some Magic:
//* For ReShade 3.0+ v 1.1
//* ---------------------------------
//* TAA
//* Due Diligence
//* Based on port by yvt
//* https://www.shadertoy.com/view/4tcXD2
//* https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf
//* If I missed any please tell me.
//*
//* LICENSE
//* ============
//* Image Contrast Enhancement is licenses under: Attribution-NoDerivatives 4.0 International
//*
//* You are free to:
//* Share - copy and redistribute the material in any medium or format
//* for any purpose, even commercially.
//* The licensor cannot revoke these freedoms as long as you follow the license terms.
//* Under the following terms:
//* Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made.
//* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
//*
//* NoDerivatives - If you remix, transform, or build upon the material, you may not distribute the modified material.
//*
//* No additional restrictions - You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//*
//* https://creativecommons.org/licenses/by-nd/4.0/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//*
//* Special thank you too "Jak0bW" j4712@web.de For Mouse Compatibility & Guidance.
//* Please feel free to message him for help and information
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if exists "Overwatch.fxh" //Overwatch Intercepter//
#include "Overwatch.fxh"
#else //DA_W Depth_Linearization | DB_X Depth_Flip
static const float DA_W = 0.0, DB_X = 0;
#define NC 0
#define NP 0
#endif
#define App_Sync 0
uniform float Clamping_Adjust <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0; ui_max = 1.0;
ui_label = "Clamping Adjust";
ui_tooltip = "Adjust Clamping that effects Blur.\n"
"Default is Zero.";
ui_category = "TAA";
> = 0.0;
uniform float Persistence <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.0; ui_max = 1.00;
ui_label = "User Adjust";
ui_tooltip = "Increase persistence of the frames this is really the Temporal Part.\n"
"Default is 0.25. But, a value around 0.05 is recommended.";
ui_category = "TAA";
> = 0.125;
uniform float Similarity <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = -1.0; ui_max = 1.0;
ui_label = "Depth Similarity";
ui_tooltip = "Extra Image clamping based on Depth Similarities between Past and Current Depth for DeGhosing TAA.\n"
"Works on Depth & Color Delta is Selected and Depth is working in the game.\n"
"Default is 0.25.";
ui_category = "TAA";
> = 0.25;
uniform int Delta <
ui_type = "combo";
ui_label = "Used Delta Masking";
ui_items = "Color Delta\0Depth Delta\0";
ui_label = "TAA";
ui_category = "TAA";
> = 0;
uniform float Delta_Power <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 0.0; ui_max = 1.0;
ui_label = "Color & Depth Delta Power";
ui_tooltip = "Extra Image clamping based on delta between Past and Current Depth Buffer.\n"
"Only works on Depth Delta is Selected and Depth is working in the game.\n"
"Default is 0.25.";
ui_category = "TAA";
> = 0.25;
//Depth Map//
uniform int Debug <
ui_type = "combo";
ui_items = "TAA\0Delta Clamping\0DeGhosting Mask\0Depth\0";
ui_label = "Debug View";
> = 0;
uniform int Depth_Map <
ui_type = "combo";
ui_items = "Normal\0Reverse\0";
ui_label = "Custom Depth Map";
ui_tooltip = "Pick your Depth Map.";
ui_category = "Depth Buffer";
> = DA_W;
uniform float Depth_Map_Adjust <
#if Compatibility
ui_type = "drag";
#else
ui_type = "slider";
#endif
ui_min = 1.0; ui_max = 1000.0; ui_step = 0.125;
ui_label = "Depth Map Adjustment";
ui_tooltip = "Adjust the depth map and sharpness distance.";
ui_category = "Depth Buffer";
> = 250.0;
uniform float Depth_CutOff <
ui_type = "drag";
ui_min = -1.0; ui_max = 1.0;
ui_label = "Depth CutOff point";
ui_tooltip = "Use this too set a TAA Cutoff point based on depth.\n"
"Default is 0.0.";
ui_category = "Depth Buffer";
> = 0.0;
uniform bool Depth_Map_Flip <
ui_label = "Depth Map Flip";
ui_tooltip = "Flip the depth map if it is upside down.";
ui_category = "Depth Buffer";
> = DB_X;
/////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
texture DepthBufferTex : DEPTH;
sampler DepthBuffer
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
};
texture CurrentBackBufferTAA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler CBackBuffer
{
Texture = CurrentBackBufferTAA;
};
texture CurrentDepthBufferTAA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R16f;};
sampler CDepthBuffer
{
Texture = CurrentDepthBufferTAA;
};
texture PastBackBufferTAA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler PBackBuffer
{
Texture = PastBackBufferTAA;
};
texture PastSingleBackBufferTAA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler PSBackBuffer
{
Texture = PastSingleBackBufferTAA;
};
texture PastSingleDepthBufferTAA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R16f;};
sampler PSDepthBuffer
{
Texture = PastSingleDepthBufferTAA;
};
//Total amount of frames since the game started.
uniform uint framecount < source = "framecount"; >;
uniform float timer < source = "timer"; >;
///////////////////////////////////////////////////////////TAA/////////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
#define iResolution float2(BUFFER_WIDTH, BUFFER_HEIGHT)
#define Alternate framecount % 2 == 0
float2 DepthM(float2 texcoord)
{
if (Depth_Map_Flip)
texcoord.y = 1 - texcoord.y;
float zBuffer = tex2D(DepthBuffer, texcoord).x; //Depth Buffer
//Conversions to linear space.....
//Near & Far Adjustment
float Far = 1.0, Near = 0.125/Depth_Map_Adjust; //Division Depth Map Adjust - Near
float2 Z = float2( zBuffer, 1-zBuffer );
if (Depth_Map == 0)//DM0. Normal
zBuffer = Far * Near / (Far + Z.x * (Near - Far));
else if (Depth_Map == 1)//DM1. Reverse
zBuffer = Far * Near / (Far + Z.y * (Near - Far));
return float2(step(smoothstep(0,1,zBuffer),abs(Depth_CutOff)),zBuffer);
}
float4 BB_H(float2 TC)
{
return tex2D(BackBuffer, TC );
}
// YUV-RGB conversion routine from Hyper3D
float3 encodePalYuv(float3 rgb)
{
float3 RGB2Y = float3( 0.299, 0.587, 0.114);
float3 RGB2Cb = float3(-0.169,-0.331, 0.500);
float3 RGB2Cr = float3( 0.500,-0.419,-0.081);
return float3(dot(rgb, RGB2Y), dot(rgb, RGB2Cb), dot(rgb, RGB2Cr));
}
float3 decodePalYuv(float3 ycc)
{
float3 YCbCr2R = float3( 1.000, 0.000, 1.400);
float3 YCbCr2G = float3( 1.000,-0.343,-0.711);
float3 YCbCr2B = float3( 1.000, 1.765, 0.000);
return float3(dot(ycc, YCbCr2R), dot(ycc, YCbCr2G), dot(ycc, YCbCr2B));
}
float4 TAA(float2 texcoord)
{ //Depth Similarity
float M_Similarity = 1-abs(Similarity), D_Similarity = saturate(pow(abs(DepthM(texcoord).y/tex2D(PSDepthBuffer,texcoord).x), 100) + M_Similarity);
//Velocity Scaler
float S_Velocity = 12.5 * lerp( 1, 80,Delta_Power), V_Buffer = saturate(distance(DepthM(texcoord).y,tex2D(PSDepthBuffer,texcoord).x) * S_Velocity);
float Per = 1-Persistence;
float4 PastColor = tex2Dlod(PBackBuffer,float4(texcoord,0,0) );//Past Back Buffer
PastColor = (1-Per) * tex2D(BackBuffer, texcoord) + Per * PastColor;
float3 antialiased = PastColor.xyz;
float mixRate = min(PastColor.w, 0.5), MB = Clamping_Adjust;//WIP
float3 BB = tex2D(BackBuffer, texcoord).xyz;
antialiased = lerp(antialiased * antialiased, BB * BB, mixRate);
antialiased = sqrt(antialiased);
const float2 XYoffset[8] = { float2( 0,+pix.y ), float2( 0,-pix.y), float2(+pix.x, 0), float2(-pix.x, 0), float2(-pix.x,-pix.y), float2(+pix.x,-pix.y), float2(-pix.x,+pix.y), float2(+pix.x,+pix.y) };
float3 minColor = encodePalYuv(tex2D(BackBuffer, texcoord ).rgb) - MB;
float3 maxColor = encodePalYuv(tex2D(BackBuffer, texcoord ).rgb) + MB;
for(int i = 1; i < 8; ++i)
{ //DX9 work around.
minColor = min(minColor,encodePalYuv(tex2Dlod(BackBuffer, float4(texcoord + XYoffset[i],0,0)).rgb)) - MB;
maxColor = max(maxColor,encodePalYuv(tex2Dlod(BackBuffer, float4(texcoord + XYoffset[i],0,0)).rgb)) + MB;
}
antialiased = clamp(encodePalYuv(antialiased), minColor, maxColor);
mixRate = rcp(1.0 / mixRate + 1.0);
float diff = length(BB - tex2D(PSBackBuffer, texcoord).xyz) * lerp(1.0,8.0,Delta_Power);
if(Delta == 1)
diff = V_Buffer;
float clampAmount = diff;
mixRate += clampAmount;
mixRate = clamp(mixRate, 0.05, 0.5);
antialiased = decodePalYuv(antialiased);
//Need to check for DX9
float4 Output = Similarity > 0 ? lerp(float4(BB,1), float4(antialiased,mixRate), D_Similarity) : float4(lerp(BB,antialiased, D_Similarity),mixRate);
if (Debug == 1)
Output = diff;
else if (Debug == 2)
Output = lerp(float3(1,0,0),Output.rgb, D_Similarity);
else if (Debug == 3)
Output = DepthM(texcoord).y;
return Output;
}
void Out(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target)
{
float PosX = 0.9525f*BUFFER_WIDTH*pix.x,PosY = 0.975f*BUFFER_HEIGHT*pix.y, Scale = 2;
float3 D,E,P,T,H,Three,DD,Dot,I,N,F,O;
float4 T_A_A = TAA(texcoord);
#if App_Sync
if(texcoord.x < pix.x * Scale && 1-texcoord.y < pix.y * Scale)
T_A_A = Alternate ? 0 : 1; //Jak0bW Suggestion for Mouse Jiggle Wiggle
#endif
[branch] if(timer <= 12500)
{
//DEPTH
//D
float PosXD = -0.035+PosX, offsetD = 0.001;
float3 OneD = all( abs(float2( texcoord.x -PosXD, texcoord.y-PosY)) < float2(0.0025,0.009));
float3 TwoD = all( abs(float2( texcoord.x -PosXD-offsetD, texcoord.y-PosY)) < float2(0.0025,0.007));
D = OneD-TwoD;
//E
float PosXE = -0.028+PosX, offsetE = 0.0005;
float3 OneE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.009));
float3 TwoE = all( abs(float2( texcoord.x -PosXE-offsetE, texcoord.y-PosY)) < float2(0.0025,0.007));
float3 ThreeE = all( abs(float2( texcoord.x -PosXE, texcoord.y-PosY)) < float2(0.003,0.001));
E = (OneE-TwoE)+ThreeE;
//P
float PosXP = -0.0215+PosX, PosYP = -0.0025+PosY, offsetP = 0.001, offsetP1 = 0.002;
float3 OneP = all( abs(float2( texcoord.x -PosXP, texcoord.y-PosYP)) < float2(0.0025,0.009*0.775));
float3 TwoP = all( abs(float2( texcoord.x -PosXP-offsetP, texcoord.y-PosYP)) < float2(0.0025,0.007*0.680));
float3 ThreeP = all( abs(float2( texcoord.x -PosXP+offsetP1, texcoord.y-PosY)) < float2(0.0005,0.009));
P = (OneP-TwoP) + ThreeP;
//T
float PosXT = -0.014+PosX, PosYT = -0.008+PosY;
float3 OneT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosYT)) < float2(0.003,0.001));
float3 TwoT = all( abs(float2( texcoord.x -PosXT, texcoord.y-PosY)) < float2(0.000625,0.009));
T = OneT+TwoT;
//H
float PosXH = -0.0072+PosX;
float3 OneH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.001));
float3 TwoH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.002,0.009));
float3 ThreeH = all( abs(float2( texcoord.x -PosXH, texcoord.y-PosY)) < float2(0.00325,0.009));
H = (OneH-TwoH)+ThreeH;
//Three
float offsetFive = 0.001, PosX3 = -0.001+PosX;
float3 OneThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.009));
float3 TwoThree = all( abs(float2( texcoord.x -PosX3 - offsetFive, texcoord.y-PosY)) < float2(0.003,0.007));
float3 ThreeThree = all( abs(float2( texcoord.x -PosX3, texcoord.y-PosY)) < float2(0.002,0.001));
Three = (OneThree-TwoThree)+ThreeThree;
//DD
float PosXDD = 0.006+PosX, offsetDD = 0.001;
float3 OneDD = all( abs(float2( texcoord.x -PosXDD, texcoord.y-PosY)) < float2(0.0025,0.009));
float3 TwoDD = all( abs(float2( texcoord.x -PosXDD-offsetDD, texcoord.y-PosY)) < float2(0.0025,0.007));
DD = OneDD-TwoDD;
//Dot
float PosXDot = 0.011+PosX, PosYDot = 0.008+PosY;
float3 OneDot = all( abs(float2( texcoord.x -PosXDot, texcoord.y-PosYDot)) < float2(0.00075,0.0015));
Dot = OneDot;
//INFO
//I
float PosXI = 0.0155+PosX, PosYI = 0.004+PosY, PosYII = 0.008+PosY;
float3 OneI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosY)) < float2(0.003,0.001));
float3 TwoI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYI)) < float2(0.000625,0.005));
float3 ThreeI = all( abs(float2( texcoord.x - PosXI, texcoord.y - PosYII)) < float2(0.003,0.001));
I = OneI+TwoI+ThreeI;
//N
float PosXN = 0.0225+PosX, PosYN = 0.005+PosY,offsetN = -0.001;
float3 OneN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN)) < float2(0.002,0.004));
float3 TwoN = all( abs(float2( texcoord.x - PosXN, texcoord.y - PosYN - offsetN)) < float2(0.003,0.005));
N = OneN-TwoN;
//F
float PosXF = 0.029+PosX, PosYF = 0.004+PosY, offsetF = 0.0005, offsetF1 = 0.001;
float3 OneF = all( abs(float2( texcoord.x -PosXF-offsetF, texcoord.y-PosYF-offsetF1)) < float2(0.002,0.004));
float3 TwoF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0025,0.005));
float3 ThreeF = all( abs(float2( texcoord.x -PosXF, texcoord.y-PosYF)) < float2(0.0015,0.00075));
F = (OneF-TwoF)+ThreeF;
//O
float PosXO = 0.035+PosX, PosYO = 0.004+PosY;
float3 OneO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.003,0.005));
float3 TwoO = all( abs(float2( texcoord.x -PosXO, texcoord.y-PosYO)) < float2(0.002,0.003));
O = OneO-TwoO;
//Website
color = float4(D+E+P+T+H+Three+DD+Dot+I+N+F+O,1.) ? 1-texcoord.y*50.0+48.35f : T_A_A;
}
else
color = T_A_A;
}
void Current_BackBuffer(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 Color : SV_Target0, out float Depth : SV_Target1)
{
Color = BB_H(texcoord);
Depth = DepthM(texcoord).y;
}
void Past_BackBuffer(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 PastSingleC : SV_Target0, out float PastSingleD : SV_Target1, out float4 Past : SV_Target2)
{
PastSingleC = tex2D(CBackBuffer,texcoord).rgba;
PastSingleD = tex2D(CDepthBuffer,texcoord).x;
Past = BB_H(texcoord);
}
///////////////////////////////////////////////////////////ReShade.fxh/////////////////////////////////////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
technique TAA
{
pass CBB
{
VertexShader = PostProcessVS;
PixelShader = Current_BackBuffer;
RenderTarget0 = CurrentBackBufferTAA;
RenderTarget1 = CurrentDepthBufferTAA;
}
pass Out
{
VertexShader = PostProcessVS;
PixelShader = Out;
}
pass PBB
{
VertexShader = PostProcessVS;
PixelShader = Past_BackBuffer;
RenderTarget0 = PastSingleBackBufferTAA;
RenderTarget1 = PastSingleDepthBufferTAA;
RenderTarget2 = PastBackBufferTAA;
}
}

View File

@ -0,0 +1,68 @@
#To use this script load it up in FreePie and make sure you have Tobii Eye Tracker fully installed and Enabled.
#Then make sure to start FreePie in Admin mode then run this script. Once that is done Move your head the full
#length of your monitor so that it calibrates it's center. Then start your game with reshade and start my Shader.
#Once in game and in SuperDepth3D's Menu use the Calibrate slider to reduce the ghosting in game to a tolerable
#level. There should be a veary slight delay in tracking this is ok for now maybe it can be improved later.
#Thank you and as always for more information head over to http://www.Depth3D.com
#If you like to dontate please do at. https://www.buymeacoffee.com/BlueSkyDefender
#Downloads Needed
#https://andersmalmgren.github.io/FreePIE/
#https://gaming.tobii.com/getstarted/
#If you don't know what your doing don't adjust the script below this line.
def map_tobii(n):
IsLooking = tobiiEyeX.userPresence == "Present"
Center = 4
MC = Center * 2
if (IsLooking): #and enabled):
#yaw = rotobiiEyeX.yaw
#roll = tobiiEyeX.roll
#x = tobiiEyeX.averageEyePositionInMmX
#y = tobiiEyeX.averageEyePositionInMmY
#z = tobiiEyeX.averageEyePositionInMmZ
x = tobiiEyeX.averageEyePositionNormalizedX * MC - Center
y = tobiiEyeX.averageEyePositionNormalizedY * MC - Center
z = round(tobiiEyeX.averageEyePositionNormalizedZ * MC)
#x = tobiiEyeX.normalizedCenterDeltaX
#y = tobiiEyeX.normalizedCenterDeltaY
#x = tobiiEyeX.gazePointInPixelsX
#y = tobiiEyeX.gazePointInPixelsY
else :
#yaw = 0
#roll = 0
x = 0
y = 0
z = 0
#freePieIO[0].yaw = 0
#freePieIO[0].pitch = 0
#freePieIO[0].roll = 0
freePieIO[0].x = x
freePieIO[0].y = y
freePieIO[0].z = z
#diagnostics.watch(enabled)
#diagnostics.watch(yaw)
#diagnostics.watch(roll)
diagnostics.watch(x)
diagnostics.watch(y)
diagnostics.watch(z)
#Tobii update function
def update():
map_tobii(0)
if starting:
#enabled = True
system.setThreadTiming(TimingTypes.HighresSystemTimer)
system.threadExecutionInterval = 0
tobiiEyeX.update += update
#toggleA = keyboard.getPressed(Key.X)
#if toggleA:
#enabled = not enabled

View File

@ -0,0 +1,72 @@
/**
* Tonemap version 1.1
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*/
#include "ReShadeUI.fxh"
uniform float Gamma < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 2.0;
ui_tooltip = "Adjust midtones. 1.0 is neutral. This setting does exactly the same as the one in Lift Gamma Gain, only with less control.";
> = 1.0;
uniform float Exposure < __UNIFORM_SLIDER_FLOAT1
ui_min = -1.0; ui_max = 1.0;
ui_tooltip = "Adjust exposure";
> = 0.0;
uniform float Saturation < __UNIFORM_SLIDER_FLOAT1
ui_min = -1.0; ui_max = 1.0;
ui_tooltip = "Adjust saturation";
> = 0.0;
uniform float Bleach < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Brightens the shadows and fades the colors";
> = 0.0;
uniform float Defog < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "How much of the color tint to remove";
> = 0.0;
uniform float3 FogColor < __UNIFORM_COLOR_FLOAT3
ui_label = "Defog Color";
ui_tooltip = "Which color tint to remove";
> = float3(0.0, 0.0, 1.0);
#include "ReShade.fxh"
float3 TonemapPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
color = saturate(color - Defog * FogColor * 2.55); // Defog
color *= pow(2.0f, Exposure); // Exposure
color = pow(color, Gamma); // Gamma
const float3 coefLuma = float3(0.2126, 0.7152, 0.0722);
float lum = dot(coefLuma, color);
float L = saturate(10.0 * (lum - 0.45));
float3 A2 = Bleach * color;
float3 result1 = 2.0f * color * lum;
float3 result2 = 1.0f - 2.0f * (1.0f - lum) * (1.0f - color);
float3 newColor = lerp(result1, result2, L);
float3 mixRGB = A2 * newColor;
color += ((1.0f - A2) * mixRGB);
float3 middlegray = dot(color, (1.0 / 3.0));
float3 diffcolor = color - middlegray;
color = (color + diffcolor * Saturation) / (1 + (diffcolor * Saturation)); // Saturation
return color;
}
technique Tonemap
{
pass
{
VertexShader = PostProcessVS;
PixelShader = TonemapPass;
}
}

View File

@ -0,0 +1,306 @@
////----------//
///**Trails**///
//----------////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//* Trails
//* For Reshade 3.0
//* --------------------------
//* This work is licensed under a Creative Commons Attribution 3.0 Unported License.
//* So you are free to share, modify and adapt it for your needs, and even use it for commercial use.
//* I would also love to hear about a project you are using it with.
//* https://creativecommons.org/licenses/by/3.0/us/
//*
//* Have fun,
//* Jose Negrete AKA BlueSkyDefender
//*
//* https://github.com/BlueSkyDefender/Depth3D
//* ---------------------------------
//*
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define Per_Color_Channel 0 // Lets you adjust per Color Channel.Default 0 off
#define Add_Depth_Effects 0 // Lets this effect be affected by Depth..Default 0 off
#if !Per_Color_Channel
uniform float Persistence <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.00;
ui_label = "Persistence";
ui_tooltip = "Increase persistence longer the trail or afterimage.\n"
"If pushed out the effect is alot like long exposure.\n"
"This can be used for light painting in games.\n"
"1000/1 is 1.0, so 1/2 is 0.5 and so forth.\n"
"Default is 0.25, 0 is infinity.";
> = 0.25;
#else
uniform float3 Persistence <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.00;
ui_label = "Persistence";
ui_tooltip = "Increase persistence longer the trail or afterimage RGB.\n"
"If pushed out the effect is alot like long exposure.\n"
"This can be used for light painting in games.\n"
"1000/1 is 1.0, so 1/2 is 0.5 and so forth.\n"
"Default is 0.25, 0 is infinity.";
> = float3(0.25,0.25,0.25);
#endif
uniform float TQ <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Trail Blur Quality";
ui_tooltip = "Adjust Trail Blur Quality.\n"
"Default is Zero.";
> = 0.0;
//uniform bool TrailsX2 <
// ui_label = "Trails X2";
// ui_tooltip = "Two times the samples.\n"
// "This disables Trail Quality.";
//> = false;
uniform bool PS2 <
ui_label = "PS2 Style Echo";
ui_tooltip = "This enables PS2 Style Echo in your game.\n"
"This disables Trail Quality.";
> = false;
#if Add_Depth_Effects
uniform bool Allow_Depth <
ui_label = "Depth Map Toggle";
ui_tooltip = "This Alows Depth to be used in Trails.";
ui_category = "Depth Buffer";
> = 0;
uniform int Depth_Map <
ui_type = "combo";
ui_items = "Normal\0Reverse\0";
ui_label = "Custom Depth Map";
ui_tooltip = "Pick your Depth Map.";
ui_category = "Depth Buffer";
> = 0;
uniform float Depth_Map_Adjust <
ui_type = "slider";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Depth Map Adjustment";
ui_tooltip = "Adjust the depth map and sharpness distance.";
ui_category = "Depth Buffer";
> = 0.0;
uniform bool Hard_CutOff <
ui_label = "Hard CutOff";
ui_tooltip = "Depth Cutoff toggle this give a hard cutoff for depth isolation.";
ui_category = "Depth Buffer";
> = 0;
uniform bool Depth_Map_Flip <
ui_label = "Depth Map Flip";
ui_tooltip = "Flip the depth map if it is upside down.";
ui_category = "Depth Buffer";
> = 0;
uniform bool Invert_Depth <
ui_label = "Depth Map Inverte";
ui_tooltip = "Inverts Depth so you can target only your weapon or what's near you.";
ui_category = "Depth Buffer";
> = 0;
uniform bool Depth_View <
ui_label = "Depth Map View";
ui_tooltip = "Lets you see Depth so you can Debug.";
ui_category = "Depth Buffer";
> = 0;
#else
static const int Allow_Depth = 0;
static const int Depth_Map = 0;
static const float Depth_Map_Adjust = 250.0;
static const int Depth_Map_Flip = 0;
static const int Invert_Depth = 0;
static const int Depth_View = 0;
static const int Hard_CutOff = 0;
#endif
/////////////////////////////////////////////D3D Starts Here/////////////////////////////////////////////////////////////////
texture DepthBufferTex : DEPTH;
sampler DepthBuffer
{
Texture = DepthBufferTex;
};
texture BackBufferTex : COLOR;
sampler BackBuffer
{
Texture = BackBufferTex;
};
texture CurrentBackBufferT { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler CBackBuffer
{
Texture = CurrentBackBufferT;
};
texture PBB { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; MipLevels = 2;};
sampler PBackBuffer
{
Texture = PBB;
};
texture PSBB { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8;};
sampler PSBackBuffer
{
Texture = PSBB;
};
///////////////////////////////////////////////////////////TAA/////////////////////////////////////////////////////////////////////
#define pix float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Depth(in float2 texcoord : TEXCOORD0)
{
if (Depth_Map_Flip)
texcoord.y = 1 - texcoord.y;
float zBuffer = tex2D(DepthBuffer, texcoord).x; //Depth Buffer
//Conversions to linear space.....
//Near & Far Adjustment
float Far = 1.0, Near = 0.125/250.0; //Division Depth Map Adjust - Near
float2 Z = float2( zBuffer, 1-zBuffer );
if (Depth_Map == 0)//DM0. Normal
zBuffer = Far * Near / (Far + Z.x * (Near - Far));
else if (Depth_Map == 1)//DM1. Reverse
zBuffer = Far * Near / (Far + Z.y * (Near - Far));
return saturate(zBuffer);
}
float3 T_Out(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float TQA = TQ, D = Depth(texcoord);
if(PS2)
TQA = 0;
float3 C = tex2D(BackBuffer, texcoord).rgb;
//float3 PS = tex2D(PSBackBuffer, texcoord).rgb;
float3 P = tex2Dlod(PBackBuffer, float4(texcoord,0,TQA)).rgb;
#if !PerColor
float Per = 1-Persistence;
#else
float3 Per = 1-Persistence;
#endif
D = smoothstep(0,Depth_Map_Adjust,D);
if(Hard_CutOff)
D = step(0.5,D);
if(Invert_Depth)
D = 1-D;
if(!PS2)
{
P *= Per;
C = max( tex2D(BackBuffer, texcoord).rgb, P);
//PS = max( tex2D(BackBuffer, texcoord).rgb, P);
}
else
{
C = (1-Per) * C + Per * P;
//PS = (1-Per) * PS + Per * P;
}
//if(TrailsX2)
//{
// C = lerp(PS,C,0.5);
//}
if(Allow_Depth)
C = lerp(C,tex2D(BackBuffer, texcoord).rgb,saturate(D));
if(Depth_View)
C = D;
return C;
}
void Current_BackBuffer_T(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0)
{
color = tex2D(BackBuffer,texcoord);
}
void Past_BB(float4 position : SV_Position, float2 texcoord : TEXCOORD, out float4 Past : SV_Target0, out float4 PastSingle : SV_Target1)
{ float2 samples[12] = {
float2(-0.326212, -0.405805),
float2(-0.840144, -0.073580),
float2(-0.695914, 0.457137),
float2(-0.203345, 0.620716),
float2(0.962340, -0.194983),
float2(0.473434, -0.480026),
float2(0.519456, 0.767022),
float2(0.185461, -0.893124),
float2(0.507431, 0.064425),
float2(0.896420, 0.412458),
float2(-0.321940, -0.932615),
float2(-0.791559, -0.597705)
};
float4 sum_A = tex2D(BackBuffer,texcoord), sum_B = 0;//tex2D(CBackBuffer,texcoord);
if(!PS2)
{
float Adjust = TQ*pix.x;
[loop]
for (int i = 0; i < 12; i++)
{
sum_A += tex2Dlod(BackBuffer, float4(texcoord + Adjust * samples[i],0,0));
//sum_B += tex2Dlod(CBackBuffer, float4(texcoord + Adjust * samples[i],0,0));
}
Past = sum_A * 0.07692307;
PastSingle = 0;//sum_B * 0.07692307;
}
else
{
Past = sum_A;
PastSingle = 0;//sum_B * 0.07692307;
}
}
///////////////////////////////////////////////////////////ReShade.fxh/////////////////////////////////////////////////////////////
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD)
{
texcoord.x = (id == 2) ? 2.0 : 0.0;
texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}
technique Trails
{
pass CBB
{
VertexShader = PostProcessVS;
PixelShader = Current_BackBuffer_T;
RenderTarget = CurrentBackBufferT;
}
pass Trails
{
VertexShader = PostProcessVS;
PixelShader = T_Out;
}
pass PBB
{
VertexShader = PostProcessVS;
PixelShader = Past_BB;
RenderTarget0 = PBB;
RenderTarget1 = PSBB;
}
}

View File

@ -0,0 +1,73 @@
////////////////////////////////////////////////////////////////////////////////
// Triangular Dither //
// By The Sandvich Maker //
// Ported to ReShade by TreyM //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// //
// Usage: //
// Include this file in your shader like so: #include "TriDither.fx" //
// //
// For shader developers, use this syntax to do a function call in your //
// code as the last thing before exiting a given shader. You should dither //
// anytime data is going to be truncated to a lower bitdepth. Color input //
// must be a float3 value. //
// //
// input.rgb += TriDither(input.rgb, uv, bits); //
// //
// "bits" is an integer number that determines the bit depth //
// being dithered to. Usually 8, sometimes 10 //
// You can automate this by letting Reshade decide like so: //
// //
// input += TriDither(input, uv, BUFFER_COLOR_BIT_DEPTH); //
// //
// Manual setup looks something like this for an 8-bit backbuffer: //
// //
// input.rgb += TriDither(input.rgb, uv, 8); //
// //
////////////////////////////////////////////////////////////////////////////////
uniform float DitherTimer < source = "timer"; >;
#define remap(v, a, b) (((v) - (a)) / ((b) - (a)))
float rand21(float2 uv)
{
float2 noise = frac(sin(dot(uv, float2(12.9898, 78.233) * 2.0)) * 43758.5453);
return (noise.x + noise.y) * 0.5;
}
float rand11(float x)
{
return frac(x * 0.024390243);
}
float permute(float x)
{
return ((34.0 * x + 1.0) * x) % 289.0;
}
float3 TriDither(float3 color, float2 uv, int bits)
{
float bitstep = exp2(bits) - 1.0;
float lsb = 1.0 / bitstep;
float lobit = 0.5 / bitstep;
float hibit = (bitstep - 0.5) / bitstep;
float3 m = float3(uv, rand21(uv + (DitherTimer * 0.001))) + 1.0;
float h = permute(permute(permute(m.x) + m.y) + m.z);
float3 noise1, noise2;
noise1.x = rand11(h); h = permute(h);
noise2.x = rand11(h); h = permute(h);
noise1.y = rand11(h); h = permute(h);
noise2.y = rand11(h); h = permute(h);
noise1.z = rand11(h); h = permute(h);
noise2.z = rand11(h);
float3 lo = saturate(remap(color.xyz, 0.0, lobit));
float3 hi = saturate(remap(color.xyz, 1.0, hibit));
float3 uni = noise1 - 0.5;
float3 tri = noise1 - noise2;
return lerp(uni, tri, min(lo, hi)) * lsb;
}

View File

@ -0,0 +1,310 @@
/*
Simple UIMask shader by luluco250
I have no idea why this was never ported back to ReShade 3.0 from 2.0,
but if you missed it, here it is.
It doesn't feature the auto mask from the original shader.
It does feature a new multi-channnel masking feature. UI masks can now contain
separate 'modes' within each of the three color channels.
For example, you can have the regular hud on the red channel (the default one),
a mask for an inventory screen on the green channel and a mask for a quest menu
on the blue channel. You can then use keyboard keys to toggle each channel on or off.
Multiple channels can be active at once, they'll just add up to mask the image.
Simple/legacy masks are not affected by this, they'll work just as you'd expect,
so you can still make simple black and white masks that use all color channels, it'll
be no different than just having it on a single channel.
Tips:
--You can adjust how much it will affect your HUD by changing "Mask Intensity".
--You don't actually need to place the UIMask_Bottom technique at the bottom of
your shader pipeline, if you have any effects that don't necessarily affect
the visibility of the HUD you can place it before that.
For instance, if you use color correction shaders like LUT, you might want
to place UIMask_Bottom just before that.
--Preprocessor flags:
--UIMASK_MULTICHANNEL:
Enables having up to three different masks on each color channel.
--UIMASK_TOGGLEKEY_RED:
Keycode that toggles the red channel of the mask.
--UIMASK_TOGGLEKEY_BLUE:
Keycode that toggles the blue channel of the mask.
--UIMASK_TOGGLEKEY_GREEN:
Keycode that toggles the green channel of the mask.
--Refer to this page for keycodes:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
--To make a custom mask:
1-Take a screenshot of your game with the HUD enabled,
preferrably with any effects disabled for maximum visibility.
2-Open the screenshot with your preferred image editor program, I use GIMP.
3-Make a background white layer if there isn't one already.
Be sure to leave it behind your actual screenshot for the while.
4-Make an empty layer for the mask itself, you can call it "mask".
5-Having selected the mask layer, paint the places where HUD constantly is,
such as health bars, important messages, minimaps etc.
6-Delete or make your screenshot layer invisible.
7-Before saving your mask, let's do some gaussian blurring to improve it's look and feel:
For every step of blurring you want to do, make a new layer, such as:
Mask - Blur16x16
Mask - Blur8x8
Mask - Blur4x4
Mask - Blur2x2
Mask - NoBlur
You should use your image editor's default gaussian blurring filter, if there is one.
This avoids possible artifacts and makes the mask blend more easily on the eyes.
You may not need this if your mask is accurate enough and/or the HUD is simple enough.
8-Now save the final image as "UIMask.png" in your textures folder and you're done!
MIT Licensed:
Copyright (c) 2017 Lucas Melo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//#region Preprocessor
#include "ReShade.fxh"
#include "ReShadeUI.fxh"
#ifndef UIMASK_MULTICHANNEL
#define UIMASK_MULTICHANNEL 0
#endif
#ifndef UIMASK_TOGGLEKEY_RED
#define UIMASK_TOGGLEKEY_RED 0x67 //Numpad 7
#endif
#ifndef UIMASK_TOGGLEKEY_GREEN
#define UIMASK_TOGGLEKEY_GREEN 0x68 //Numpad 8
#endif
#ifndef UIMASK_TOGGLEKEY_BLUE
#define UIMASK_TOGGLEKEY_BLUE 0x69 //Numpad 9
#endif
#if !UIMASK_MULTICHANNEL
#define TEXFORMAT R8
#else
#define TEXFORMAT RGBA8
#endif
//#endregion
namespace UIMask
{
//#region Uniforms
uniform int _Help
<
ui_label = " ";
ui_text =
"For more detailed instructions, see the text at the top of this "
"effect's shader file (UIMask.fx).\n"
"\n"
"Available preprocessor definitions:\n"
" UIMASK_MULTICHANNEL:\n"
" If set to 1, each of the RGB color channels in the texture is "
"treated as a separate mask.\n"
" UIMASK_TOGGLEKEY_RED:\n"
" Defines the key for using the mask in the red channel, the "
"default is Numpad 7.\n"
" UIMASK_TOGGLEKEY_GREEN:\n"
" Defines the key for using the mask in the green channel, the "
"default is Numpad 8.\n"
" UIMASK_TOGGLEKEY_BLUE:\n"
" Defines the key for using the mask in the blue channel, the "
"default is Numpad 9.\n"
"\n"
"Google \"virtual key codes\" for the values of each keyboard key.\n"
"\n"
"How to create a mask:\n"
"\n"
"1. Take a screenshot with the game's UI appearing.\n"
"2. Open the screenshot in an image editor, GIMP or Photoshop are "
"recommended.\n"
"3. Create a new layer over the screenshot layer, fill it with black.\n"
"4. Reduce the layer opacity so you can see the screenshot layer "
"below.\n"
"5. Cover the UI with white to mask it from effects. The stronger the "
"mask white color, the more opaque the mask will be.\n"
"6. Set the mask layer opacity back to 100%.\n"
"7. Save the image in one of your texture folders, named "
"\"UIMask.png\".\n"
;
ui_category = "Help";
ui_category_closed = true;
ui_type = "radio";
>;
uniform float fMask_Intensity
<
__UNIFORM_SLIDER_FLOAT1
ui_label = "Mask Intensity";
ui_tooltip =
"How much to mask effects from affecting the original image.\n"
"\nDefault: 1.0";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 0.001;
> = 1.0;
uniform bool bDisplayMask <
ui_label = "Display Mask";
ui_tooltip =
"Display the mask texture.\n"
"Useful for testing multiple channels or simply the mask itself.\n"
"\nDefault: Off";
> = false;
#if UIMASK_MULTICHANNEL
uniform bool ToggleRed
<
source = "key";
keycode = UIMASK_TOGGLEKEY_RED;
toggle = true;
>;
uniform bool ToggleGreen
<
source = "key";
keycode = UIMASK_TOGGLEKEY_GREEN;
toggle = true;
>;
uniform bool ToggleBlue
<
source = "key";
keycode = UIMASK_TOGGLEKEY_BLUE;
toggle = true;
>;
#endif
//#endregion
//#region Textures
texture BackupTex
{
Width = BUFFER_WIDTH;
Height = BUFFER_HEIGHT;
};
sampler Backup
{
Texture = BackupTex;
};
texture MaskTex <source="UIMask.png";>
{
Width = BUFFER_WIDTH;
Height = BUFFER_HEIGHT;
Format = TEXFORMAT;
};
sampler Mask
{
Texture = MaskTex;
};
//#endregion
//#region Shaders
float4 BackupPS(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target {
return tex2D(ReShade::BackBuffer, uv);
}
float4 MainPS(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target {
float4 color = tex2D(ReShade::BackBuffer, uv);
float4 backup = tex2D(Backup, uv);
#if !UIMASK_MULTICHANNEL
float mask = tex2D(Mask, uv).r;
#else
float3 mask_rgb = tex2D(Mask, uv).rgb;
// This just works, it basically adds masking with each channel that has
// been toggled. 'ToggleRed' is inverted so it defaults to 'true' upon
// start.
float mask = saturate(
1.0 - dot(1.0 - mask_rgb,
float3(!ToggleRed, ToggleGreen, ToggleBlue)));
#endif
color = lerp(color, backup, mask * fMask_Intensity);
color = bDisplayMask ? mask : color;
return color;
}
//#endregion
//#region Techniques
technique UIMask_Top
<
ui_tooltip = "Place this *above* the effects to be masked.";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = BackupPS;
RenderTarget = BackupTex;
}
}
technique UIMask_Bottom
<
ui_tooltip =
"Place this *below* the effects to be masked.\n"
"If you want to add a toggle key for the effect, set it to this one.";
>
{
pass
{
VertexShader = PostProcessVS;
PixelShader = MainPS;
}
}
//#endregion
} // Namespace.

View File

@ -0,0 +1,75 @@
/**
Vibrance
by Christian Cann Schuldt Jensen ~ CeeJay.dk
Vibrance intelligently boosts the saturation of pixels so pixels that had little color get a larger boost than pixels that had a lot.
This avoids oversaturation of pixels that were already very saturated.
History:
Version 1.0 by Ceejay.dk
- Original
Version 1.1 by CeeJay.dk
- Introduced RBG balance to help colorblind users
Version 1.1.1
- Minor UI improvements for Reshade 3.x
*/
#include "ReShadeUI.fxh"
uniform float Vibrance < __UNIFORM_SLIDER_FLOAT1
ui_min = -1.0; ui_max = 1.0;
ui_tooltip = "Intelligently saturates (or desaturates if you use negative values) the pixels depending on their original saturation.";
> = 0.15;
uniform float3 VibranceRGBBalance <
ui_type = "drag";
ui_min = 0.0; ui_max = 10.0;
ui_label = "RGB Balance";
ui_tooltip = "A per channel multiplier to the Vibrance strength so you can give more boost to certain colors over others.\nThis is handy if you are colorblind and less sensitive to a specific color.\nYou can then boost that color more than the others.";
> = float3(1.0, 1.0, 1.0);
/*
uniform int Vibrance_Luma <
ui_type = "combo";
ui_label = "Luma type";
ui_items = "Perceptual\0Even\0";
> = 0;
*/
#include "ReShade.fxh"
float3 VibrancePass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
float3 coefLuma = float3(0.212656, 0.715158, 0.072186);
/*
if (Vibrance_Luma)
coefLuma = float3(0.333333, 0.333334, 0.333333);
*/
float luma = dot(coefLuma, color);
float max_color = max(color.r, max(color.g, color.b)); // Find the strongest color
float min_color = min(color.r, min(color.g, color.b)); // Find the weakest color
float color_saturation = max_color - min_color; // The difference between the two is the saturation
// Extrapolate between luma and original by 1 + (1-saturation) - current
float3 coeffVibrance = float3(VibranceRGBBalance * Vibrance);
color = lerp(luma, color, 1.0 + (coeffVibrance * (1.0 - (sign(coeffVibrance) * color_saturation))));
return color;
}
technique Vibrance
{
pass
{
VertexShader = PostProcessVS;
PixelShader = VibrancePass;
}
}

View File

@ -0,0 +1,115 @@
/**
* Vignette version 1.3
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*
* Darkens the edges of the image to make it look more like it was shot with a camera lens.
* May cause banding artifacts.
*/
#include "ReShadeUI.fxh"
uniform int Type <
ui_type = "combo";
ui_items = "Original\0New\0TV style\0Untitled 1\0Untitled 2\0Untitled 3\0Untitled 4\0";
> = 0;
uniform float Ratio < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.15; ui_max = 6.0;
ui_tooltip = "Sets a width to height ratio. 1.00 (1/1) is perfectly round, while 1.60 (16/10) is 60 % wider than it's high.";
> = 1.0;
uniform float Radius < __UNIFORM_SLIDER_FLOAT1
ui_min = -1.0; ui_max = 3.0;
ui_tooltip = "lower values = stronger radial effect from center";
> = 2.0;
uniform float Amount < __UNIFORM_SLIDER_FLOAT1
ui_min = -2.0; ui_max = 1.0;
ui_tooltip = "Strength of black. -2.00 = Max Black, 1.00 = Max White.";
> = -1.0;
uniform int Slope < __UNIFORM_SLIDER_INT1
ui_min = 2; ui_max = 16;
ui_tooltip = "How far away from the center the change should start to really grow strong (odd numbers cause a larger fps drop than even numbers).";
> = 2;
uniform float2 Center < __UNIFORM_SLIDER_FLOAT2
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Center of effect for 'Original' vignette type. 'New' and 'TV style' do not obey this setting.";
> = float2(0.5, 0.5);
#include "ReShade.fxh"
float4 VignettePass(float4 vpos : SV_Position, float2 tex : TexCoord) : SV_Target
{
float4 color = tex2D(ReShade::BackBuffer, tex);
if (Type == 0)
{
// Set the center
float2 distance_xy = tex - Center;
// Adjust the ratio
distance_xy *= float2((BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH), Ratio);
// Calculate the distance
distance_xy /= Radius;
float distance = dot(distance_xy, distance_xy);
// Apply the vignette
color.rgb *= (1.0 + pow(distance, Slope * 0.5) * Amount); //pow - multiply
}
if (Type == 1) // New round (-x*x+x) + (-y*y+y) method.
{
tex = -tex * tex + tex;
color.rgb = saturate(((BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH)*(BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH) * Ratio * tex.x + tex.y) * 4.0) * color.rgb;
}
if (Type == 2) // New (-x*x+x) * (-y*y+y) TV style method.
{
tex = -tex * tex + tex;
color.rgb = saturate(tex.x * tex.y * 100.0) * color.rgb;
}
if (Type == 3)
{
tex = abs(tex - 0.5);
float tc = dot(float4(-tex.x, -tex.x, tex.x, tex.y), float4(tex.y, tex.y, 1.0, 1.0)); //XOR
tc = saturate(tc - 0.495);
color.rgb *= (pow((1.0 - tc * 200), 4) + 0.25); //or maybe abs(tc*100-1) (-(tc*100)-1)
}
if (Type == 4)
{
tex = abs(tex - 0.5);
float tc = dot(float4(-tex.x, -tex.x, tex.x, tex.y), float4(tex.y, tex.y, 1.0, 1.0)); //XOR
tc = saturate(tc - 0.495) - 0.0002;
color.rgb *= (pow((1.0 - tc * 200), 4) + 0.0); //or maybe abs(tc*100-1) (-(tc*100)-1)
}
if (Type == 5) // MAD version of 2
{
tex = abs(tex - 0.5);
float tc = tex.x * (-2.0 * tex.y + 1.0) + tex.y; //XOR
tc = saturate(tc - 0.495);
color.rgb *= (pow((-tc * 200 + 1.0), 4) + 0.25); //or maybe abs(tc*100-1) (-(tc*100)-1)
//color.rgb *= (pow(((tc*200.0)-1.0),4)); //or maybe abs(tc*100-1) (-(tc*100)-1)
}
if (Type == 6) // New round (-x*x+x) * (-y*y+y) method.
{
//tex.y /= float2((BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH), Ratio);
float tex_xy = dot(float4(tex, tex), float4(-tex, 1.0, 1.0)); //dot is actually slower
color.rgb = saturate(tex_xy * 4.0) * color.rgb;
}
return color;
}
technique Vignette
{
pass
{
VertexShader = PostProcessVS;
PixelShader = VignettePass;
}
}

View File

@ -0,0 +1,409 @@
/*=============================================================================
ReShade 4 effect file
github.com/martymcmodding
Support me:
paypal.me/mcflypg
patreon.com/mcflypg
Simple Bloom
by Marty McFly / P.Gilcher
part of qUINT shader library for ReShade 4
Copyright (c) Pascal Gilcher / Marty McFly. All rights reserved.
=============================================================================*/
/*=============================================================================
Preprocessor settings
=============================================================================*/
#ifndef SAMPLE_HIGH_QUALITY
#define SAMPLE_HIGH_QUALITY 0
#endif
/*=============================================================================
UI Uniforms
=============================================================================*/
uniform float BLOOM_INTENSITY <
ui_type = "drag";
ui_min = 0.00; ui_max = 10.00;
ui_label = "Bloom Intensity";
ui_tooltip = "Scales bloom brightness.";
> = 1.2;
uniform float BLOOM_CURVE <
ui_type = "drag";
ui_min = 0.00; ui_max = 10.00;
ui_label = "Bloom Curve";
ui_tooltip = "Higher values limit bloom to bright light sources only.";
> = 1.5;
uniform float BLOOM_SAT <
ui_type = "drag";
ui_min = 0.00; ui_max = 5.00;
ui_label = "Bloom Saturation";
ui_tooltip = "Adjusts the color strength of the bloom effect";
> = 2.0;
/*
uniform float BLOOM_DIRT <
ui_type = "drag";
ui_min = 0.00; ui_max = 2.00;
ui_label = "Lens Dirt Amount";
ui_tooltip = "Applies a dirt mask on top of the original bloom.";
> = 0.0;
*/
uniform float BLOOM_LAYER_MULT_1 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 1 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.05;
uniform float BLOOM_LAYER_MULT_2 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 2 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.05;
uniform float BLOOM_LAYER_MULT_3 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 3 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.05;
uniform float BLOOM_LAYER_MULT_4 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 4 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.1;
uniform float BLOOM_LAYER_MULT_5 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 5 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.5;
uniform float BLOOM_LAYER_MULT_6 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 6 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.01;
uniform float BLOOM_LAYER_MULT_7 <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Layer 7 Intensity";
ui_tooltip = "Intensity of this bloom layer. 1 is sharpest layer, 7 the most blurry.";
> = 0.01;
uniform float BLOOM_ADAPT_STRENGTH <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Bloom Scene Adaptation Sensitivity";
ui_tooltip = "Amount of adaptation applied, 0 means same exposure for all scenes, 1 means complete autoexposure.";
> = 0.5;
uniform float BLOOM_ADAPT_EXPOSURE <
ui_type = "drag";
ui_min = -5.00; ui_max = 5.00;
ui_label = "Bloom Scene Exposure Bias";
ui_tooltip = "qUINT bloom employs eye adaptation to tune bloom intensity for scene differences.\nThis parameter adjusts the final scene exposure.";
> = 0.0;
uniform float BLOOM_ADAPT_SPEED <
ui_type = "drag";
ui_min = 0.50; ui_max = 10.00;
ui_label = "Bloom Scene Adaptation Speed";
ui_tooltip = "Eye adaptation data is created by exponential moving average with last frame data.\nThis parameter controls the adjustment speed.\nHigher parameters let the image adjust more quickly.";
> = 2.0;
uniform bool BLOOM_ADAPT_MODE <
ui_label = "Adapt bloom only";
> = false;
uniform float BLOOM_TONEMAP_COMPRESSION <
ui_type = "drag";
ui_min = 0.00; ui_max = 10.00;
ui_label = "Bloom Tonemap Compression";
ui_tooltip = "Lower values compress a larger color range.";
> = 4.0;
/*=============================================================================
Textures, Samplers, Globals
=============================================================================*/
#define RESHADE_QUINT_COMMON_VERSION_REQUIRE 200
#include "qUINT_common.fxh"
#define INT_LOG2(v) (((v >> 1) != 0) + ((v >> 2) != 0) + ((v >> 3) != 0) + ((v >> 4) != 0) + ((v >> 5) != 0) + ((v >> 6) != 0) + ((v >> 7) != 0) + ((v >> 8) != 0) + ((v >> 9) != 0) + ((v >> 10) != 0) + ((v >> 11) != 0) + ((v >> 12) != 0) + ((v >> 13) != 0) + ((v >> 14) != 0) + ((v >> 15) != 0) + ((v >> 16) != 0))
//static const int BloomTex7_LowestMip = int(log(BUFFER_HEIGHT/128) / log(2)) + 1;
static const int BloomTex7_LowestMip = INT_LOG2(BUFFER_HEIGHT/128);
texture2D MXBLOOM_BloomTexSource { Width = BUFFER_WIDTH/2; Height = BUFFER_HEIGHT/2; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex1 { Width = BUFFER_WIDTH/2; Height = BUFFER_HEIGHT/2; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex2 { Width = BUFFER_WIDTH/4; Height = BUFFER_HEIGHT/4; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex3 { Width = BUFFER_WIDTH/8; Height = BUFFER_HEIGHT/8; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex4 { Width = BUFFER_WIDTH/16; Height = BUFFER_HEIGHT/16; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex5 { Width = BUFFER_WIDTH/32; Height = BUFFER_HEIGHT/32; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex6 { Width = BUFFER_WIDTH/64; Height = BUFFER_HEIGHT/64; Format = RGBA16F;};
texture2D MXBLOOM_BloomTex7 { Width = BUFFER_WIDTH/128; Height = BUFFER_HEIGHT/128; Format = RGBA16F; MipLevels = BloomTex7_LowestMip;};
texture2D MXBLOOM_BloomTexAdapt { Format = R16F; };
sampler2D sMXBLOOM_BloomTexSource { Texture = MXBLOOM_BloomTexSource; };
sampler2D sMXBLOOM_BloomTex1 { Texture = MXBLOOM_BloomTex1; };
sampler2D sMXBLOOM_BloomTex2 { Texture = MXBLOOM_BloomTex2; };
sampler2D sMXBLOOM_BloomTex3 { Texture = MXBLOOM_BloomTex3; };
sampler2D sMXBLOOM_BloomTex4 { Texture = MXBLOOM_BloomTex4; };
sampler2D sMXBLOOM_BloomTex5 { Texture = MXBLOOM_BloomTex5; };
sampler2D sMXBLOOM_BloomTex6 { Texture = MXBLOOM_BloomTex6; };
sampler2D sMXBLOOM_BloomTex7 { Texture = MXBLOOM_BloomTex7; };
sampler2D sMXBLOOM_BloomTexAdapt { Texture = MXBLOOM_BloomTexAdapt; };
/*=============================================================================
Functions
=============================================================================*/
float4 downsample(sampler2D tex, float2 tex_size, float2 uv)
{
float4 offset_uv = 0;
float2 kernel_small_offsets = float2(2.0,2.0) / tex_size;
float2 kernel_large_offsets = float2(4.0,4.0) / tex_size;
float4 kernel_center = tex2D(tex, uv);
float4 kernel_small = 0;
offset_uv.xy = uv + kernel_small_offsets;
kernel_small += tex2Dlod(tex, offset_uv); //++
offset_uv.x = uv.x - kernel_small_offsets.x;
kernel_small += tex2Dlod(tex, offset_uv); //-+
offset_uv.y = uv.y - kernel_small_offsets.y;
kernel_small += tex2Dlod(tex, offset_uv); //--
offset_uv.x = uv.x + kernel_small_offsets.x;
kernel_small += tex2Dlod(tex, offset_uv); //+-
#if SAMPLE_HIGH_QUALITY == 0
return kernel_center / 5.0
+ kernel_small / 5.0;
#else
float4 kernel_large_1 = 0;
offset_uv.xy = uv + kernel_large_offsets;
kernel_large_1 += tex2Dlod(tex, offset_uv); //++
offset_uv.x = uv.x - kernel_large_offsets.x;
kernel_large_1 += tex2Dlod(tex, offset_uv); //-+
offset_uv.y = uv.y - kernel_large_offsets.y;
kernel_large_1 += tex2Dlod(tex, offset_uv); //--
offset_uv.x = uv.x + kernel_large_offsets.x;
kernel_large_1 += tex2Dlod(tex, offset_uv); //+-
float4 kernel_large_2 = 0;
offset_uv.xy = uv;
offset_uv.x += kernel_large_offsets.x;
kernel_large_2 += tex2Dlod(tex, offset_uv); //+0
offset_uv.x -= kernel_large_offsets.x * 2.0;
kernel_large_2 += tex2Dlod(tex, offset_uv); //-0
offset_uv.x = uv.x;
offset_uv.y += kernel_large_offsets.y;
kernel_large_2 += tex2Dlod(tex, offset_uv); //0+
offset_uv.y -= kernel_large_offsets.y * 2.0;
kernel_large_2 += tex2Dlod(tex, offset_uv); //0-
return kernel_center * 0.5 / 4.0
+ kernel_small * 0.5 / 4.0
+ kernel_large_1 * 0.125 / 4.0
+ kernel_large_2 * 0.25 / 4.0;
#endif
}
float3 Upsample(sampler2D tex, float2 texel_size, float2 uv)
{
float4 offset_uv = 0;
float4 kernel_small_offsets;
kernel_small_offsets.xy = 1.5 * texel_size;
kernel_small_offsets.zw = kernel_small_offsets.xy * 2;
float3 kernel_center = tex2D(tex, uv).rgb;
float3 kernel_small_1 = 0;
offset_uv.xy = uv.xy - kernel_small_offsets.xy;
kernel_small_1 += tex2Dlod(tex, offset_uv).rgb; //--
offset_uv.x += kernel_small_offsets.z;
kernel_small_1 += tex2Dlod(tex, offset_uv).rgb; //+-
offset_uv.y += kernel_small_offsets.w;
kernel_small_1 += tex2Dlod(tex, offset_uv).rgb; //++
offset_uv.x -= kernel_small_offsets.z;
kernel_small_1 += tex2Dlod(tex, offset_uv).rgb; //-+
#if SAMPLE_HIGH_QUALITY == 0
return kernel_center / 5.0
+ kernel_small_1 / 5.0;
#else
float3 kernel_small_2 = 0;
offset_uv.xy = uv.xy + float2(kernel_small_offsets.x, 0);
kernel_small_2 += tex2Dlod(tex, offset_uv).rgb; //+0
offset_uv.x -= kernel_small_offsets.z;
kernel_small_2 += tex2Dlod(tex, offset_uv).rgb; //-0
offset_uv.xy = uv.xy + float2(0, kernel_small_offsets.y);
kernel_small_2 += tex2Dlod(tex, offset_uv).rgb; //0+
offset_uv.y -= kernel_small_offsets.w;
kernel_small_2 += tex2Dlod(tex, offset_uv).rgb; //0-
return kernel_center * 4.0 / 16.0
+ kernel_small_1 * 1.0 / 16.0
+ kernel_small_2 * 2.0 / 16.0;
#endif
}
/*=============================================================================
Pixel Shaders
=============================================================================*/
void PS_BloomPrepass(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 color : SV_Target0)
{
color = downsample(qUINT::sBackBufferTex, qUINT::SCREEN_SIZE, uv);
color.w = saturate(dot(color.rgb, 0.333));
color.rgb = lerp(color.w, color.rgb, BLOOM_SAT);
color.rgb *= (pow(color.w, BLOOM_CURVE) * BLOOM_INTENSITY * BLOOM_INTENSITY * BLOOM_INTENSITY) / (color.w + 1e-3);
}
void PS_Downsample1(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTexSource, ldexp(qUINT::SCREEN_SIZE, -1.0), uv);
}
void PS_Downsample2(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTex1, ldexp(qUINT::SCREEN_SIZE, -2.0), uv);
}
void PS_Downsample3(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTex2, ldexp(qUINT::SCREEN_SIZE, -3.0), uv);
}
void PS_Downsample4(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTex3, ldexp(qUINT::SCREEN_SIZE, -4.0), uv);
}
void PS_Downsample5(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTex4, ldexp(qUINT::SCREEN_SIZE, -5.0), uv);
}
void PS_Downsample6(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTex5, ldexp(qUINT::SCREEN_SIZE, -6.0), uv);
}
void PS_Downsample7(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = downsample(sMXBLOOM_BloomTex6, ldexp(qUINT::SCREEN_SIZE, -7.0), uv);
bloom.w = lerp(tex2D(sMXBLOOM_BloomTexAdapt, 0).x /*last*/,
bloom.w /*current*/,
saturate(qUINT::FRAME_TIME * 1e-3 * BLOOM_ADAPT_SPEED));
}
void PS_AdaptStoreLast(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float adapt : SV_Target0)
{ adapt = tex2Dlod(sMXBLOOM_BloomTex7, float4(uv.xy,0,BloomTex7_LowestMip)).w;}
void PS_Upsample1(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = float4(Upsample(sMXBLOOM_BloomTex7, ldexp(qUINT::PIXEL_SIZE, 7.0), uv) * BLOOM_LAYER_MULT_7, BLOOM_LAYER_MULT_6);}
void PS_Upsample2(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = float4(Upsample(sMXBLOOM_BloomTex6, ldexp(qUINT::PIXEL_SIZE, 6.0), uv), BLOOM_LAYER_MULT_5);
}
void PS_Upsample3(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = float4(Upsample(sMXBLOOM_BloomTex5, ldexp(qUINT::PIXEL_SIZE, 5.0), uv), BLOOM_LAYER_MULT_4);
}
void PS_Upsample4(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = float4(Upsample(sMXBLOOM_BloomTex4, ldexp(qUINT::PIXEL_SIZE, 4.0), uv), BLOOM_LAYER_MULT_3);
}
void PS_Upsample5(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = float4(Upsample(sMXBLOOM_BloomTex3, ldexp(qUINT::PIXEL_SIZE, 3.0), uv), BLOOM_LAYER_MULT_2);
}
void PS_Upsample6(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 bloom : SV_Target0)
{
bloom = float4(Upsample(sMXBLOOM_BloomTex2, ldexp(qUINT::PIXEL_SIZE, 2.0), uv), BLOOM_LAYER_MULT_1);
}
void PS_Combine(in float4 pos : SV_Position, in float2 uv : TEXCOORD, out float4 color : SV_Target0)
{
float3 bloom = Upsample(sMXBLOOM_BloomTex1, ldexp(qUINT::PIXEL_SIZE, 1.0), uv);
bloom /= dot(float4(BLOOM_LAYER_MULT_1, BLOOM_LAYER_MULT_2, BLOOM_LAYER_MULT_3, BLOOM_LAYER_MULT_4), 1) + dot(float3(BLOOM_LAYER_MULT_5, BLOOM_LAYER_MULT_6, BLOOM_LAYER_MULT_7), 1);
color = tex2D(qUINT::sBackBufferTex, uv);
float adapt = tex2D(sMXBLOOM_BloomTexAdapt, 0).x + 1e-3; // we lerped to 0.5 earlier.
adapt *= 8;
//based on suggestion by https://github.com/KarlRamstedt
if(BLOOM_ADAPT_MODE)
{
bloom *= lerp(1, rcp(adapt), BLOOM_ADAPT_STRENGTH);
bloom *= exp2(BLOOM_ADAPT_EXPOSURE);
color.rgb += bloom;
}
else
{
color.rgb += bloom;
color.rgb *= lerp(1, rcp(adapt), BLOOM_ADAPT_STRENGTH);
color.rgb *= exp2(BLOOM_ADAPT_EXPOSURE);
}
color.rgb = pow(max(0,color.rgb), BLOOM_TONEMAP_COMPRESSION);
color.rgb = color.rgb / (1.0 + color.rgb);
color.rgb = pow(color.rgb, 1.0 / BLOOM_TONEMAP_COMPRESSION);
}
/*=============================================================================
Techniques
=============================================================================*/
technique Bloom
< ui_tooltip = " >> qUINT::Bloom <<\n\n"
"Bloom is a shader that produces a glow around bright\n"
"light sources and other emitters on screen.\n"
"\nBloom is written by Marty McFly / Pascal Gilcher"; >
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomPrepass;
RenderTarget0 = MXBLOOM_BloomTexSource;
}
#define PASS_DOWNSAMPLE(i) pass { VertexShader = PostProcessVS; PixelShader = PS_Downsample##i; RenderTarget0 = MXBLOOM_BloomTex##i; }
PASS_DOWNSAMPLE(1)
PASS_DOWNSAMPLE(2)
PASS_DOWNSAMPLE(3)
PASS_DOWNSAMPLE(4)
PASS_DOWNSAMPLE(5)
PASS_DOWNSAMPLE(6)
PASS_DOWNSAMPLE(7)
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_AdaptStoreLast;
RenderTarget0 = MXBLOOM_BloomTexAdapt;
}
#define PASS_UPSAMPLE(i,j) pass {VertexShader = PostProcessVS;PixelShader = PS_Upsample##i;RenderTarget0 = MXBLOOM_BloomTex##j;ClearRenderTargets = false;BlendEnable = true;BlendOp = ADD;SrcBlend = ONE;DestBlend = SRCALPHA;}
PASS_UPSAMPLE(1,6)
PASS_UPSAMPLE(2,5)
PASS_UPSAMPLE(3,4)
PASS_UPSAMPLE(4,3)
PASS_UPSAMPLE(5,2)
PASS_UPSAMPLE(6,1)
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_Combine;
}
}

View File

@ -0,0 +1,199 @@
/*
changelog:
2.0.0: added frame count parameter
added versioning system
removed common textures - should only be declared if needed
flipped reversed depth buffer switch by default as most games use this format
2.0.1: added more depth scaling parameters to match ReShade.fxh
2.0.2: added UI for depth linearization when loaded by NVIDIA FreeStyle/Ansel
with cue given by effect if depth is required
2.0.3: fixed scaling ( "-define" resulted in "--define" if define was negative)
split depth buffer retrieval into 2 functions, so that nonlinearized
depth can also be taken and a given depth be linearized manually
2.0.4: splitted get_depth function into submodules that correct UV scaling and alignment
and a function that samples depth using this corrected UV
2.0.5: renamed linear_depth(depth) to linearize_depth(depth). Polymorphism is cool, but unintuitive.
Perfect time to do this change now as no filter uses that function in this way yet.
2.0.6: added new pixel offsets to depth buffer and reorganized the existing defines
*/
/*=============================================================================
Version checks
=============================================================================*/
#ifndef RESHADE_QUINT_COMMON_VERSION
#define RESHADE_QUINT_COMMON_VERSION 206
#endif
#if RESHADE_QUINT_COMMON_VERSION_REQUIRE > RESHADE_QUINT_COMMON_VERSION
#error "qUINT_common.fxh outdated."
#error "Please download update from github.com/martymcmodding/qUINT"
#endif
#if !defined(RESHADE_QUINT_COMMON_VERSION_REQUIRE)
#error "Incompatible qUINT_common.fxh and shaders."
#error "Do not mix different file versions."
#endif
#if !defined(__RESHADE__) || __RESHADE__ < 40000
#error "ReShade 4.4+ is required to use this header file"
#endif
/*=============================================================================
Define defaults
=============================================================================*/
//depth buffer
#ifndef RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
#define RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN 0
#endif
#ifndef RESHADE_DEPTH_INPUT_IS_REVERSED
#define RESHADE_DEPTH_INPUT_IS_REVERSED 1
#endif
#ifndef RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
#define RESHADE_DEPTH_INPUT_IS_LOGARITHMIC 0
#endif
#ifndef RESHADE_DEPTH_LINEARIZATION_FAR_PLANE
#define RESHADE_DEPTH_LINEARIZATION_FAR_PLANE 1000.0
#endif
//new compatibility flags
#ifndef RESHADE_DEPTH_MULTIPLIER
#define RESHADE_DEPTH_MULTIPLIER 1 //mcfly: probably not a good idea, many shaders depend on having depth range 0-1
#endif
#ifndef RESHADE_DEPTH_INPUT_X_SCALE
#define RESHADE_DEPTH_INPUT_X_SCALE 1
#endif
#ifndef RESHADE_DEPTH_INPUT_Y_SCALE
#define RESHADE_DEPTH_INPUT_Y_SCALE 1
#endif
// An offset to add to the X coordinate, (+) = move right, (-) = move left
#ifndef RESHADE_DEPTH_INPUT_X_OFFSET
#define RESHADE_DEPTH_INPUT_X_OFFSET 0
#endif
// An offset to add to the Y coordinate, (+) = move up, (-) = move down
#ifndef RESHADE_DEPTH_INPUT_Y_OFFSET
#define RESHADE_DEPTH_INPUT_Y_OFFSET 0
#endif
// An offset to add to the X coordinate, (+) = move right, (-) = move left
#ifndef RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET
#define RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET 0
#endif
// An offset to add to the Y coordinate, (+) = move up, (-) = move down
#ifndef RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET
#define RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET 0
#endif
/*=============================================================================
Depth UI
=============================================================================*/
#if defined(__RESHADE_FXC__)
//if using FreeStyle or Ansel and effect requires depth, make UI toggle
//available. If not, replace with dummy which is unused anyways.
#if defined(RESHADE_QUINT_EFFECT_DEPTH_REQUIRE)
uniform bool UI_RESHADE_DEPTH_INPUT_IS_REVERSED <
ui_type = "bool";
ui_label = "Depth input is reversed";
> = RESHADE_DEPTH_INPUT_IS_REVERSED; //use default preprocessor setting
#else
#define UI_RESHADE_DEPTH_INPUT_IS_REVERSED RESHADE_DEPTH_INPUT_IS_REVERSED
#endif
#endif
/*=============================================================================
Uniforms
=============================================================================*/
namespace qUINT
{
uniform float FRAME_TIME < source = "frametime"; >;
uniform int FRAME_COUNT < source = "framecount"; >;
#if defined(__RESHADE_FXC__)
float2 get_aspect_ratio() { return float2(1.0, BUFFER_WIDTH * BUFFER_RCP_HEIGHT); }
float2 get_pixel_size() { return float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT); }
float2 get_screen_size() { return float2(BUFFER_WIDTH, BUFFER_HEIGHT); }
#define ASPECT_RATIO get_aspect_ratio()
#define PIXEL_SIZE get_pixel_size()
#define SCREEN_SIZE get_screen_size()
#else
static const float2 ASPECT_RATIO = float2(1.0, BUFFER_WIDTH * BUFFER_RCP_HEIGHT);
static const float2 PIXEL_SIZE = float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT);
static const float2 SCREEN_SIZE = float2(BUFFER_WIDTH, BUFFER_HEIGHT);
#endif
// Global textures and samplers
texture BackBufferTex : COLOR;
texture DepthBufferTex : DEPTH;
sampler sBackBufferTex { Texture = BackBufferTex; };
sampler sDepthBufferTex { Texture = DepthBufferTex; };
float2 depthtex_uv(float2 uv)
{
#if RESHADE_DEPTH_INPUT_IS_UPSIDE_DOWN
uv.y = 1.0 - uv.y;
#endif
uv.x /= RESHADE_DEPTH_INPUT_X_SCALE;
uv.y /= RESHADE_DEPTH_INPUT_Y_SCALE;
#if RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET
uv.x -= RESHADE_DEPTH_INPUT_X_PIXEL_OFFSET * BUFFER_RCP_WIDTH;
#else // Do not check RESHADE_DEPTH_INPUT_X_OFFSET, since it may be a decimal number, which the preprocessor cannot handle
uv.x -= RESHADE_DEPTH_INPUT_X_OFFSET / 2.000000001;
#endif
#if RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET
uv.y += RESHADE_DEPTH_INPUT_Y_PIXEL_OFFSET * BUFFER_RCP_HEIGHT;
#else
uv.y += RESHADE_DEPTH_INPUT_Y_OFFSET / 2.000000001;
#endif
return uv;
}
float get_depth(float2 uv)
{
float depth = tex2Dlod(sDepthBufferTex, float4(depthtex_uv(uv), 0, 0)).x;
return depth;
}
float linearize_depth(float depth)
{
depth *= RESHADE_DEPTH_MULTIPLIER;
#if RESHADE_DEPTH_INPUT_IS_LOGARITHMIC
const float C = 0.01;
depth = (exp(depth * log(C + 1.0)) - 1.0) / C;
#endif
#if defined(__RESHADE_FXC__)
depth = UI_RESHADE_DEPTH_INPUT_IS_REVERSED ? 1.0 - depth : depth;
#else
#if RESHADE_DEPTH_INPUT_IS_REVERSED
depth = 1.0 - depth;
#endif
#endif
const float N = 1.0;
depth /= RESHADE_DEPTH_LINEARIZATION_FAR_PLANE - depth * (RESHADE_DEPTH_LINEARIZATION_FAR_PLANE - N);
return saturate(depth);
}
//standard linear depth fetch
float linear_depth(float2 uv)
{
float depth = get_depth(uv);
depth = linearize_depth(depth);
return depth;
}
}
// Vertex shader generating a triangle covering the entire screen
void PostProcessVS(in uint id : SV_VertexID, out float4 vpos : SV_Position, out float2 uv : TEXCOORD)
{
uv.x = (id == 2) ? 2.0 : 0.0;
uv.y = (id == 1) ? 2.0 : 0.0;
vpos = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}

View File

@ -0,0 +1,134 @@
/*=============================================================================
ReShade 4 effect file
github.com/martymcmodding
Support me:
paypal.me/mcflypg
patreon.com/mcflypg
Dither / Deband filter
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
=============================================================================*/
/*=============================================================================
Preprocessor settings
=============================================================================*/
/*=============================================================================
UI Uniforms
=============================================================================*/
uniform float SEARCH_RADIUS <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Debanding Search Radius";
> = 0.5;
uniform int BIT_DEPTH <
ui_type = "slider";
ui_min = 4; ui_max = 10;
ui_label = "Bit depth of data to be debanded";
> = 8;
uniform bool AUTOMATE_BIT_DEPTH <
ui_label = "Automatic bit depth detection";
> = true;
uniform int DEBAND_MODE <
ui_type = "radio";
ui_label = "Dither mode";
ui_items = "None\0Dither\0Deband\0";
> = 2;
uniform bool SKY_ONLY <
ui_label = "Apply to sky only";
> = false;
/*=============================================================================
Textures, Samplers, Globals
=============================================================================*/
#define RESHADE_QUINT_COMMON_VERSION_REQUIRE 202
#include "qUINT_common.fxh"
/*=============================================================================
Vertex Shader
=============================================================================*/
struct VSOUT
{
float4 vpos : SV_Position;
float2 uv : TEXCOORD0;
};
VSOUT VSMain(in uint id : SV_VertexID)
{
VSOUT o;
PostProcessVS(id, o.vpos, o.uv); //use original fullscreen triangle VS
return o;
}
/*=============================================================================
Functions
=============================================================================*/
/*=============================================================================
Pixel Shaders
=============================================================================*/
void PSMain(in VSOUT i, out float3 o : SV_Target0)
{
o = tex2D(qUINT::sBackBufferTex, i.uv).rgb;
const float2 magicdot = float2(0.75487766624669276, 0.569840290998);
const float3 magicadd = float3(0, 0.025, 0.0125) * dot(magicdot, 1);
float3 dither = frac(dot(i.vpos.xy, magicdot) + magicadd);
if(SKY_ONLY)
{
if(qUINT::linear_depth(i.uv) < 0.98) return;
}
float bit_depth = AUTOMATE_BIT_DEPTH ? BUFFER_COLOR_BIT_DEPTH : BIT_DEPTH;
float lsb = rcp(exp2(bit_depth) - 1.0);
if(DEBAND_MODE == 2)
{
float2 shift;
sincos(6.283 * 30.694 * dither.x, shift.x, shift.y);
shift = shift * sqrt(dither.y);
float3 scatter = tex2Dlod(qUINT::sBackBufferTex, float4(i.uv + shift * 0.025 * SEARCH_RADIUS, 0, 0)).rgb;
float4 diff;
diff.rgb = abs(o.rgb - scatter);
diff.w = max(max(diff.x, diff.y), diff.z);
o = lerp(o, scatter, diff.w <= lsb);
}
else if(DEBAND_MODE == 1)
{
o += (dither - 0.5) * lsb;
}
}
/*=============================================================================
Techniques
=============================================================================*/
technique Debanding
< ui_tooltip = " >> qUINT::Debanding <<\n\n"
"This is a simple debanding filter, which aims to hide color\n"
"quantization artifacts in games. \n"
"\nqUINT Debanding is written by Marty McFly / Pascal Gilcher"; >
{
pass
{
VertexShader = VSMain;
PixelShader = PSMain;
}
}

View File

@ -0,0 +1,772 @@
/*=============================================================================
ReShade 4 effect file
github.com/martymcmodding
Support me:
paypal.me/mcflypg
patreon.com/mcflypg
Advanced Depth of Field "ADoF"
by Marty McFly / P.Gilcher
part of qUINT shader library for ReShade 4
Copyright (c) Pascal Gilcher / Marty McFly. All rights reserved.
=============================================================================*/
/*
TODO: extend tiles to contain min abs depth for better high precision sampling
*/
/*=============================================================================
Preprocessor settings
=============================================================================*/
//------------------------------------------------------------------
//Enables partial occlusion of bokeh disc at screen corners
#ifndef ADOF_OPTICAL_VIGNETTE_ENABLE
#define ADOF_OPTICAL_VIGNETTE_ENABLE 0 //[0 or 1]
#endif
//------------------------------------------------------------------
//Enables chromatic aberration at bokeh shape borders.
#ifndef ADOF_CHROMATIC_ABERRATION_ENABLE
#define ADOF_CHROMATIC_ABERRATION_ENABLE 1 //[0 or 1]
#endif
/*=============================================================================
UI Uniforms
=============================================================================*/
uniform bool bADOF_AutofocusEnable <
ui_type = "bool";
ui_label = "Enable Autofocus";
ui_tooltip = "Enables automated focus calculation.";
ui_category = "Focusing";
> = true;
uniform float2 fADOF_AutofocusCenter <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_label = "Autofocus Center";
ui_tooltip = "X and Y coordinates of autofocus center. Axes start from upper left screen corner.";
ui_category = "Focusing";
> = float2(0.5, 0.5);
uniform float fADOF_AutofocusRadius <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Autofocus sample radius";
ui_tooltip = "Radius of area contributing to focus calculation.";
ui_category = "Focusing";
> = 0.6;
uniform float fADOF_AutofocusSpeed <
ui_type = "drag";
ui_min = 0.05;
ui_max = 1.0;
ui_label = "Autofocus Adjustment Speed";
ui_tooltip = "Adjustment speed of autofocus on focus change";
ui_category = "Focusing";
> = 0.1;
uniform float fADOF_ManualfocusDepth <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Manual focus depth";
ui_tooltip = "Manually adjusted static focus depth, disable autofocus to use it.";
ui_category = "Focusing";
> = 0.001;
uniform float fADOF_NearBlurCurve <
ui_type = "drag";
ui_min = 0.5;
ui_max = 6.0;
ui_label = "Near blur curve";
ui_category = "Focusing";
> = 6.0;
uniform float fADOF_FarBlurCurve <
ui_type = "drag";
ui_min = 0.5;
ui_max = 6.0;
ui_label = "Far blur curve";
ui_category = "Focusing";
> = 1.5;
uniform float fADOF_HyperFocus <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Hyperfocal depth distance";
ui_category = "Focusing";
> = 0.10;
uniform float fADOF_RenderResolutionMult <
ui_type = "drag";
ui_min = 0.5;
ui_max = 1.0;
ui_label = "Size Scale";
ui_tooltip = "Resolution Scale of bokeh blur. 0.5 means 1/2 screen width and height.";
ui_category = "Blur & Quality";
> = 0.5;
uniform float fADOF_ShapeRadius <
ui_type = "drag";
ui_min = 0.0;
ui_max = 100.0;
ui_label = "Bokeh Maximal Blur Size";
ui_tooltip = "Blur size of areas entirely out of focus.";
ui_category = "Blur & Quality";
> = 20.5;
uniform float fADOF_SmootheningAmount <
ui_type = "drag";
ui_min = 0.0;
ui_max = 20.0;
ui_label = "Gaussian blur width";
ui_tooltip = "Width of gaussian blur after bokeh filter.";
ui_category = "Blur & Quality";
> = 4.0;
uniform float fADOF_BokehIntensity <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Bokeh Intensity";
ui_tooltip = "Intensity of bokeh discs.";
ui_category = "Bokeh";
> = 0.3;
uniform int iADOF_BokehMode <
ui_type = "slider";
ui_min = 0;
ui_max = 3;
ui_label = "Bokeh highlight type";
ui_tooltip = "Different methods to emphasize bokeh sprites";
ui_category = "Bokeh";
> = 2;
uniform int iADOF_ShapeVertices <
ui_type = "drag";
ui_min = 3;
ui_max = 9;
ui_label = "Bokeh shape vertices";
ui_tooltip = "Vertices of bokeh kernel. 5 = pentagon, 6 = hexagon etc.";
ui_category = "Bokeh";
> = 6;
uniform int iADOF_ShapeQuality <
ui_type = "drag";
ui_min = 2;
ui_max = 25;
ui_label = "Bokeh shape quality";
ui_category = "Bokeh";
> = 5;
uniform float fADOF_ShapeCurvatureAmount <
ui_type = "drag";
ui_min = -1.0;
ui_max = 1.0;
ui_label = "Bokeh shape roundness";
ui_tooltip = "Roundness of bokeh kernel. 1.0 = circle, 0.0 = polygon.";
ui_category = "Bokeh";
> = 1.0;
uniform float fADOF_ShapeRotation <
ui_type = "drag";
ui_min = 0.0;
ui_max = 360.0;
ui_label = "Bokeh shape rotation";
ui_category = "Bokeh";
> = 0.0;
uniform float fADOF_ShapeAnamorphRatio <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Bokeh shape aspect ratio";
ui_category = "Bokeh";
> = 1.0;
#if(ADOF_OPTICAL_VIGNETTE_ENABLE != 0)
uniform float fADOF_ShapeVignetteCurve <
ui_type = "drag";
ui_min = 0.5;
ui_max = 2.5;
ui_label = "Bokeh shape vignette curve";
ui_category = "Bokeh";
> = 0.75;
uniform float fADOF_ShapeVignetteAmount <
ui_type = "drag";
ui_min = 0.0;
ui_max = 2.0;
ui_label = "Bokeh shape vignette amount";
ui_category = "Bokeh";
> = 1.0;
#endif
#if(ADOF_CHROMATIC_ABERRATION_ENABLE != 0)
uniform float fADOF_ShapeChromaAmount <
ui_type = "drag";
ui_min = -1.0;
ui_max = 1.0;
ui_label = "Shape chromatic aberration amount";
ui_category = "Chromatic Aberration";
> = -0.1;
uniform int iADOF_ShapeChromaMode <
ui_type = "drag";
ui_min = 0;
ui_max = 2;
ui_label = "Shape chromatic aberration type";
ui_category = "Chromatic Aberration";
> = 2;
#endif
/*=============================================================================
Textures, Samplers, Globals
=============================================================================*/
#define RESHADE_QUINT_COMMON_VERSION_REQUIRE 202
#define RESHADE_QUINT_EFFECT_DEPTH_REQUIRE //effect requires depth access
#include "qUINT_common.fxh"
#define DISCRADIUS_RESOLUTION_BOUNDARY_LOWER 0.25//1.0 //used for blending blurred scene.
#define DISCRADIUS_RESOLUTION_BOUNDARY_UPPER 2.0//6.0 //used for blending blurred scene.
#define DISCRADIUS_RESOLUTION_BOUNDARY_CURVE 0.5 //used for blending blurred scene.
#define FPS_HAND_BLUR_CUTOFF_DIST 0.3353 //fps hand depth (x10.000), change if you perceive blurred fps weapons.
#define FPS_HAND_BLUR_CUTOFF_CHECK 0 //blur = max if depth > hand depth, else 0, useful for tweaking above param
#define GAUSSIAN_BUILDUP_MULT 4.0 //value of x -> gaussian reaches max radius at |CoC| == 1/x
texture2D ADOF_FocusTex { Format = R16F; };
texture2D ADOF_FocusTexPrev { Format = R16F; };
sampler2D sADOF_FocusTex { Texture = ADOF_FocusTex; };
sampler2D sADOF_FocusTexPrev { Texture = ADOF_FocusTexPrev; };
texture2D CommonTex0 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler2D sCommonTex0 { Texture = CommonTex0; };
texture2D CommonTex1 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler2D sCommonTex1 { Texture = CommonTex1; };
/*=============================================================================
Vertex Shader
=============================================================================*/
struct ADOF_VSOUT
{
float4 vpos : SV_Position;
float4 txcoord : TEXCOORD0;
float4 offset0 : TEXCOORD1;
float2x2 offsmat : TEXCOORD2;
};
ADOF_VSOUT VS_ADOF(in uint id : SV_VertexID)
{
ADOF_VSOUT OUT;
OUT.txcoord.x = (id == 2) ? 2.0 : 0.0;
OUT.txcoord.y = (id == 1) ? 2.0 : 0.0;
OUT.txcoord.zw = OUT.txcoord.xy / fADOF_RenderResolutionMult;
OUT.vpos = float4(OUT.txcoord.xy * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
//can't precompute vertices directly, not enough registers in sm3
sincos(6.2831853 / iADOF_ShapeVertices, OUT.offsmat._21, OUT.offsmat._22);
OUT.offsmat._11 = OUT.offsmat._22;
OUT.offsmat._12 = -OUT.offsmat._21;
sincos(radians(fADOF_ShapeRotation), OUT.offset0.x, OUT.offset0.y);
OUT.offset0.zw = mul(OUT.offset0.xy, OUT.offsmat);
return OUT;
}
/*=============================================================================
Functions
=============================================================================*/
float GetLinearDepth(float2 coords)
{
return qUINT::linear_depth(coords);
}
float CircleOfConfusion(float2 texcoord, bool aggressiveLeakReduction)
{
float2 depthdata; //x - linear scene depth, y - linear scene focus
float scenecoc; //blur value, signed by position relative to focus plane
depthdata.x = GetLinearDepth(texcoord.xy);
[branch]
if(aggressiveLeakReduction)
{
float3 neighbourOffsets = float3(qUINT::PIXEL_SIZE.xy, 0);
//sadly, flipped depth buffers etc don't allow for gather or linearizing in batch
float4 neighbourDepths = float4(GetLinearDepth(texcoord.xy - neighbourOffsets.xz), //left
GetLinearDepth(texcoord.xy + neighbourOffsets.xz), //right
GetLinearDepth(texcoord.xy - neighbourOffsets.zy), //top
GetLinearDepth(texcoord.xy + neighbourOffsets.zy));//bottom
float neighbourMin = min(min(neighbourDepths.x,neighbourDepths.y),min(neighbourDepths.z,neighbourDepths.w));
depthdata.x = lerp(min(neighbourMin, depthdata.x), depthdata.x, 0.001);
}
depthdata.y = tex2D(sADOF_FocusTex, texcoord.xy).x;
float handdepth = depthdata.x;
depthdata.xy = saturate(depthdata.xy / fADOF_HyperFocus);
[branch]
if(depthdata.x < depthdata.y)
{
scenecoc = depthdata.x / depthdata.y - 1.0;
scenecoc *= exp2(-0.5*fADOF_NearBlurCurve*fADOF_NearBlurCurve);
}
else
{
scenecoc = (depthdata.x - depthdata.y)/((depthdata.y * exp2(fADOF_FarBlurCurve*fADOF_FarBlurCurve)) - depthdata.y);
scenecoc = saturate(scenecoc);
}
#if(FPS_HAND_BLUR_CUTOFF_CHECK != 0)
scenecoc = (handdepth < FPS_HAND_BLUR_CUTOFF_DIST * 1e-4) ? 0.0 : 1.0;
#else //FPS_HAND_BLUR_CUTOFF_CHECK
scenecoc = (handdepth < FPS_HAND_BLUR_CUTOFF_DIST * 1e-4) ? 0.0 : scenecoc;
#endif //FPS_HAND_BLUR_CUTOFF_CHECK
return scenecoc;
}
void ShapeRoundness(inout float2 sampleOffset, in float roundness)
{
sampleOffset *= (1.0-roundness) + rsqrt(dot(sampleOffset,sampleOffset))*roundness;
}
void OpticalVignette(in float2 sampleOffset, in float2 centerVec, inout float sampleWeight)
{
sampleOffset -= centerVec; //scaled by vignette intensity
sampleWeight *= saturate(3.333 - dot(sampleOffset,sampleOffset) * 1.666); //notsosmoothstep to avoid aliasing
}
float2 CoC2BlurRadius(float CoC)
{
return float2(fADOF_ShapeAnamorphRatio, qUINT::ASPECT_RATIO.y) * CoC * fADOF_ShapeRadius * 6e-4;
}
/*=============================================================================
Pixel Shaders
=============================================================================*/
void PS_CopyBackBuffer(in ADOF_VSOUT IN, out float4 color : SV_Target0)
{
color = tex2D(qUINT::sBackBufferTex, IN.txcoord.xy);
}
void PS_ReadFocus(in ADOF_VSOUT IN, out float focus : SV_Target0)
{
float scenefocus = 0.0;
[branch]
if(bADOF_AutofocusEnable == true)
{
float samples = 10.0;
float weightsum = 1e-6;
for(float xcoord = 0.0; xcoord < samples; xcoord++)
for(float ycoord = 0.0; ycoord < samples; ycoord++)
{
float2 sampleOffset = (float2(xcoord,ycoord) + 0.5) / samples;
sampleOffset = sampleOffset * 2.0 - 1.0;
sampleOffset *= fADOF_AutofocusRadius;
sampleOffset += (fADOF_AutofocusCenter - 0.5);
float sampleWeight = saturate(1.2 * exp2(-dot(sampleOffset,sampleOffset)*4.0));
float tempfocus = GetLinearDepth(sampleOffset * 0.5 + 0.5);
sampleWeight *= rcp(tempfocus + 0.001);
sampleWeight *= saturate(tempfocus > FPS_HAND_BLUR_CUTOFF_DIST * 1e-4); //remove fps hands from focus calculations
scenefocus += tempfocus * sampleWeight;
weightsum += sampleWeight;
}
scenefocus /= weightsum;
}
else
{
scenefocus = fADOF_ManualfocusDepth * fADOF_ManualfocusDepth;
}
float prevscenefocus = tex2D(sADOF_FocusTexPrev, 0.5).x;
float adjustmentspeed = fADOF_AutofocusSpeed * fADOF_AutofocusSpeed;
adjustmentspeed *= prevscenefocus > scenefocus ? 2.0 : 1.0;
focus = lerp(prevscenefocus, scenefocus, saturate(adjustmentspeed));
}
void PS_CopyFocus(in ADOF_VSOUT IN, out float focus : SV_Target0)
{
focus = tex2D(sADOF_FocusTex, IN.txcoord.xy).x;
}
void PS_CoC(in ADOF_VSOUT IN, out float4 color : SV_Target0)
{
color = tex2D(qUINT::sBackBufferTex, IN.txcoord.xy);
static const float2 sampleOffsets[4] = { float2( 1.5, 0.5) * qUINT::PIXEL_SIZE.xy,
float2( 0.5,-1.5) * qUINT::PIXEL_SIZE.xy,
float2(-1.5,-0.5) * qUINT::PIXEL_SIZE.xy,
float2(-0.5, 1.5) * qUINT::PIXEL_SIZE.xy};
float centerDepth = GetLinearDepth(IN.txcoord.xy);
float4 sampleCoord = 0.0;
float3 neighbourOffsets = float3(qUINT::PIXEL_SIZE.xy, 0);
float4 coccolor = 0.0;
[loop]
for(int i=0; i<4; i++)
{
sampleCoord.xy = IN.txcoord.xy + sampleOffsets[i];
float3 sampleColor = tex2Dlod(qUINT::sBackBufferTex, sampleCoord).rgb;
float4 sampleDepths = float4(GetLinearDepth(sampleCoord.xy + neighbourOffsets.xz), //right
GetLinearDepth(sampleCoord.xy - neighbourOffsets.xz), //left
GetLinearDepth(sampleCoord.xy + neighbourOffsets.zy), //bottom
GetLinearDepth(sampleCoord.xy - neighbourOffsets.zy)); //top
float sampleDepthMin = min(min(sampleDepths.x,sampleDepths.y),min(sampleDepths.z,sampleDepths.w));
sampleColor /= 1.0 + max(max(sampleColor.r, sampleColor.g), sampleColor.b);
float sampleWeight = saturate(sampleDepthMin * rcp(centerDepth) + 1e-3);
coccolor += float4(sampleColor.rgb * sampleWeight, sampleWeight);
}
coccolor.rgb /= coccolor.a;
coccolor.rgb /= 1.0 - max(coccolor.r, max(coccolor.g, coccolor.b));
color.rgb = lerp(color.rgb, coccolor.rgb, saturate(coccolor.w * 8.0));
color.w = CircleOfConfusion(IN.txcoord.xy, 1);
color.w = saturate(color.w * 0.5 + 0.5);
}
void unpack_hdr(inout float3 color)
{
color = color * rcp(1.2 - saturate(color));
}
void pack_hdr(inout float3 color)
{
color = 1.2 * color * rcp(color + 1.0);
}
float4 PS_DoF_Main(in ADOF_VSOUT IN) : SV_Target0
{
if(max(IN.txcoord.z,IN.txcoord.w) > 1.01) discard;
float4 BokehSum, BokehMax;
BokehMax = tex2D(sCommonTex0, IN.txcoord.zw);
BokehSum = BokehMax;
float weightSum = 1.0;
float CoC = abs(BokehSum.w * 2.0 - 1.0);
float2 bokehRadiusScaled = CoC2BlurRadius(CoC);
float nRings = lerp(1.0,iADOF_ShapeQuality,saturate(CoC)) + (dot(IN.vpos.xy,1) % 2) * 0.5;
if(bokehRadiusScaled.x < DISCRADIUS_RESOLUTION_BOUNDARY_LOWER * qUINT::PIXEL_SIZE.x) return BokehSum;
bokehRadiusScaled /= nRings;
CoC /= nRings;
#if (ADOF_OPTICAL_VIGNETTE_ENABLE != 0)
float2 centerVec = IN.txcoord.zw - 0.5;
float centerDist = sqrt(dot(centerVec,centerVec));
float vignette = pow(centerDist, fADOF_ShapeVignetteCurve) * fADOF_ShapeVignetteAmount;
centerVec = centerVec / centerDist * vignette;
weightSum *= saturate(3.33 - vignette * 2.0);
BokehSum *= weightSum;
BokehMax *= weightSum;
#endif
int densityScale = max(1, 6 - iADOF_ShapeVertices);
[loop]
for (int iVertices = 0; iVertices < iADOF_ShapeVertices && iVertices < 10; iVertices++)
{
[loop]
for(float iRings = 1; iRings <= nRings && iRings < 26; iRings++)
{
[loop]
for(float iSamplesPerRing = 0; iSamplesPerRing < iRings * densityScale && iSamplesPerRing < 26*2; iSamplesPerRing++)
{
float x = iSamplesPerRing/(iRings * densityScale);
float a = x * x * (3.0 - 2.0 * x);
float l = 2.55 * rcp(iADOF_ShapeVertices * iADOF_ShapeVertices * 0.4 - 1.0);
x = lerp(x, (1.0 + l) * x - a * l, fADOF_ShapeCurvatureAmount);
float2 sampleOffset = lerp(IN.offset0.xy,IN.offset0.zw, x);
ShapeRoundness(sampleOffset,fADOF_ShapeCurvatureAmount);
float4 sampleBokeh = tex2Dlod(sCommonTex0, float4(IN.txcoord.zw + sampleOffset.xy * (bokehRadiusScaled * iRings),0,0));
float sampleWeight = saturate(1e6 * (abs(sampleBokeh.a * 2.0 - 1.0) - CoC * (float)iRings) + 1.0);
#if (ADOF_OPTICAL_VIGNETTE_ENABLE != 0)
OpticalVignette(sampleOffset.xy * iRings/nRings, centerVec, sampleWeight);
#endif
sampleBokeh.rgb *= sampleWeight;
weightSum += sampleWeight;
BokehSum += sampleBokeh;
BokehMax = max(BokehMax,sampleBokeh);
}
}
IN.offset0.xy = IN.offset0.zw;
IN.offset0.zw = mul(IN.offset0.zw, IN.offsmat);
}
// return lerp(BokehSum / weightSum, BokehMax, fADOF_BokehIntensity * saturate(CoC*nRings*2.0));
float4 ret = 0;
BokehSum /= weightSum;
unpack_hdr(BokehSum.rgb);
unpack_hdr(BokehMax.rgb);
if(iADOF_BokehMode == 0)
{
ret = lerp(BokehSum, BokehMax, fADOF_BokehIntensity * saturate(CoC * nRings * 2.0));
}
else if(iADOF_BokehMode == 1)
{
float maxlum = dot(float3(0.3, 0.59, 0.11), BokehMax.rgb);
float avglum = dot(float3(0.3, 0.59, 0.11), BokehSum.rgb);
ret = BokehSum * lerp(avglum, maxlum, fADOF_BokehIntensity * saturate(CoC * nRings * 2.0)) / avglum;
}
else if(iADOF_BokehMode == 2)
{
float maxlum = dot(float3(0.3, 0.59, 0.11), BokehMax.rgb);
float avglum = dot(float3(0.3, 0.59, 0.11), BokehSum.rgb);
float bokehweight = max(0, maxlum - avglum);
bokehweight = bokehweight * fADOF_BokehIntensity * 2.0;
bokehweight *= bokehweight;
ret = BokehSum + BokehMax * saturate(bokehweight * CoC * nRings);
}
else if(iADOF_BokehMode == 3)
{
float maxlum = dot(float3(0.3, 0.59, 0.11), BokehMax.rgb);
float avglum = dot(float3(0.3, 0.59, 0.11), BokehSum.rgb);
float bokehweight = maxlum - avglum;
ret = lerp(BokehSum, BokehMax, saturate(bokehweight * CoC * nRings * fADOF_BokehIntensity));
}
pack_hdr(ret.rgb);
return ret;
}
void PS_DoF_Combine(in ADOF_VSOUT IN, out float4 color : SV_Target0)
{
float4 blurredColor = tex2D(sCommonTex1, IN.txcoord.xy * fADOF_RenderResolutionMult);
float4 originalColor = tex2D(qUINT::sBackBufferTex, IN.txcoord.xy);
float CoC = abs(CircleOfConfusion(IN.txcoord.xy, 0));
float bokehRadiusPixels = CoC2BlurRadius(CoC).x * BUFFER_WIDTH;
#define linearstep(a,b,x) saturate((x-a)/(b-a))
float blendWeight = linearstep(DISCRADIUS_RESOLUTION_BOUNDARY_LOWER, DISCRADIUS_RESOLUTION_BOUNDARY_UPPER, bokehRadiusPixels);
blendWeight = pow(blendWeight,DISCRADIUS_RESOLUTION_BOUNDARY_CURVE);
color.rgb = lerp(originalColor.rgb, blurredColor.rgb, blendWeight);
color.a = saturate(CoC * GAUSSIAN_BUILDUP_MULT) * 0.5 + 0.5;
}
void PS_DoF_Gauss1(in ADOF_VSOUT IN, out float4 color : SV_Target0)
{
float4 centerTap = tex2D(sCommonTex0, IN.txcoord.xy);
float CoC = abs(centerTap.a * 2.0 - 1.0);
float nSteps = floor(CoC * (fADOF_SmootheningAmount + 0.0));
float expCoeff = -2.0 * rcp(nSteps * nSteps + 1e-3); //sigma adjusted for blur width
float2 blurAxisScaled = float2(1,0) * qUINT::PIXEL_SIZE.xy;
float4 gaussianSum = 0.0;
float gaussianSumWeight = 1e-3;
for(float iStep = -nSteps; iStep <= nSteps; iStep++)
{
float currentWeight = exp(iStep * iStep * expCoeff);
float currentOffset = 2.0 * iStep - 0.5; //Sample between texels to double blur width at no cost
float4 currentTap = tex2Dlod(sCommonTex0, float4(IN.txcoord.xy + blurAxisScaled.xy * currentOffset, 0, 0));
currentWeight *= saturate(abs(currentTap.a * 2.0 - 1.0) - CoC * 0.25); //bleed fix
gaussianSum += currentTap * currentWeight;
gaussianSumWeight += currentWeight;
}
gaussianSum /= gaussianSumWeight;
color.rgb = lerp(centerTap.rgb, gaussianSum.rgb, saturate(gaussianSumWeight));
color.a = centerTap.a;
}
void PS_DoF_Gauss2(in ADOF_VSOUT IN, out float4 color : SV_Target0)
{
float4 centerTap = tex2D(sCommonTex1, IN.txcoord.xy);
float CoC = abs(centerTap.a * 2.0 - 1.0);
float nSteps = min(50,floor(CoC * (fADOF_SmootheningAmount + 0.0)));
float expCoeff = -2.0 * rcp(nSteps * nSteps + 1e-3); //sigma adjusted for blur width
float2 blurAxisScaled = float2(0,1) * qUINT::PIXEL_SIZE.xy;
float4 gaussianSum = 0.0;
float gaussianSumWeight = 1e-3;
for(float iStep = -nSteps; iStep <= nSteps; iStep++)
{
float currentWeight = exp(iStep * iStep * expCoeff);
float currentOffset = 2.0 * iStep - 0.5; //Sample between texels to double blur width at no cost
float4 currentTap = tex2Dlod(sCommonTex1, float4(IN.txcoord.xy + blurAxisScaled.xy * currentOffset, 0, 0));
currentWeight *= saturate(abs(currentTap.a * 2.0 - 1.0) - CoC * 0.25); //bleed fix
gaussianSum += currentTap * currentWeight;
gaussianSumWeight += currentWeight;
}
gaussianSum /= gaussianSumWeight;
color.rgb = lerp(centerTap.rgb, gaussianSum.rgb, saturate(gaussianSumWeight));
color.a = centerTap.a;
}
#if (ADOF_CHROMATIC_ABERRATION_ENABLE != 0)
void PS_DoF_ChromaticAberration(in ADOF_VSOUT IN, out float4 color : SV_Target0)
{
float4 colorVals[5];
float3 neighbourOffsets = float3(qUINT::PIXEL_SIZE.xy, 0);
colorVals[0] = tex2D(sCommonTex0, IN.txcoord.xy); //C
colorVals[1] = tex2D(sCommonTex0, IN.txcoord.xy - neighbourOffsets.xz); //L
colorVals[2] = tex2D(sCommonTex0, IN.txcoord.xy - neighbourOffsets.zy); //T
colorVals[3] = tex2D(sCommonTex0, IN.txcoord.xy + neighbourOffsets.xz); //R
colorVals[4] = tex2D(sCommonTex0, IN.txcoord.xy + neighbourOffsets.zy); //B
float CoC = abs(colorVals[0].a * 2.0 - 1.0);
float2 bokehRadiusScaled = CoC2BlurRadius(CoC);
float4 vGradTwosided = float4(dot(colorVals[0].rgb - colorVals[1].rgb, 1), //C - L
dot(colorVals[0].rgb - colorVals[2].rgb, 1), //C - T
dot(colorVals[3].rgb - colorVals[0].rgb, 1), //R - C
dot(colorVals[4].rgb - colorVals[0].rgb, 1)); //B - C
float2 vGrad = min(vGradTwosided.xy, vGradTwosided.zw);
float vGradLen = sqrt(dot(vGrad,vGrad)) + 1e-6;
vGrad = vGrad / vGradLen * saturate(vGradLen * 32.0) * bokehRadiusScaled * 0.125 * fADOF_ShapeChromaAmount;
float4 chromaVals[3];
chromaVals[0] = colorVals[0];
chromaVals[1] = tex2D(sCommonTex0, IN.txcoord.xy + vGrad);
chromaVals[2] = tex2D(sCommonTex0, IN.txcoord.xy - vGrad);
chromaVals[1].rgb = lerp(chromaVals[0].rgb, chromaVals[1].rgb, saturate(4.0 * abs(chromaVals[1].w)));
chromaVals[2].rgb = lerp(chromaVals[0].rgb, chromaVals[2].rgb, saturate(4.0 * abs(chromaVals[2].w)));
uint3 chromaMode = (uint3(0,1,2) + iADOF_ShapeChromaMode.xxx) % 3;
color.rgb = float3(chromaVals[chromaMode.x].r,
chromaVals[chromaMode.y].g,
chromaVals[chromaMode.z].b);
color.a = 1.0;
}
#endif
/*=============================================================================
Techniques
=============================================================================*/
technique ADOF
< ui_tooltip = " >> qUINT::ADOF <<\n\n"
"ADOF is a bokeh depth of field shader.\n"
"It blurs the scene in front of and behind the focus plane\n"
"to simulate the behaviour of real lenses. A multitude of features\n"
"allows to simulate various types of bokeh blur that cameras produce.\n"
"\nADOF is written by Marty McFly / Pascal Gilcher"; >
{
/* pass
{
VertexShader = VS_ADOF;
PixelShader = PS_CopyBackBuffer;
RenderTarget = texOriginal;
}*/
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_ReadFocus;
RenderTarget = ADOF_FocusTex;
}
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_CopyFocus;
RenderTarget = ADOF_FocusTexPrev;
}
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_CoC;
RenderTarget = CommonTex0;
}
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_DoF_Main;
RenderTarget = CommonTex1;
}
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_DoF_Combine;
RenderTarget = CommonTex0;
}
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_DoF_Gauss1;
RenderTarget = CommonTex1;
}
#if(ADOF_CHROMATIC_ABERRATION_ENABLE != 0)
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_DoF_Gauss2;
RenderTarget = CommonTex0;
}
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_DoF_ChromaticAberration;
}
#else
pass
{
VertexShader = VS_ADOF;
PixelShader = PS_DoF_Gauss2;
}
#endif
}

View File

@ -0,0 +1,910 @@
/*=============================================================================
ReShade 4 effect file
github.com/martymcmodding
Support me:
paypal.me/mcflypg
patreon.com/mcflypg
Lightroom
by Marty McFly / P.Gilcher
part of qUINT shader library for ReShade 4
Copyright (c) Pascal Gilcher / Marty McFly. All rights reserved.
=============================================================================*/
/*=============================================================================
Preprocessor settings
=============================================================================*/
#ifndef ENABLE_HISTOGRAM
#define ENABLE_HISTOGRAM 0
#endif
#ifndef HISTOGRAM_BINS_NUM
#define HISTOGRAM_BINS_NUM 128
#endif
/*=============================================================================
UI Uniforms
=============================================================================*/
uniform bool LIGHTROOM_ENABLE_LUT <
ui_label = "Enable LUT Overlay";
ui_tooltip = "This displays a neutral LUT onscreen, all color adjustments of this shader and consecutive ones are applied to it.\nTaking a screenshot and using the cropped LUT with the TuningPalette will reproduce all changes of this shader.\nTo make sure that all color changes of your current preset are saved, put Lightroom as early in the\ntechnique chain as possible. Putting grain, sharpening, bloom etc after Lightroom.fx will break the LUT.";
ui_category = "LUT";
> = false;
uniform int LIGHTROOM_LUT_TILE_SIZE <
ui_type = "drag";
ui_min = 8; ui_max = 64;
ui_label = "LUT tile size";
ui_tooltip = "This controls the XY size of tiles of the LUT (which is accuracy in red/green channel).";
ui_category = "LUT";
> = 16;
uniform int LIGHTROOM_LUT_TILE_COUNT <
ui_type = "drag";
ui_min = 8; ui_max = 64;
ui_label = "LUT tile count";
ui_tooltip = "This controls the amount of tiles of the LUT (which is accuracy in blue channel).\nBe aware that Tile Size XY * Tile Amount is the width of the LUT and if this value\nis larger than your resolution width, the LUT won't fit on your screen.";
ui_category = "LUT";
> = 16;
uniform int LIGHTROOM_LUT_SCROLL <
ui_type = "drag";
ui_min = 0; ui_max = 5;
ui_label = "LUT scroll";
ui_tooltip = "If your LUT size exceeds your screen width, set this to 0, take screenshot, set it to 1, take screenshot\netc until you reach the end of your LUT and assemble the screenshots like a panorama.\nIf your LUT fits the screen size however, leave it at 0.";
ui_category = "LUT";
> = 0;
uniform bool LIGHTROOM_ENABLE_CURVE_DISPLAY <
ui_label = "Enable Luma Curve Display";
ui_tooltip = "This enables a small overlay with a luma curve\nso you can monitor changes made by exposure, levels etc.";
ui_category = "Debug";
> = false;
uniform bool LIGHTROOM_ENABLE_CLIPPING_DISPLAY <
ui_label = "Enable Black/White Clipping Mask";
ui_tooltip = "This shows where colors reach #000000 black or #ffffff white, helpful for adjusting levels properly.\nNOTE: Any shader that operates after Lightroom in ReShade technique list can change final color levels afterwards\nso either put Lightroom last in line or take this with a grain of salt.";
ui_category = "Debug";
> = false;
#if(ENABLE_HISTOGRAM == 1)
uniform bool LIGHTROOM_ENABLE_HISTOGRAM <
ui_label = "Enable Histogram";
ui_tooltip = "This enables a small overlay with a histogram for monitoring purposes.\nFor higher performance, open shader and set HISTOGRAM_BINS_NUM to a lower value.";
ui_category = "Histogram";
> = false;
uniform int LIGHTROOM_HISTOGRAM_SAMPLES <
ui_type = "drag";
ui_min = 32; ui_max = 96;
ui_label = "Histogram Samples";
ui_tooltip = "The amount of samples, 20 means 20x20 samples distributed on the screen.\nHigher means a more accurate histogram depicition and less temporal noise.";
ui_category = "Histogram";
> = 20;
uniform float LIGHTROOM_HISTOGRAM_HEIGHT <
ui_type = "drag";
ui_step = 1;
ui_min = 5.0; ui_max = 50.0;
ui_label = "Histogram Curve Height";
ui_tooltip = "Raises the Histogram curve if the values are highly distributed and not visible very well.";
ui_category = "Histogram";
> = 15;
uniform float LIGHTROOM_HISTOGRAM_SMOOTHNESS <
ui_type = "drag";
ui_min = 1.0; ui_max = 10.00;
ui_label = "Histogram Curve Smoothness";
ui_tooltip = "Smoothens the Histogram curve for a more temporally coherent result.\nNote that raising this falsifies the Histogram data.";
ui_category = "Histogram";
> = 5.00;
#endif
//=============================================================================
uniform float LIGHTROOM_RED_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Red Hue Control";
ui_tooltip = "Magenta <= ... Red ... => Orange";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_ORANGE_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Orange Hue Control";
ui_tooltip = "Red <= ... Orange ... => Yellow";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_YELLOW_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Yellow Hue Control";
ui_tooltip = "Orange <= ... Yellow ... => Green";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_GREEN_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Green Hue Control";
ui_tooltip = "Yellow <= ... Green ... => Aqua";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_AQUA_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Aqua Hue Control";
ui_tooltip = "Green <= ... Aqua ... => Blue";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_BLUE_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Blue Hue Control";
ui_tooltip = "Aqua <= ... Blue ... => Magenta";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_MAGENTA_HUESHIFT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Magenta Hue Control";
ui_tooltip = "Blue <= ... Magenta ... => Red";
ui_category = "Palette";
> = 0.00;
//=============================================================================
uniform float LIGHTROOM_RED_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Red Exposure";
ui_tooltip = "Exposure control of Red colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_ORANGE_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Orange Exposure";
ui_tooltip = "Exposure control of Orange colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_YELLOW_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Yellow Exposure";
ui_tooltip = "Exposure control of Yellow colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_GREEN_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Green Exposure";
ui_tooltip = "Exposure control of Green colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_AQUA_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Aqua Exposure";
ui_tooltip = "Exposure control of Aqua colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_BLUE_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Blue Exposure";
ui_tooltip = "Exposure control of Blue colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_MAGENTA_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Magenta Exposure";
ui_tooltip = "Exposure control of Magenta colors";
ui_category = "Palette";
> = 0.00;
//=============================================================================
uniform float LIGHTROOM_RED_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Red Saturation";
ui_tooltip = "Saturation control of Red colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_ORANGE_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Orange Saturation";
ui_tooltip = "Saturation control of Orange colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_YELLOW_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Yellow Saturation";
ui_tooltip = "Saturation control of Yellow colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_GREEN_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Green Saturation";
ui_tooltip = "Saturation control of Green colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_AQUA_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Aqua Saturation";
ui_tooltip = "Saturation control of Aqua colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_BLUE_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Blue Saturation";
ui_tooltip = "Saturation control of Blue colors";
ui_category = "Palette";
> = 0.00;
uniform float LIGHTROOM_MAGENTA_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Magenta Saturation";
ui_tooltip = "Saturation control of Magenta colors";
ui_category = "Palette";
> = 0.00;
//=============================================================================
uniform float LIGHTROOM_GLOBAL_BLACK_LEVEL <
ui_type = "drag";
ui_min = 0; ui_max = 512;
ui_step = 1;
ui_label = "Global Black Level";
ui_tooltip = "Scales input HSL value. Everything darker than this is mapped to black.";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_WHITE_LEVEL <
ui_type = "drag";
ui_min = 0; ui_max = 512;
ui_step = 1;
ui_label = "Global White Level";
ui_tooltip = "Scales input HSL value. ";
ui_category = "Curves";
> = 255.00;
uniform float LIGHTROOM_GLOBAL_EXPOSURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Exposure";
ui_tooltip = "Global Exposure Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_GAMMA <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Gamma";
ui_tooltip = "Global Gamma Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_BLACKS_CURVE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Blacks Curve";
ui_tooltip = "Global Blacks Curve Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_SHADOWS_CURVE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Shadows Curve";
ui_tooltip = "Global Shadows Curve Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_MIDTONES_CURVE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Midtones Curve";
ui_tooltip = "Global Midtones Curve Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_HIGHLIGHTS_CURVE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Highlights Curve";
ui_tooltip = "Global Highlights Curve Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_WHITES_CURVE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Whites Curve";
ui_tooltip = "Global Whites Curve Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_CONTRAST <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Contrast";
ui_tooltip = "Global Contrast Control";
ui_category = "Curves";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_SATURATION <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Saturation";
ui_tooltip = "Global Saturation Control";
ui_category = "Color & Saturation";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_VIBRANCE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global Vibrance";
ui_tooltip = "Global Vibrance Control";
ui_category = "Color & Saturation";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_TEMPERATURE <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global White Balance: Temperature";
ui_tooltip = "Global Temperature Control";
ui_category = "Color & Saturation";
> = 0.00;
uniform float LIGHTROOM_GLOBAL_TINT <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Global White Balance: Tint";
ui_tooltip = "Global Tint Control";
ui_category = "Color & Saturation";
> = 0.00;
//=============================================================================
uniform bool LIGHTROOM_ENABLE_VIGNETTE <
ui_label = "Enable Vignette Effect";
ui_tooltip = "This enables a vignette effect (corner darkening).";
ui_category = "Vignette";
> = false;
uniform bool LIGHTROOM_VIGNETTE_SHOW_RADII <
ui_label = "Show Vignette Inner and Outer radius";
ui_tooltip = "This makes the inner and outer radius setting visible.\nVignette intensity builds up from green (no vignetting) to red (full vignetting).";
ui_category = "Vignette";
> = false;
uniform float2 LIGHTROOM_VIGNETTE_OFFS <
ui_type = "drag";
ui_min = -1.00; ui_max = 1.00;
ui_label = "Vignette Center";
ui_category = "Vignette";
> = float2(0.0, 0.0);
uniform float LIGHTROOM_VIGNETTE_RADIUS_INNER <
ui_type = "drag";
ui_min = 0.00; ui_max = 2.00;
ui_label = "Inner Vignette Radius";
ui_tooltip = "Anything closer to the screen center than this is not affected by vignette.";
ui_category = "Vignette";
> = 0.00;
uniform float LIGHTROOM_VIGNETTE_RADIUS_OUTER <
ui_type = "drag";
ui_min = 0.00; ui_max = 3.00;
ui_label = "Outer Vignette Radius";
ui_tooltip = "Anything farther from the screen center than this gets fully vignette'd.";
ui_category = "Vignette";
> = 1.00;
uniform float LIGHTROOM_VIGNETTE_WIDTH <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Vignette Width";
ui_tooltip = "Higher values stretch the vignette horizontally.";
ui_category = "Vignette";
> = 0.00;
uniform float LIGHTROOM_VIGNETTE_HEIGHT <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Vignette Height";
ui_tooltip = "Higher values stretch the vignette vertically.";
ui_category = "Vignette";
> = 0.00;
uniform float LIGHTROOM_VIGNETTE_AMOUNT <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Vignette Amount";
ui_tooltip = "Intensity of vignette effect.";
ui_category = "Vignette";
> = 1.00;
uniform float LIGHTROOM_VIGNETTE_CURVE <
ui_type = "drag";
ui_min = 0.00; ui_max = 10.00;
ui_label = "Vignette Curve";
ui_tooltip = "Curve of gradient between inner and outer radius. 1.0 means linear.";
ui_category = "Vignette";
> = 1.00;
uniform float3 LIGHTROOM_VIGNETTE_COLOR <
ui_type = "color";
ui_label="Vignette Color";
ui_category = "Vignette";
> = float3(0.0, 0.0, 0.0);
uniform int LIGHTROOM_VIGNETTE_BLEND_MODE <
ui_type = "combo";
ui_items = "Multiply\0Subtract\0Screen\0LumaPreserving\0Alpha Blend\0";
ui_tooltip = "Select between different ways of applying vignette";
ui_label = "Vignette Blend Mode";
ui_category = "Vignette";
> = 1;
/*=============================================================================
Textures, Samplers, Globals
=============================================================================*/
#define RESHADE_QUINT_COMMON_VERSION_REQUIRE 200
#include "qUINT_common.fxh"
#if(ENABLE_HISTOGRAM == 1)
texture2D HistogramTex { Width = HISTOGRAM_BINS_NUM; Height = 1; Format = RGBA16F; };
sampler2D sHistogramTex { Texture = HistogramTex; };
#endif
texture2D LutTexInternal { Width = 4096; Height = 64; Format = RGBA8; };
sampler2D sLutTexInternal { Texture = LutTexInternal; };
/*=============================================================================
Vertex Shader
=============================================================================*/
void VS_Lightroom(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 uv : TEXCOORD0, out nointerpolation float huefactors[7] : TEXCOORD1)
{
uv.x = (id == 2) ? 2.0 : 0.0;
uv.y = (id == 1) ? 2.0 : 0.0;
position = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
static const float originalHue[8] = {0.0,0.0833333333333,0.1666666666666,0.3333333333333,0.5,0.6666666666666,0.8333333333333,1.0};
huefactors[0] = (LIGHTROOM_RED_HUESHIFT > 0) ? lerp(originalHue[0], originalHue[1], LIGHTROOM_RED_HUESHIFT) : lerp(originalHue[7], originalHue[6], -LIGHTROOM_RED_HUESHIFT);
huefactors[1] = (LIGHTROOM_ORANGE_HUESHIFT > 0) ? lerp(originalHue[1], originalHue[2], LIGHTROOM_ORANGE_HUESHIFT) : lerp(originalHue[1], originalHue[0], -LIGHTROOM_ORANGE_HUESHIFT);
huefactors[2] = (LIGHTROOM_YELLOW_HUESHIFT > 0) ? lerp(originalHue[2], originalHue[3], LIGHTROOM_YELLOW_HUESHIFT) : lerp(originalHue[2], originalHue[1], -LIGHTROOM_YELLOW_HUESHIFT);
huefactors[3] = (LIGHTROOM_GREEN_HUESHIFT > 0) ? lerp(originalHue[3], originalHue[4], LIGHTROOM_GREEN_HUESHIFT) : lerp(originalHue[3], originalHue[2], -LIGHTROOM_GREEN_HUESHIFT);
huefactors[4] = (LIGHTROOM_AQUA_HUESHIFT > 0) ? lerp(originalHue[4], originalHue[5], LIGHTROOM_AQUA_HUESHIFT) : lerp(originalHue[4], originalHue[3], -LIGHTROOM_AQUA_HUESHIFT);
huefactors[5] = (LIGHTROOM_BLUE_HUESHIFT > 0) ? lerp(originalHue[5], originalHue[6], LIGHTROOM_BLUE_HUESHIFT) : lerp(originalHue[5], originalHue[4], -LIGHTROOM_BLUE_HUESHIFT);
huefactors[6] = (LIGHTROOM_MAGENTA_HUESHIFT > 0) ? lerp(originalHue[6], originalHue[7], LIGHTROOM_MAGENTA_HUESHIFT) : lerp(originalHue[6], originalHue[5], -LIGHTROOM_MAGENTA_HUESHIFT);
}
/*=============================================================================
Functions
=============================================================================*/
struct CurvesStruct
{
float2 levels;
float exposure;
float gamma;
float contrast;
float blacks;
float shadows;
float midtones;
float highlights;
float whites;
};
struct PaletteStruct
{
float hue[7];
float saturation[7];
float exposure[7];
};
struct VignetteStruct
{
float2 ratio;
float2 radii;
float amount;
float curve;
int blend;
bool debug;
};
CurvesStruct setup_curves()
{
CurvesStruct Curves;
Curves.levels = float2(LIGHTROOM_GLOBAL_BLACK_LEVEL, LIGHTROOM_GLOBAL_WHITE_LEVEL) * rcp(255.0);
Curves.exposure = exp2(LIGHTROOM_GLOBAL_EXPOSURE);
Curves.gamma = exp2(-LIGHTROOM_GLOBAL_GAMMA);
Curves.contrast = LIGHTROOM_GLOBAL_CONTRAST;
Curves.blacks = exp2(-LIGHTROOM_GLOBAL_BLACKS_CURVE);
Curves.shadows = exp2(-LIGHTROOM_GLOBAL_SHADOWS_CURVE);
Curves.midtones = exp2(-LIGHTROOM_GLOBAL_MIDTONES_CURVE);
Curves.highlights = exp2(-LIGHTROOM_GLOBAL_HIGHLIGHTS_CURVE);
Curves.whites = exp2(-LIGHTROOM_GLOBAL_WHITES_CURVE);
return Curves;
}
PaletteStruct setup_palette()
{
PaletteStruct Palette;
Palette.hue[0] = LIGHTROOM_RED_HUESHIFT;
Palette.hue[1] = LIGHTROOM_ORANGE_HUESHIFT;
Palette.hue[2] = LIGHTROOM_YELLOW_HUESHIFT;
Palette.hue[3] = LIGHTROOM_GREEN_HUESHIFT;
Palette.hue[4] = LIGHTROOM_AQUA_HUESHIFT;
Palette.hue[5] = LIGHTROOM_BLUE_HUESHIFT;
Palette.hue[6] = LIGHTROOM_MAGENTA_HUESHIFT;
Palette.saturation[0] = LIGHTROOM_RED_SATURATION;
Palette.saturation[1] = LIGHTROOM_ORANGE_SATURATION;
Palette.saturation[2] = LIGHTROOM_YELLOW_SATURATION;
Palette.saturation[3] = LIGHTROOM_GREEN_SATURATION;
Palette.saturation[4] = LIGHTROOM_AQUA_SATURATION;
Palette.saturation[5] = LIGHTROOM_BLUE_SATURATION;
Palette.saturation[6] = LIGHTROOM_MAGENTA_SATURATION;
Palette.exposure[0] = LIGHTROOM_RED_EXPOSURE;
Palette.exposure[1] = LIGHTROOM_ORANGE_EXPOSURE;
Palette.exposure[2] = LIGHTROOM_YELLOW_EXPOSURE;
Palette.exposure[3] = LIGHTROOM_GREEN_EXPOSURE;
Palette.exposure[4] = LIGHTROOM_AQUA_EXPOSURE;
Palette.exposure[5] = LIGHTROOM_BLUE_EXPOSURE;
Palette.exposure[6] = LIGHTROOM_MAGENTA_EXPOSURE;
return Palette;
}
VignetteStruct setup_vignette()
{
VignetteStruct Vignette;
Vignette.ratio = float2(LIGHTROOM_VIGNETTE_WIDTH,LIGHTROOM_VIGNETTE_HEIGHT);
Vignette.radii = float2(LIGHTROOM_VIGNETTE_RADIUS_INNER, LIGHTROOM_VIGNETTE_RADIUS_OUTER);
Vignette.amount = LIGHTROOM_VIGNETTE_AMOUNT;
Vignette.curve = LIGHTROOM_VIGNETTE_CURVE;
Vignette.blend = LIGHTROOM_VIGNETTE_BLEND_MODE;
Vignette.debug = LIGHTROOM_VIGNETTE_SHOW_RADII;
return Vignette;
}
float3 rgb_to_hcv(in float3 RGB)
{
RGB = saturate(RGB);
float Epsilon = 1e-10;
// Based on work by Sam Hocevar and Emil Persson
float4 P = (RGB.g < RGB.b) ? float4(RGB.bg, -1.0, 2.0/3.0) : float4(RGB.gb, 0.0, -1.0/3.0);
float4 Q = (RGB.r < P.x) ? float4(P.xyw, RGB.r) : float4(RGB.r, P.yzx);
float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
return float3(H, C, Q.x);
}
float3 rgb_to_hsl(in float3 RGB)
{
float3 HCV = rgb_to_hcv(RGB);
float L = HCV.z - HCV.y * 0.5;
float S = HCV.y / (1.0000001 - abs(L * 2 - 1));
return float3(HCV.x, S, L);
}
float3 hsl_to_rgb(in float3 HSL)
{
HSL = saturate(HSL);
float3 RGB = saturate(float3(abs(HSL.x * 6.0 - 3.0) - 1.0,2.0 - abs(HSL.x * 6.0 - 2.0),2.0 - abs(HSL.x * 6.0 - 4.0)));
float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
return (RGB - 0.5) * C + HSL.z;
}
float linearstep(float lower, float upper, float value)
{
return saturate((value-lower)/(upper-lower));
}
float3 get_function_graph(float2 coords, float F, float3 origcolor, float thickness)
{
F -= coords.y;
float DistanceField = abs(F) / length(float2(ddx(F) / ddx(coords.x), -1.0));
return lerp(origcolor, 1 - origcolor, smoothstep(qUINT::PIXEL_SIZE.y*thickness, 0.0, DistanceField));
}
float3 get_vignette(float3 color, float2 uv, VignetteStruct v)
{
float2 vign_uv = uv * 2 - 1;
vign_uv += LIGHTROOM_VIGNETTE_OFFS;
vign_uv -= vign_uv * v.ratio;
float vign_gradient = length(vign_uv);
float vignette = linearstep(v.radii.x, v.radii.y, vign_gradient);
vignette = pow(vignette, v.curve + 1e-6) * v.amount;
vignette = saturate(vignette);
color = (v.blend == 0) ? lerp(color, color * LIGHTROOM_VIGNETTE_COLOR, vignette) : color;
color = (v.blend == 1) ? saturate(color - vignette.xxx) : color;
color = (v.blend == 2) ? 1 - (1 - color) * (vignette + 1) : color;
color = (v.blend == 3) ? color * saturate(lerp(1 - vignette * 2 , 1, dot(color, 0.333))) : color;
color = (v.blend == 4) ? lerp(color, LIGHTROOM_VIGNETTE_COLOR, vignette) : color;
//can't use the graph function here, as it's not a y=f(x) function (at least not a real one)
if(v.debug)
{
float2 radii_sdf = abs(vign_gradient - v.radii);
radii_sdf *= qUINT::PIXEL_SIZE.yy / fwidth(radii_sdf);
radii_sdf = saturate(1 - 200 * radii_sdf);
color = lerp(color, float3(0.0,1.0,0.0), radii_sdf.x);
color = lerp(color, float3(1.0,0.0,0.0), radii_sdf.y);
}
return color;
}
float curves(in float x, in CurvesStruct c)
{
x = linearstep(c.levels.x, c.levels.y, x);
x = saturate(pow(x * c.exposure, c.gamma));
float blacks_mult = smoothstep(0.25, 0.00, x);
float shadows_mult = smoothstep(0.00, 0.25, x) * smoothstep(0.50, 0.25, x);
float midtones_mult = smoothstep(0.25, 0.50, x) * smoothstep(0.75, 0.50, x);
float highlights_mult = smoothstep(0.50, 0.75, x) * smoothstep(1.00, 0.75, x);
float whites_mult = smoothstep(0.75, 1.00, x);
x = pow(x, exp2(blacks_mult * c.blacks
+ shadows_mult * c.shadows
+ midtones_mult * c.midtones
+ highlights_mult * c.highlights
+ whites_mult * c.whites
- 1));
x = lerp(x, x * x * (3 - 2 * x), c.contrast);
return saturate(x);
}
void draw_lut(inout float3 color, in float2 vpos, in float tile_size, in float tile_amount, in float scroll)
{
float2 pixelcoord = vpos.xy; // - 0.5;
pixelcoord.x += scroll * BUFFER_WIDTH;
if(pixelcoord.x < tile_size * tile_amount && pixelcoord.y < tile_size)
{
color.rg = frac(pixelcoord.xy / tile_size) - 0.5 / tile_size;
color.rg /= 1.0 - rcp(tile_size);
color.b = floor(pixelcoord.x / tile_size)/(tile_amount - 1);
color.rgb = floor(color.rgb * 255.0) / 255.0;
}
}
void draw_lut_4096x64(inout float3 color, in float2 vpos)
{
color.rgb = vpos.xyx / 64.0;
color.rg = frac(color.rg) - 0.5 / 64.0;
color.rg /= 1.0 - 1.0 / 64.0;
color.b = floor(color.b) / (64.0 - 1);
}
void read_lut_4096x64(inout float3 color)
{
float4 lut_coord;
lut_coord.xyz = color.rgb * 63.0;
lut_coord.xy = (lut_coord.xy + 0.5) / float2(4096.0, 64.0);
lut_coord.x += floor(lut_coord.z) / 64.0;
lut_coord.z = frac(lut_coord.z);
lut_coord.w = lut_coord.x + 0.015625;
color.rgb = lerp(tex2D(sLutTexInternal, lut_coord.xy).rgb, tex2D(sLutTexInternal, lut_coord.wy).rgb, lut_coord.z);
}
float3 palette(in float3 hsl_color, in PaletteStruct p, in float huefactors[7])
{
float huemults[7] =
{
max(saturate(1.0 - abs((hsl_color.x - 0.0/12) * 12.0)), //red left side - need this due to 360 degrees -> 0 degrees
saturate(1.0 - abs((hsl_color.x - 12.0/12) * 6.0))), //red right side
saturate(1.0 - abs((hsl_color.x - 1.0/12) * 12.0)), //orange both sides
max(saturate(1.0 - abs((hsl_color.x - 2.0/12) * 12.0)) * step(hsl_color.x,2.0/12.0), //yellow left side - need this because hues are not evenly distributed around color wheel, it's 1/12 from orange to yellow but 1/6 from yellow to green
saturate(1.0 - abs((hsl_color.x - 2.0/12) * 6.0)) * step(2.0/12.0,hsl_color.x)), //yellow right side
saturate(1.0 - abs((hsl_color.x - 4.0/12) * 6.0)), //green both sides
saturate(1.0 - abs((hsl_color.x - 6.0/12) * 6.0)), //aqua both sides
saturate(1.0 - abs((hsl_color.x - 8.0/12) * 6.0)), //blue both sides
saturate(1.0 - abs((hsl_color.x - 10.0/12) * 6.0)) //magenta both sides
};
float3 tcolor = 0;
for(int i=0; i < 7; i++)
tcolor += huemults[i] * hsl_to_rgb(float3(huefactors[i], saturate(hsl_color.y + hsl_color.y * p.saturation[i]), hsl_color.z * exp2(sqrt(hsl_color.y) * p.exposure[i] * (1 - hsl_color.z) * hsl_color.y)));
return tcolor;
}
/*=============================================================================
Pixel Shaders
=============================================================================*/
#if(ENABLE_HISTOGRAM == 1)
void PS_HistogramGenerate(float4 vpos : SV_Position, float2 uv : TEXCOORD, out float4 res : SV_Target0)
{
res = 0;float4 coord = 0;
coord.z = rcp(LIGHTROOM_HISTOGRAM_SAMPLES);
float2 histogram_data = float2(HISTOGRAM_BINS_NUM, vpos.x) / LIGHTROOM_HISTOGRAM_SMOOTHNESS;
[loop]
for(int x = 0; x < LIGHTROOM_HISTOGRAM_SAMPLES; x++)
{
coord.y = 0;
[loop]
for(int y = 0; y < LIGHTROOM_HISTOGRAM_SAMPLES; y++)
{
res.xyz += saturate(1.0 - abs(tex2Dlod(qUINT::sBackBufferTex,coord).xyz * histogram_data.xxx - histogram_data.yyy));
coord.y += coord.z;
}
coord.x += coord.z;
}
res.xyz /= LIGHTROOM_HISTOGRAM_SMOOTHNESS;
}
#endif
void PS_ProcessLUT(float4 vpos : SV_Position, float2 uv : TEXCOORD0, nointerpolation float huefactors[7] : TEXCOORD1, out float4 color : SV_Target0)
{
//ReShade bug :( can't initialize structs the old fashioned/C way
const CurvesStruct Curves = setup_curves();
const PaletteStruct Palette = setup_palette();
draw_lut_4096x64(color.rgb, vpos.xy);
color.a = 1;
color.r = curves(color.r, Curves);
color.g = curves(color.g, Curves);
color.b = curves(color.b, Curves);
float3 hsl_color = rgb_to_hsl(color.rgb);
color.rgb = LIGHTROOM_GLOBAL_TEMPERATURE > 0 ? lerp(color.rgb, hsl_to_rgb(float3(0.06111, 1.0, hsl_color.z)), LIGHTROOM_GLOBAL_TEMPERATURE) : lerp(color.rgb, hsl_to_rgb(float3(0.56111, 1.0, hsl_color.z)), -LIGHTROOM_GLOBAL_TEMPERATURE);
color.rgb = LIGHTROOM_GLOBAL_TEMPERATURE > 0 ? lerp(color.rgb, hsl_to_rgb(float3(0.31111, 1.0, hsl_color.z)), LIGHTROOM_GLOBAL_TINT) : lerp(color.rgb, hsl_to_rgb(float3(0.81111, 1.0, hsl_color.z)), -LIGHTROOM_GLOBAL_TINT);
hsl_color = rgb_to_hsl(color.rgb);
hsl_color.y = saturate(hsl_color.y + hsl_color.y * LIGHTROOM_GLOBAL_SATURATION);
hsl_color.y = pow(hsl_color.y,exp2(-LIGHTROOM_GLOBAL_VIBRANCE));
hsl_color = saturate(hsl_color);
color.rgb = palette(hsl_color, Palette, huefactors);
}
float3 dither(in int2 pos, int bit_depth)
{
const float2 magicdot = float2(0.75487766624669276, 0.569840290998);
const float3 magicadd = float3(0, 0.025, 0.0125) * dot(magicdot, 1);
const float lsb = exp2(bit_depth) - 1;
float3 dither = frac(dot(pos, magicdot) + magicadd);
dither = dither - 0.5;
dither *= 0.99; //so if added to source color, it just does not spill over to next bucket
dither /= lsb;
return dither;
}
void PS_ApplyLUT(float4 vpos : SV_Position, float2 uv : TEXCOORD0, nointerpolation float huefactors[7] : TEXCOORD1, out float4 color : SV_Target0)
{
color = tex2D(qUINT::sBackBufferTex, uv);
if(LIGHTROOM_ENABLE_LUT)
draw_lut(color.rgb, vpos.xy, LIGHTROOM_LUT_TILE_SIZE, LIGHTROOM_LUT_TILE_COUNT, LIGHTROOM_LUT_SCROLL);
read_lut_4096x64(color.rgb);
}
void PS_DisplayStatistics(float4 vpos : SV_Position, float2 uv : TEXCOORD0, nointerpolation float huefactors[7] : TEXCOORD1, out float4 res : SV_Target0)
{
const CurvesStruct Curves = setup_curves();
const VignetteStruct Vignette = setup_vignette();
float4 color = tex2D(qUINT::sBackBufferTex,uv);
if(LIGHTROOM_ENABLE_VIGNETTE) color.rgb = get_vignette(color.rgb, uv, Vignette);
float2 vposfbl = float2(vpos.x, BUFFER_HEIGHT-vpos.y);
float2 vposfbl_n = vposfbl / 255.0;
color.rgb = (LIGHTROOM_ENABLE_CLIPPING_DISPLAY && dot(color.rgb, 1.0) >= 3.0) ? float3(1.0,0.0,0.0) : color.rgb;
color.rgb = (LIGHTROOM_ENABLE_CLIPPING_DISPLAY && dot(color.rgb, 1.0) <= 0.0) ? float3(0.0,0.0,1.0) : color.rgb;
#if(ENABLE_HISTOGRAM == 1)
if(LIGHTROOM_ENABLE_HISTOGRAM || LIGHTROOM_ENABLE_CURVE_DISPLAY)
{
float luma_curve = curves(vposfbl_n.x, Curves);
float3 histogram = tex2Dlod(sHistogramTex, vposfbl_n.xyxy).xyz / (LIGHTROOM_HISTOGRAM_SAMPLES * LIGHTROOM_HISTOGRAM_SAMPLES) * LIGHTROOM_HISTOGRAM_HEIGHT;
if(all(saturate(-vposfbl_n * vposfbl_n + vposfbl_n)))
{
color.rgb = LIGHTROOM_ENABLE_HISTOGRAM ? vposfbl_n.yyy < histogram.xyz : color.rgb;
color.rgb = LIGHTROOM_ENABLE_CURVE_DISPLAY ? get_function_graph(vposfbl_n.xy, luma_curve, color.rgb, 20.0) : color.rgb;
}
}
#else
if(LIGHTROOM_ENABLE_CURVE_DISPLAY)
{
float luma_curve = curves(vposfbl_n.x, Curves);
if(all(saturate(-vposfbl_n * vposfbl_n + vposfbl_n)))
color.rgb = LIGHTROOM_ENABLE_CURVE_DISPLAY ? get_function_graph(vposfbl_n.xy, luma_curve, color.rgb, 20.0) : color.rgb;
}
#endif
res.xyz = color.xyz;
res.w = 1.0;
}
/*=============================================================================
Techniques
=============================================================================*/
technique Lightroom
< ui_tooltip = " >> qUINT::Lightroom <<\n\n"
"Lightroom is a color grading toolbox that offers a multitude\n"
"of features commonly found in color grading software.\n"
"You can do deep color modifications, adjust contrast and levels,\n"
"tweak color balance, view a histogram and bake the CC into a 3D LUT.\n"
"\nLightroom is written by Marty McFly / Pascal Gilcher"; >
{
pass PProcessLUT
{
VertexShader = VS_Lightroom;
PixelShader = PS_ProcessLUT;
RenderTarget = LutTexInternal;
}
pass PApplyLUT
{
VertexShader = VS_Lightroom;
PixelShader = PS_ApplyLUT;
}
#if(ENABLE_HISTOGRAM == 1)
pass PHistogramGenerate
{
VertexShader = PostProcessVS;
PixelShader = PS_HistogramGenerate;
RenderTarget = HistogramTex;
}
#endif
pass PHistogram
{
VertexShader = VS_Lightroom;
PixelShader = PS_DisplayStatistics;
}
}

View File

@ -0,0 +1,706 @@
/*=============================================================================
ReShade 4 effect file
github.com/martymcmodding
Support me:
paypal.me/mcflypg
patreon.com/mcflypg
Ambient Obscurance with Indirect Lighting "MXAO"
by Marty McFly / P.Gilcher
part of qUINT shader library for ReShade 4
Copyright (c) Pascal Gilcher / Marty McFly. All rights reserved.
=============================================================================*/
/*=============================================================================
Preprocessor settings
=============================================================================*/
#ifndef MXAO_MIPLEVEL_AO
#define MXAO_MIPLEVEL_AO 0 //[0 to 2] Miplevel of AO texture. 0 = fullscreen, 1 = 1/2 screen width/height, 2 = 1/4 screen width/height and so forth. Best results: IL MipLevel = AO MipLevel + 2
#endif
#ifndef MXAO_MIPLEVEL_IL
#define MXAO_MIPLEVEL_IL 2 //[0 to 4] Miplevel of IL texture. 0 = fullscreen, 1 = 1/2 screen width/height, 2 = 1/4 screen width/height and so forth.
#endif
#ifndef MXAO_ENABLE_IL
#define MXAO_ENABLE_IL 0 //[0 or 1] Enables Indirect Lighting calculation. Will cause a major fps hit.
#endif
#ifndef MXAO_SMOOTHNORMALS
#define MXAO_SMOOTHNORMALS 0 //[0 or 1] This feature makes low poly surfaces smoother, especially useful on older games.
#endif
#ifndef MXAO_TWO_LAYER
#define MXAO_TWO_LAYER 0 //[0 or 1] Splits MXAO into two separate layers that allow for both large and fine AO.
#endif
#ifndef MXAO_HIGH_QUALITY
#define MXAO_HIGH_QUALITY 0 //[0 or 1] Enables a different, more physically accurate but slower SSAO mode. Based on Ground Truth Ambient Occlusion by Activision. No IL yet.
#endif
/*=============================================================================
UI Uniforms
=============================================================================*/
uniform int MXAO_GLOBAL_SAMPLE_QUALITY_PRESET <
ui_type = "combo";
ui_label = "Sample Quality";
ui_items = "Very Low (4 samples)\0Low (8 samples)\0Medium (16 samples)\0High (24 samples)\0Very High (32 samples)\0Ultra (64 samples)\0Maximum (255 samples)\0Auto (variable)\0";
ui_tooltip = "Global quality control, main performance knob. Higher radii might require higher quality.";
ui_category = "Global";
> = 2;
uniform float MXAO_SAMPLE_RADIUS <
ui_type = "drag";
ui_min = 0.5; ui_max = 20.0;
ui_label = "Sample Radius";
ui_tooltip = "Sample radius of MXAO, higher means more large-scale occlusion with less fine-scale details.";
ui_category = "Global";
> = 2.5;
#if (MXAO_HIGH_QUALITY==0)
uniform float MXAO_SAMPLE_NORMAL_BIAS <
ui_type = "drag";
ui_min = 0.0; ui_max = 0.8;
ui_label = "Normal Bias";
ui_tooltip = "Occlusion Cone bias to reduce self-occlusion of surfaces that have a low angle to each other.";
ui_category = "Global";
> = 0.2;
#else
#define MXAO_SAMPLE_NORMAL_BIAS 0 //don't break PS which needs this, cleaner this way
#endif
uniform float MXAO_GLOBAL_RENDER_SCALE <
ui_type = "drag";
ui_label = "Render Size Scale";
ui_min = 0.50; ui_max = 1.00;
ui_tooltip = "Factor of MXAO resolution, lower values greatly reduce performance overhead but decrease quality.\n1.0 = MXAO is computed in original resolution\n0.5 = MXAO is computed in 1/2 width 1/2 height of original resolution\n...";
ui_category = "Global";
> = 1.0;
uniform float MXAO_SSAO_AMOUNT <
ui_type = "drag";
ui_min = 0.00; ui_max = 4.00;
ui_label = "Ambient Occlusion Amount";
ui_tooltip = "Intensity of AO effect. Can cause pitch black clipping if set too high.";
ui_category = "Ambient Occlusion";
> = 1.00;
#if(MXAO_ENABLE_IL != 0)
uniform float MXAO_SSIL_AMOUNT <
ui_type = "drag";
ui_min = 0.00; ui_max = 12.00;
ui_label = "Indirect Lighting Amount";
ui_tooltip = "Intensity of IL effect. Can cause overexposured white spots if set too high.";
ui_category = "Indirect Lighting";
> = 4.00;
uniform float MXAO_SSIL_SATURATION <
ui_type = "drag";
ui_min = 0.00; ui_max = 3.00;
ui_label = "Indirect Lighting Saturation";
ui_tooltip = "Controls color saturation of IL effect.";
ui_category = "Indirect Lighting";
> = 1.00;
#endif
#if (MXAO_TWO_LAYER != 0)
uniform float MXAO_SAMPLE_RADIUS_SECONDARY <
ui_type = "drag";
ui_min = 0.1; ui_max = 1.00;
ui_label = "Fine AO Scale";
ui_tooltip = "Multiplier of Sample Radius for fine geometry. A setting of 0.5 scans the geometry at half the radius of the main AO.";
ui_category = "Double Layer";
> = 0.2;
uniform float MXAO_AMOUNT_FINE <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Fine AO intensity multiplier";
ui_tooltip = "Intensity of small scale AO / IL.";
ui_category = "Double Layer";
> = 1.0;
uniform float MXAO_AMOUNT_COARSE <
ui_type = "drag";
ui_min = 0.00; ui_max = 1.00;
ui_label = "Coarse AO intensity multiplier";
ui_tooltip = "Intensity of large scale AO / IL.";
ui_category = "Double Layer";
> = 1.0;
#endif
uniform int MXAO_BLEND_TYPE <
ui_type = "slider";
ui_min = 0; ui_max = 3;
ui_label = "Blending Mode";
ui_tooltip = "Different blending modes for merging AO/IL with original color.\0Blending mode 0 matches formula of MXAO 2.0 and older.";
ui_category = "Blending";
> = 0;
uniform float MXAO_FADE_DEPTH_START <
ui_type = "drag";
ui_label = "Fade Out Start";
ui_min = 0.00; ui_max = 1.00;
ui_tooltip = "Distance where MXAO starts to fade out. 0.0 = camera, 1.0 = sky. Must be less than Fade Out End.";
ui_category = "Blending";
> = 0.05;
uniform float MXAO_FADE_DEPTH_END <
ui_type = "drag";
ui_label = "Fade Out End";
ui_min = 0.00; ui_max = 1.00;
ui_tooltip = "Distance where MXAO completely fades out. 0.0 = camera, 1.0 = sky. Must be greater than Fade Out Start.";
ui_category = "Blending";
> = 0.4;
uniform int MXAO_DEBUG_VIEW_ENABLE <
ui_type = "combo";
ui_label = "Enable Debug View";
ui_items = "None\0AO/IL channel\0Normal vectors\0";
ui_tooltip = "Different debug outputs";
ui_category = "Debug";
> = 0;
/*=============================================================================
Textures, Samplers, Globals
=============================================================================*/
#define RESHADE_QUINT_COMMON_VERSION_REQUIRE 202
#define RESHADE_QUINT_EFFECT_DEPTH_REQUIRE //effect requires depth access
#include "qUINT_common.fxh"
texture2D MXAO_ColorTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; MipLevels = 3+MXAO_MIPLEVEL_IL;};
texture2D MXAO_DepthTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R16F; MipLevels = 3+MXAO_MIPLEVEL_AO;};
texture2D MXAO_NormalTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; MipLevels = 3+MXAO_MIPLEVEL_IL;};
sampler2D sMXAO_ColorTex { Texture = MXAO_ColorTex; };
sampler2D sMXAO_DepthTex { Texture = MXAO_DepthTex; };
sampler2D sMXAO_NormalTex { Texture = MXAO_NormalTex; };
texture2D CommonTex0 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler2D sCommonTex0 { Texture = CommonTex0; };
texture2D CommonTex1 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler2D sCommonTex1 { Texture = CommonTex1; };
#if(MXAO_ENABLE_IL != 0)
#define BLUR_COMP_SWIZZLE xyzw
#else
#define BLUR_COMP_SWIZZLE w
#endif
/*=============================================================================
Vertex Shader
=============================================================================*/
struct MXAO_VSOUT
{
float4 vpos : SV_Position;
float4 uv : TEXCOORD0;
nointerpolation float samples : TEXCOORD1;
nointerpolation float3 uvtoviewADD : TEXCOORD4;
nointerpolation float3 uvtoviewMUL : TEXCOORD5;
};
struct BlurData
{
float4 key;
float4 mask;
};
MXAO_VSOUT VS_MXAO(in uint id : SV_VertexID)
{
MXAO_VSOUT MXAO;
MXAO.uv.x = (id == 2) ? 2.0 : 0.0;
MXAO.uv.y = (id == 1) ? 2.0 : 0.0;
MXAO.uv.zw = MXAO.uv.xy / MXAO_GLOBAL_RENDER_SCALE;
MXAO.vpos = float4(MXAO.uv.xy * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
static const int samples_per_preset[8] = {4, 8, 16, 24, 32, 64, 255, 8 /*overridden*/};
MXAO.samples = samples_per_preset[MXAO_GLOBAL_SAMPLE_QUALITY_PRESET];
MXAO.uvtoviewADD = float3(-1.0,-1.0,1.0);
MXAO.uvtoviewMUL = float3(2.0,2.0,0.0);
#if 0
static const float FOV = 75; //vertical FoV
MXAO.uvtoviewADD = float3(-tan(radians(FOV * 0.5)).xx,1.0) * qUINT::ASPECT_RATIO.yxx;
MXAO.uvtoviewMUL = float3(-2.0 * MXAO.uvtoviewADD.xy,0.0);
#endif
return MXAO;
}
/*=============================================================================
Functions
=============================================================================*/
float3 get_position_from_uv(in float2 uv, in MXAO_VSOUT MXAO)
{
return (uv.xyx * MXAO.uvtoviewMUL + MXAO.uvtoviewADD) * qUINT::linear_depth(uv) * RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
}
float3 get_position_from_uv_mipmapped(in float2 uv, in MXAO_VSOUT MXAO, in int miplevel)
{
return (uv.xyx * MXAO.uvtoviewMUL + MXAO.uvtoviewADD) * tex2Dlod(sMXAO_DepthTex, float4(uv.xyx, miplevel)).x;
}
void spatial_blur_data(inout BlurData o, in sampler inputsampler, in float inputscale, in float4 uv)
{
o.key = tex2Dlod(inputsampler, uv * inputscale);
o.mask = tex2Dlod(sMXAO_NormalTex, uv);
o.mask.xyz = o.mask.xyz * 2 - 1;
}
float compute_spatial_tap_weight(in BlurData center, in BlurData tap)
{
float depth_term = saturate(1 - abs(tap.mask.w - center.mask.w));
float normal_term = saturate(dot(tap.mask.xyz, center.mask.xyz) * 16 - 15);
return depth_term * normal_term;
}
float4 blur_filter(in MXAO_VSOUT MXAO, in sampler inputsampler, in float inputscale, in float radius, in int blursteps)
{
float4 blur_uv = float4(MXAO.uv.xy, 0, 0);
BlurData center, tap;
spatial_blur_data(center, inputsampler, inputscale, blur_uv);
float4 blursum = center.key;
float4 blursum_noweight = center.key;
float blurweight = 1;
static const float2 offsets[8] =
{
float2(1.5,0.5),float2(-1.5,-0.5),float2(-0.5,1.5),float2(0.5,-1.5),
float2(1.5,2.5),float2(-1.5,-2.5),float2(-2.5,1.5),float2(2.5,-1.5)
};
float2 blur_offsetscale = qUINT::PIXEL_SIZE / inputscale * radius;
[unroll]
for(int i = 0; i < blursteps; i++)
{
blur_uv.xy = MXAO.uv.xy + offsets[i] * blur_offsetscale;
spatial_blur_data(tap, inputsampler, inputscale, blur_uv);
float tap_weight = compute_spatial_tap_weight(center, tap);
blurweight += tap_weight;
blursum.BLUR_COMP_SWIZZLE += tap.key.BLUR_COMP_SWIZZLE * tap_weight;
blursum_noweight.BLUR_COMP_SWIZZLE += tap.key.BLUR_COMP_SWIZZLE;
}
blursum.BLUR_COMP_SWIZZLE /= blurweight;
blursum_noweight.BLUR_COMP_SWIZZLE /= 1 + blursteps;
return lerp(blursum.BLUR_COMP_SWIZZLE, blursum_noweight.BLUR_COMP_SWIZZLE, blurweight < 2);
}
void sample_parameter_setup(in MXAO_VSOUT MXAO, in float scaled_depth, in float layer_id, out float scaled_radius, out float falloff_factor)
{
scaled_radius = 0.25 * MXAO_SAMPLE_RADIUS / (MXAO.samples * (scaled_depth + 2.0));
falloff_factor = -1.0/(MXAO_SAMPLE_RADIUS * MXAO_SAMPLE_RADIUS);
#if(MXAO_TWO_LAYER != 0)
scaled_radius *= lerp(1.0, MXAO_SAMPLE_RADIUS_SECONDARY + 1e-6, layer_id);
falloff_factor *= lerp(1.0, 1.0 / (MXAO_SAMPLE_RADIUS_SECONDARY * MXAO_SAMPLE_RADIUS_SECONDARY + 1e-6), layer_id);
#endif
}
void smooth_normals(inout float3 normal, in float3 position, in MXAO_VSOUT MXAO)
{
float2 scaled_radius = 0.018 / position.z * qUINT::ASPECT_RATIO;
float3 neighbour_normal[4] = {normal, normal, normal, normal};
[unroll]
for(int i = 0; i < 4; i++)
{
float2 direction;
sincos(6.28318548 * 0.25 * i, direction.y, direction.x);
[unroll]
for(int direction_step = 1; direction_step <= 5; direction_step++)
{
float search_radius = exp2(direction_step);
float2 tap_uv = MXAO.uv.zw + direction * search_radius * scaled_radius;
float3 temp_normal = tex2Dlod(sMXAO_NormalTex, float4(tap_uv, 0, 0)).xyz * 2.0 - 1.0;
float3 temp_position = get_position_from_uv_mipmapped(tap_uv, MXAO, 0);
float3 position_delta = temp_position - position;
float distance_weight = saturate(1.0 - dot(position_delta, position_delta) * 20.0 / search_radius);
float normal_angle = dot(normal, temp_normal);
float angle_weight = smoothstep(0.3, 0.98, normal_angle) * smoothstep(1.0, 0.98, normal_angle); //only take normals into account that are NOT equal to the current normal.
float total_weight = saturate(3.0 * distance_weight * angle_weight / search_radius);
neighbour_normal[i] = lerp(neighbour_normal[i], temp_normal, total_weight);
}
}
normal = normalize(neighbour_normal[0] + neighbour_normal[1] + neighbour_normal[2] + neighbour_normal[3]);
}
/*=============================================================================
Pixel Shaders
=============================================================================*/
void PS_InputBufferSetup(in MXAO_VSOUT MXAO, out float4 color : SV_Target0, out float4 depth : SV_Target1, out float4 normal : SV_Target2)
{
float3 single_pixel_offset = float3(qUINT::PIXEL_SIZE.xy, 0);
float3 position = get_position_from_uv(MXAO.uv.xy, MXAO);
float3 position_delta_x1 = - position + get_position_from_uv(MXAO.uv.xy + single_pixel_offset.xz, MXAO);
float3 position_delta_x2 = position - get_position_from_uv(MXAO.uv.xy - single_pixel_offset.xz, MXAO);
float3 position_delta_y1 = - position + get_position_from_uv(MXAO.uv.xy + single_pixel_offset.zy, MXAO);
float3 position_delta_y2 = position - get_position_from_uv(MXAO.uv.xy - single_pixel_offset.zy, MXAO);
position_delta_x1 = lerp(position_delta_x1, position_delta_x2, abs(position_delta_x1.z) > abs(position_delta_x2.z));
position_delta_y1 = lerp(position_delta_y1, position_delta_y2, abs(position_delta_y1.z) > abs(position_delta_y2.z));
float deltaz = abs(position_delta_x1.z * position_delta_x1.z - position_delta_x2.z * position_delta_x2.z)
+ abs(position_delta_y1.z * position_delta_y1.z - position_delta_y2.z * position_delta_y2.z);
normal = float4(normalize(cross(position_delta_y1, position_delta_x1)) * 0.5 + 0.5, deltaz);
color = tex2D(qUINT::sBackBufferTex, MXAO.uv.xy);
depth = qUINT::linear_depth(MXAO.uv.xy) * RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
}
void PS_StencilSetup(in MXAO_VSOUT MXAO, out float4 color : SV_Target0)
{
if( qUINT::linear_depth(MXAO.uv.zw) >= MXAO_FADE_DEPTH_END
|| 0.25 * 0.5 * MXAO_SAMPLE_RADIUS / (tex2D(sMXAO_DepthTex, MXAO.uv.zw).x + 2.0) * BUFFER_HEIGHT < 1.0
|| MXAO.uv.z > 1.0
|| MXAO.uv.w > 1.0
) discard;
color = 1.0;
}
void PS_AmbientObscurance(in MXAO_VSOUT MXAO, out float4 color : SV_Target0)
{
float3 position = get_position_from_uv_mipmapped(MXAO.uv.zw, MXAO, 0);
float3 normal = tex2D(sMXAO_NormalTex, MXAO.uv.zw).xyz * 2.0 - 1.0;
float sample_jitter = dot(floor(MXAO.vpos.xy % 4 + 0.1), float2(0.0625, 0.25)) + 0.0625;
float layer_id = (MXAO.vpos.x + MXAO.vpos.y) % 2.0;
#if(MXAO_SMOOTHNORMALS != 0)
smooth_normals(normal, position, MXAO);
#endif
float linear_depth = position.z / RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
position += normal * linear_depth;
if(MXAO_GLOBAL_SAMPLE_QUALITY_PRESET == 7) MXAO.samples = 2 + floor(0.05 * MXAO_SAMPLE_RADIUS / linear_depth);
float scaled_radius;
float falloff_factor;
sample_parameter_setup(MXAO, position.z, layer_id, scaled_radius, falloff_factor);
float2 tap_uv, sample_dir;
sincos(2.3999632 * 16 * sample_jitter, sample_dir.x, sample_dir.y); //2.3999632 * 16
sample_dir *= scaled_radius;
color = 0.0;
[loop]
for(int i = 0; i < MXAO.samples; i++)
{
tap_uv = MXAO.uv.zw + sample_dir.xy * qUINT::ASPECT_RATIO * (i + sample_jitter);
sample_dir.xy = mul(sample_dir.xy, float2x2(0.76465, -0.64444, 0.64444, 0.76465)); //cos/sin 2.3999632 * 16
float sample_mip = saturate(scaled_radius * i * 20.0) * 3.0;
float3 delta_v = -position + get_position_from_uv_mipmapped(tap_uv, MXAO, sample_mip + MXAO_MIPLEVEL_AO);
float v2 = dot(delta_v, delta_v);
float vn = dot(delta_v, normal) * rsqrt(v2);
float sample_ao = saturate(1.0 + falloff_factor * v2) * saturate(vn - MXAO_SAMPLE_NORMAL_BIAS);
#if(MXAO_ENABLE_IL != 0)
[branch]
if(sample_ao > 0.1)
{
float3 sample_il = tex2Dlod(sMXAO_ColorTex, float4(tap_uv, 0, sample_mip + MXAO_MIPLEVEL_IL)).xyz;
float3 sample_normal = tex2Dlod(sMXAO_NormalTex, float4(tap_uv, 0, sample_mip + MXAO_MIPLEVEL_IL)).xyz * 2.0 - 1.0;
sample_il *= sample_ao;
sample_il *= 0.5 + 0.5*saturate(dot(sample_normal, -delta_v * v2));
color += float4(sample_il, sample_ao);
}
#else
color.w += sample_ao;
#endif
}
color = saturate(color / ((1.0 - MXAO_SAMPLE_NORMAL_BIAS) * MXAO.samples) * 2.0);
color = color.BLUR_COMP_SWIZZLE;
color = sqrt(color);
#if(MXAO_TWO_LAYER != 0)
color *= lerp(MXAO_AMOUNT_COARSE, MXAO_AMOUNT_FINE, layer_id);
#endif
}
void PS_AmbientObscuranceHQ(in MXAO_VSOUT MXAO, out float4 color : SV_Target0)
{
float3 position = get_position_from_uv_mipmapped(MXAO.uv.zw, MXAO, 0);
float3 normal = normalize(tex2D(sMXAO_NormalTex, MXAO.uv.zw).xyz * 2.0 - 1.0); //fixes black lines
#if(MXAO_SMOOTHNORMALS != 0)
smooth_normals(normal, position, MXAO);
#endif
float3 viewdir = normalize(-position);
int directions = 2 + floor(MXAO.samples / 32) * 2;
int stepshalf = MXAO.samples / (directions * 2);
float angle_correct = 1 - viewdir.z * viewdir.z;
float scaled_radius = MXAO_SAMPLE_RADIUS / position.z / stepshalf * RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
float falloff_factor = 0.25 * rcp(MXAO_SAMPLE_RADIUS * MXAO_SAMPLE_RADIUS);
float sample_jitter = dot(floor(MXAO.vpos.xy % 4 + 0.1), float2(0.0625, 0.25)) + 0.0625;
float dir_phi = 3.14159265 / directions;
float2 sample_dir; sincos(dir_phi * sample_jitter * 6, sample_dir.y, sample_dir.x);
float2x2 rot_dir = float2x2(cos(dir_phi),-sin(dir_phi),
sin(dir_phi),cos(dir_phi));
color = 0;
[loop]
for(float i = 0; i < directions; i++)
{
sample_dir = mul(sample_dir, rot_dir);
float2 start = sample_dir * sample_jitter;
float3 sliceDir = float3(sample_dir, 0);
float2 h = -1.0;
#if(MXAO_ENABLE_IL != 0)
float3 il[2];il[0] = 0;il[1] = 0;
#endif
[loop]
for(int j = 0; j < stepshalf; j++)
{
float4 tap_uv = MXAO.uv.zwzw + scaled_radius * qUINT::PIXEL_SIZE.xyxy * start.xyxy * float4(1,1,-1,-1);
float sample_mip = saturate(scaled_radius * j * 0.01) * 3.0;
float3 delta_v[2];
delta_v[0] = -position + get_position_from_uv_mipmapped(tap_uv.xy, MXAO, sample_mip + MXAO_MIPLEVEL_AO);
delta_v[1] = -position + get_position_from_uv_mipmapped(tap_uv.zw, MXAO, sample_mip + MXAO_MIPLEVEL_AO);
float2 v2 = float2(dot(delta_v[0], delta_v[0]),
dot(delta_v[1], delta_v[1]));
float2 inv_distance = rsqrt(v2);
float2 sample_h = float2(dot(delta_v[0], viewdir),
dot(delta_v[1], viewdir)) * inv_distance;
float2 falloff = saturate(v2 * falloff_factor);
sample_h = lerp(sample_h, h, falloff);
#if(MXAO_ENABLE_IL != 0)
float3 sample_il[2], sample_normal[2]; sample_il[0] = 0; sample_il[1] = 0;
[branch]
if(falloff.x < 0.8)
{
sample_il[0] = tex2Dlod(sMXAO_ColorTex, float4(tap_uv.xy, 0, sample_mip + MXAO_MIPLEVEL_IL)).xyz;
sample_normal[0] = tex2Dlod(sMXAO_NormalTex, float4(tap_uv.xy, 0, sample_mip + MXAO_MIPLEVEL_IL)).xyz * 2.0 - 1.0;
sample_il[0] *= saturate(-inv_distance.x * dot(delta_v[0], sample_normal[0]));
sample_il[0] = lerp(sample_il[0], il[0], saturate( v2.x * falloff_factor));
}
[branch]
if(falloff.y < 0.8)
{
sample_il[1] = tex2Dlod(sMXAO_ColorTex, float4(tap_uv.zw, 0, sample_mip + MXAO_MIPLEVEL_IL)).xyz;
sample_normal[1] = tex2Dlod(sMXAO_NormalTex, float4(tap_uv.zw, 0, sample_mip + MXAO_MIPLEVEL_IL)).xyz * 2.0 - 1.0;
sample_il[1] *= saturate(-inv_distance.y * dot(delta_v[1], sample_normal[1]));
sample_il[1] = lerp(sample_il[1], il[1], saturate( v2.y * falloff_factor));
}
#endif
h.xy = (sample_h > h) ? sample_h : lerp(sample_h, h, 0.75);
#if(MXAO_ENABLE_IL != 0)
il[0] = (sample_h.x > h.x) ? sample_il[0] : lerp(sample_il[0], il[0], 0.75);
il[1] = (sample_h.y > h.y) ? sample_il[1] : lerp(sample_il[1], il[1], 0.75);
#endif
start += sample_dir;
}
float3 normal_slice_plane = normalize(cross(sliceDir, viewdir));
float3 tangent = cross(viewdir, normal_slice_plane);
float3 proj_normal = normal - normal_slice_plane * dot(normal, normal_slice_plane);
float proj_length = length(proj_normal);
float cos_gamma = clamp(dot(proj_normal, viewdir) * rcp(proj_length), -1.0, 1.0);
float gamma = -sign(dot(proj_normal, tangent)) * acos(cos_gamma);
h = acos(min(h, 1));
h.x = gamma + max(-h.x - gamma, -1.5707963);
h.y = gamma + min( h.y - gamma, 1.5707963);
h *= 2;
float2 sample_ao = cos_gamma + h * sin(gamma) - cos(h - gamma);
color.w += proj_length * dot(sample_ao, 0.25);
#if(MXAO_ENABLE_IL != 0)
color.rgb += proj_length * sample_ao.x * 0.25 * il[0];
color.rgb += proj_length * sample_ao.y * 0.25 * il[1];
#endif
}
color /= directions;
color.w = 1 - color.w;
color = color.BLUR_COMP_SWIZZLE;
color = sqrt(color);
}
void PS_SpatialFilter1(in MXAO_VSOUT MXAO, out float4 color : SV_Target0)
{
color = blur_filter(MXAO, sCommonTex0, MXAO_GLOBAL_RENDER_SCALE, 0.75, 4);
}
void PS_SpatialFilter2(MXAO_VSOUT MXAO, out float4 color : SV_Target0)
{
float4 ssil_ssao = blur_filter(MXAO, sCommonTex1, 1, 1.0 / MXAO_GLOBAL_RENDER_SCALE, 8);
ssil_ssao *= ssil_ssao;
color = tex2D(sMXAO_ColorTex, MXAO.uv.xy);
static const float3 lumcoeff = float3(0.2126, 0.7152, 0.0722);
float scenedepth = qUINT::linear_depth(MXAO.uv.xy);
float colorgray = dot(color.rgb, lumcoeff);
float blendfact = 1.0 - colorgray;
#if(MXAO_ENABLE_IL != 0)
ssil_ssao.xyz = lerp(dot(ssil_ssao.xyz, lumcoeff), ssil_ssao.xyz, MXAO_SSIL_SATURATION) * MXAO_SSIL_AMOUNT * 2.0;
#else
ssil_ssao.xyz = 0.0;
#endif
#if(MXAO_HIGH_QUALITY == 0)
ssil_ssao.w = 1.0 - pow(saturate(1.0 - ssil_ssao.w), MXAO_SSAO_AMOUNT * 2.0);
#else
ssil_ssao.w = 1.0 - pow(saturate(1.0 - ssil_ssao.w), MXAO_SSAO_AMOUNT);
#endif
ssil_ssao *= 1.0 - smoothstep(MXAO_FADE_DEPTH_START, MXAO_FADE_DEPTH_END, scenedepth * float4(2.0, 2.0, 2.0, 1.0));
if(MXAO_BLEND_TYPE == 0)
{
color.rgb -= (ssil_ssao.www - ssil_ssao.xyz) * blendfact * color.rgb;
}
else if(MXAO_BLEND_TYPE == 1)
{
color.rgb = color.rgb * saturate(1.0 - ssil_ssao.www * blendfact * 1.2) + ssil_ssao.xyz * blendfact * colorgray * 2.0;
}
else if(MXAO_BLEND_TYPE == 2)
{
float colordiff = saturate(2.0 * distance(normalize(color.rgb + 1e-6),normalize(ssil_ssao.rgb + 1e-6)));
color.rgb = color.rgb + ssil_ssao.rgb * lerp(color.rgb, dot(color.rgb, 0.3333), colordiff) * blendfact * blendfact * 4.0;
color.rgb = color.rgb * (1.0 - ssil_ssao.www * (1.0 - dot(color.rgb, lumcoeff)));
}
else if(MXAO_BLEND_TYPE == 3)
{
color.rgb *= color.rgb;
color.rgb -= (ssil_ssao.www - ssil_ssao.xyz) * color.rgb;
color.rgb = sqrt(color.rgb);
}
if(MXAO_DEBUG_VIEW_ENABLE == 1)
{
color.rgb = max(0.0, 1.0 - ssil_ssao.www + ssil_ssao.xyz);
color.rgb *= (MXAO_ENABLE_IL != 0) ? 0.5 : 1.0;
}
else if(MXAO_DEBUG_VIEW_ENABLE == 2)
{
color.rgb = tex2D(sMXAO_NormalTex, MXAO.uv.xy).xyz;
color.b = 1-color.b; //looks nicer
}
color.a = 1.0;
}
/*=============================================================================
Techniques
=============================================================================*/
technique MXAO
< ui_tooltip = " >> qUINT::MXAO <<\n\n"
"MXAO is a screen-space ambient occlusion shader.\n"
"It adds diffuse shading to object corners to give more depth\n"
"and detail to the scene. Check out the preprocessor options to\n"
"get access to more functionality.\n"
"\nMake sure to move MXAO to the very top of your shader list for\n"
"maximum compatibility with other shaders.\n"
"\nMXAO is written by Marty McFly / Pascal Gilcher"; >
{
pass
{
VertexShader = VS_MXAO;
PixelShader = PS_InputBufferSetup;
RenderTarget0 = MXAO_ColorTex;
RenderTarget1 = MXAO_DepthTex;
RenderTarget2 = MXAO_NormalTex;
}
pass
{
VertexShader = VS_MXAO;
PixelShader = PS_StencilSetup;
/*Render Target is Backbuffer*/
ClearRenderTargets = true;
StencilEnable = true;
StencilPass = REPLACE;
StencilRef = 1;
}
#if(MXAO_HIGH_QUALITY != 0)
pass
{
VertexShader = VS_MXAO;
PixelShader = PS_AmbientObscuranceHQ;
RenderTarget = CommonTex0;
ClearRenderTargets = true;
StencilEnable = true;
StencilPass = KEEP;
StencilFunc = EQUAL;
StencilRef = 1;
}
#else
pass
{
VertexShader = VS_MXAO;
PixelShader = PS_AmbientObscurance;
RenderTarget = CommonTex0;
ClearRenderTargets = true;
StencilEnable = true;
StencilPass = KEEP;
StencilFunc = EQUAL;
StencilRef = 1;
}
#endif
pass
{
VertexShader = VS_MXAO;
PixelShader = PS_SpatialFilter1;
RenderTarget = CommonTex1;
}
pass
{
VertexShader = VS_MXAO;
PixelShader = PS_SpatialFilter2;
/*Render Target is Backbuffer*/
}
}

View File

@ -0,0 +1,191 @@
/*=============================================================================
ReShade 4 effect file
github.com/martymcmodding
Support me:
paypal.me/mcflypg
patreon.com/mcflypg
Depth enhanced local contrast sharpen
by Marty McFly / P.Gilcher
part of qUINT shader library for ReShade 4
Copyright (c) Pascal Gilcher / Marty McFly. All rights reserved.
=============================================================================*/
/*=============================================================================
Preprocessor settings
=============================================================================*/
/*=============================================================================
UI Uniforms
=============================================================================*/
uniform float SHARP_STRENGTH <
ui_type = "slider";
ui_label = "Sharpen Strength";
ui_min = 0.0;
ui_max = 1.0;
> = 0.7;
uniform bool DEPTH_MASK_ENABLE <
ui_label = "Use Depth Mask";
> = true;
uniform bool RMS_MASK_ENABLE <
ui_label = "Use Local Contrast Enhancer";
> = true;
uniform int SHARPEN_MODE <
ui_type = "radio";
ui_label = "Sharpen Mode";
ui_category = "Sharpen Mode";
ui_items = "Chroma\0Luma\0";
> = 1;
/*=============================================================================
Textures, Samplers, Globals
=============================================================================*/
#define RESHADE_QUINT_COMMON_VERSION_REQUIRE 202
#define RESHADE_QUINT_EFFECT_DEPTH_REQUIRE //effect requires depth access
#include "qUINT_common.fxh"
/*=============================================================================
Vertex Shader
=============================================================================*/
struct VSOUT
{
float4 vpos : SV_Position;
float2 uv : TEXCOORD0;
};
VSOUT VS_Sharp(in uint id : SV_VertexID)
{
VSOUT o;
o.uv.x = (id == 2) ? 2.0 : 0.0;
o.uv.y = (id == 1) ? 2.0 : 0.0;
o.vpos = float4(o.uv.xy * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
return o;
}
/*=============================================================================
Functions
=============================================================================*/
float color_to_lum(float3 color)
{
return dot(color, float3(0.3, 0.59, 0.11));
}
float3 blend_overlay(float3 a, float3 b)
{
float3 c = 1.0 - a;
float3 d = 1.0 - b;
return a < 0.5 ? (2.0 * a * b) : (1.0 - 2.0 * c * d);
}
float4 fetch_color_and_depth(float2 uv)
{
return float4( tex2D(qUINT::sBackBufferTex, uv).rgb,
qUINT::linear_depth(uv));
}
/*=============================================================================
Pixel Shaders
=============================================================================*/
void PS_Sharp(in VSOUT i, out float3 o : SV_Target0)
{
// A B C
// D E F
// G H I
float4 A, B, C, D, E, F, G, H, I;
float3 offsets = float3(1, 0, -1);
A = fetch_color_and_depth(i.uv + offsets.zz * qUINT::PIXEL_SIZE);
B = fetch_color_and_depth(i.uv + offsets.yz * qUINT::PIXEL_SIZE);
C = fetch_color_and_depth(i.uv + offsets.xz * qUINT::PIXEL_SIZE);
D = fetch_color_and_depth(i.uv + offsets.zy * qUINT::PIXEL_SIZE);
E = fetch_color_and_depth(i.uv + offsets.yy * qUINT::PIXEL_SIZE);
F = fetch_color_and_depth(i.uv + offsets.xy * qUINT::PIXEL_SIZE);
G = fetch_color_and_depth(i.uv + offsets.zx * qUINT::PIXEL_SIZE);
H = fetch_color_and_depth(i.uv + offsets.yx * qUINT::PIXEL_SIZE);
I = fetch_color_and_depth(i.uv + offsets.xx * qUINT::PIXEL_SIZE);
float4 corners = (A + C) + (G + I);
float4 neighbours = (B + D) + (F + H);
float4 center = E;
float4 edge = corners + 2.0 * neighbours - 12.0 * center;
float3 sharpen = edge.rgb;
//measures root mean square as local contrast measurement
//to adjust the intensity of the sharpener at edges with
//high local contrast to restrict sharpen to texture detail
//only while leaving object and detail outlines mostly alone.
[branch]
if(RMS_MASK_ENABLE)
{
float3 mean = (corners.rgb + neighbours.rgb + center.rgb) / 9.0;
float3 RMS = (mean - A.rgb) * (mean - A.rgb);
RMS += (mean - B.rgb) * (mean - B.rgb);
RMS += (mean - C.rgb) * (mean - C.rgb);
RMS += (mean - D.rgb) * (mean - D.rgb);
RMS += (mean - E.rgb) * (mean - E.rgb);
RMS += (mean - F.rgb) * (mean - F.rgb);
RMS += (mean - G.rgb) * (mean - G.rgb);
RMS += (mean - H.rgb) * (mean - H.rgb);
RMS += (mean - I.rgb) * (mean - I.rgb);
//sharpen /= RMS * 16.0 + 0.025 * 16.0; //wrapped the div / 9 in here
sharpen *= rsqrt(RMS + 0.001) * 0.1;
}
//Remove sharpen completely from depth edges, as these never look good
//with any kind of sharpening and always create exaggerated halos that
//ruin any strong sharpening which would otherwise enhance textures
sharpen *= DEPTH_MASK_ENABLE ? saturate(1.0 - abs(edge.w) * 4000.0) : 1;
//grayscale sharpen mask, helps if some color artifacts arise, red-blue
//is mostly prone to create weirdly colored spots.
if(SHARPEN_MODE == 1)
sharpen = color_to_lum(sharpen);
sharpen = -sharpen * SHARP_STRENGTH * 0.1;
//smooth falloff, cheaper than pow() with little error
sharpen = sign(sharpen) * log(abs(sharpen) * 10.0 + 1.0)*0.3;
o = blend_overlay(center.rgb, (0.5 + sharpen));
}
/*=============================================================================
Techniques
=============================================================================*/
technique DELC_Sharpen
< ui_tooltip = " >> qUINT::DELCS <<\n\n"
"DELCS is an advanced sharpen filter made to enhance texture detail.\n"
"It offers a local contrast detection method and allows to suppress\n"
"oversharpening on depth edges to combat common sharpen artifacts.\n"
"get access to more functionality.\n"
"\nDELCS is best positioned after most shaders but before film grain or such.\n"
"\DELCS is written by Marty McFly / Pascal Gilcher"; >
{
pass
{
VertexShader = VS_Sharp;
PixelShader = PS_Sharp;
}
}

Some files were not shown because too many files have changed in this diff Show More