Prod80's shader library
- prod80
- Topic Author
Reshade unfortunately does not have access to the HDR texture from the game engine. The texture we can manipulate is already 8 bit. As such we can not make a true replication of the "HDR effect" of Photoshop.
We can only simulate it (basically a contrast effect), but it won't look the same because for us the extra data that may be available in shadows and highlights like those from a 10-14bit+ camera sensor is simply not there.
Please Log in or Create an account to join the conversation.
- gamehancer
link> fixthephoto.com/fr/action-photoshop-hdr-gratuit
Please Log in or Create an account to join the conversation.
- Tojkar
That kind of effect is relatively easy to achieve with Clarity.fx. Fiddle with that to create similar HDR-effect with luma or darkness of the pixels(I dont speak photoshop, so might not use exactly correct terms here) and then use what ever color affecting shaders to colorize the image as you see fit. Lightroom from MartyMcFly for example or Prod80's shaders from this topic are good for that. You can get Clarity.fx from official repo or when installing ReShade.gamehancer wrote: thank you really for taking the time to answer it's a shame with clarity I'm trying to reproduce the same thing as the hdr like this image my it's complicated
link> fixthephoto.com/fr/action-photoshop-hdr-gratuit
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
I can do the same with my reshade shaders, or close enough, to restore from his "before" picture. Literally took less than 5 minutes to do this.
Before
After
Literally took the picture from his website and put it in an effect and ran my reshade shaders over them. As you can see here. The quality is horrible with a crappy small picture from his website that I had to upscale to 1080p and became all pixelated. But you get the point I assume..
That's why I say I'm a little at a loss what you want exactly. Most effects are already there to achieve exactly what you want to achieve. You just have to use them. I don't have a "Preset for a certain look" ... that, you have to do yourself. Photoshop "Actions" are simply a series of effects ran after each other to get a certain look. You can do the exact same with ReShade.
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
In the last few days added dithering into
- PD80_02_Bloom.fx
- PD80_01B_RT_Correct_Color.fx
- PD80_03_Shadows_Midtones_Highlights.fx
- PD80_04_Color_Gradients.fx
- PD80_04_BlacknWhite.fx
- PD80_04_Magical_Rectangle.fx
Tint (Warm / Cold) added to PD80_04_Contrast_Brightness_Saturation.fx
Please Log in or Create an account to join the conversation.
- Wicked Sick
Please Log in or Create an account to join the conversation.
- klotim
A question, do I need correct contrast if I have correct color, if yes, should correct contrast be loaded after or before correct color per your preference?
Also, do I need the dithering if I have tri-dither first in the load order?
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
klotim wrote: Thank you for the optimization for the bloom. Appreciate it!
A question, do I need correct contrast if I have correct color, if yes, should correct contrast be loaded after or before correct color per your preference?
Also, do I need the dithering if I have tri-dither first in the load order?
Correct Color and Contrast are two different effects that almost do the same thing with 1 critical difference; correct contrast does not change the coloring.
Dither is needed prior to running the effect, but within the same .fx file... doing tri-dither as a pass between or before doesn't matter because colors are rounded to uint8 each time they are written back to the backbuffer (end of each shader). Dither only helps when you're doing effects inside the shader itself (after or before dithering, depending on what you want). Doing just a shader that only dithers and nothing else is kind of weird because input is uint8 and output is uint8 and between there's nothing that's happening other then dither. Basically it becomes a noise effect then.
Example of dithering
imgsli.com/MTM0NjQ
Doing strong "destructive" effect, with and without dither
imgsli.com/MTM0NjU
Please Log in or Create an account to join the conversation.
- gamehancer
Please Log in or Create an account to join the conversation.
- klotim
prod80 wrote:
klotim wrote: Thank you for the optimization for the bloom. Appreciate it!
A question, do I need correct contrast if I have correct color, if yes, should correct contrast be loaded after or before correct color per your preference?
Also, do I need the dithering if I have tri-dither first in the load order?
Correct Color and Contrast are two different effects that almost do the same thing with 1 critical difference; correct contrast does not change the coloring.
Dither is needed prior to running the effect, but within the same .fx file... doing tri-dither as a pass between or before doesn't matter because colors are rounded to uint8 each time they are written back to the backbuffer (end of each shader). Dither only helps when you're doing effects inside the shader itself (after or before dithering, depending on what you want). Doing just a shader that only dithers and nothing else is kind of weird because input is uint8 and output is uint8 and between there's nothing that's happening other then dither. Basically it becomes a noise effect then.
Example of dithering
imgsli.com/MTM0NjQ
Doing strong "destructive" effect, with and without dither
imgsli.com/MTM0NjU
Ahh so i take it correct contrast is not needed then if i use correct color?
Just noticed that there's no performance mode for correct contrast, is it intended? I noticed quite a difference with the performance mode for correct color. Appreciate that!
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
Histogram of an image where the game compressed the available color depth
After Correct Contrast adjust the white/black points
But in most cases, there will be no effect. Only when the darkest and/or the lightest value in the screen is not 0 (0) or 255 (1).
You can easily see this effect when going in a game in a dark room, night, or just simply run to a wall.
And no, you don't need to run them at the same time, though there may be some situations where there's heavy coloring that running correct contrast before correct color will allow a better removal of the color cast. The reason it's more heavy to run is because correct contrast will sample each and every pixel on your screen.
The correct color has a performance mode in 2 different ways;
1) set the precision to a higher value in which the shader will sample mip levels, each mip level is 1/4th the size of the previous level, which also reducing the amount of samples taken when pixels are missed. It's called precision because a mip level will interpolate the pixels it reduced. For example, if a cluser of 4 pixels is reduced to 1 pixel (1 mip level lower) and the pixels have values of 0.0, 0.0, 0.0, 1.0, then the resulting pixel will have a value of 0.25. Additionally setting precision to a higher level will remove color more aggressively in case required. You can use preserve luma option to compensate if it removed too much.
2) "use performance mode" works under the assumption that if there is 1 white or black pixel in the screen, there will be more. So instead of relying on mip levels it will just skip pixels during sampling. Setting performance mode will skip 3 pixels on each read, so reducing the number of reads by a factor 4. The potential benefit here is that you may not sacrifice precision as no pixels are mixed, but it may also not find the correct pixel when the number of brightest or darkest pixels in the scene is very small.
Using both simultaneously may reduce the effect of the shader to a point it is not desirable.. would advise to use either one, but not both.
Each have their benefits.
Please Log in or Create an account to join the conversation.
- gamehancer
Please Log in or Create an account to join the conversation.
- Tojkar
I really liked the black and white shader as it was when you originally posted it. It was possible to abuse it to create very artistic effects on the screen which are not possible with the new black and white while the new is much better for it's intended use. Would you mind to re-publish the old version as a completely new shader? Combined with some other shaders it was able to make some very painterly effects which was great.
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
Tojkar wrote: Hi Prod80.
I really liked the black and white shader as it was when you originally posted it. It was possible to abuse it to create very artistic effects on the screen which are not possible with the new black and white while the new is much better for it's intended use. Would you mind to re-publish the old version as a completely new shader? Combined with some other shaders it was able to make some very painterly effects which was great.
Hey, could you let me know exactly which effect you’re referring to that the old B&W shader had? There were a few versions... also, the effect may still be there, just moved to a different shader (like all the color grading went to the new Color Gradient shader)
Please Log in or Create an account to join the conversation.
- Tojkar
prod80 wrote:
Tojkar wrote: Hi Prod80.
I really liked the black and white shader as it was when you originally posted it. It was possible to abuse it to create very artistic effects on the screen which are not possible with the new black and white while the new is much better for it's intended use. Would you mind to re-publish the old version as a completely new shader? Combined with some other shaders it was able to make some very painterly effects which was great.
Hey, could you let me know exactly which effect you’re referring to that the old B&W shader had? There were a few versions... also, the effect may still be there, just moved to a different shader (like all the color grading went to the new Color Gradient shader)
This one is the latest version of this iteration I have.
Specifically the ability to select the layers (bw/colored/etc), the strength of gaussian blur and the blend mode are important to me.
Description : PD80 04 Black & White for Reshade reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits
- Deband effect by haasn, optimized for Reshade by JPulowski
License: MIT, Copyright (c) 2015 Niklas Haas
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_blackandwhite
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
#ifndef BW_ENABLE_DEBAND
#define BW_ENABLE_DEBAND 0 // Default is OFF ( 0 ) as only makes sense on wide blur ranges which is generally not needed in this effect
#endif
// Min: 0, Max: 3 | Blur 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/2th size - High
// 2 = 1/4th size - Medium
#ifndef BW_GAUSSIAN_QUALITY
#define BW_GAUSSIAN_QUALITY 1 // Default = High quality (1) which strikes a balance between performance and image quality
#endif
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float3 luminosity <
ui_type = "color";
ui_label = "Select Color to Convert B&W";
ui_category = "Black & White Techniques";
> = float3(0.6, 1.0, 0.4);
// Gaussian Blur
uniform float BlurSigma <
ui_type = "slider";
ui_label = "Blur Width";
ui_category = "Black & White Blend Mode";
ui_min = 2.0f;
ui_max = 10.0f;
> = 6.0;
uniform int basecolor_1 < __UNIFORM_COMBO_INT1
ui_label = "Base Image";
ui_category = "Black & White Blend Mode";
ui_items = "Original Color\0Black & White\0Black & White Gaussian\0";
> = 1;
uniform int blendcolor_1 < __UNIFORM_COMBO_INT1
ui_label = "Blend Image";
ui_category = "Black & White Blend Mode";
ui_items = "Original Color\0Black & White\0Black & White Gaussian\0";
> = 2;
uniform int blendmode_1 < __UNIFORM_COMBO_INT1
ui_label = "Blend Mode";
ui_category = "Black & White Blend Mode";
ui_items = "Normal\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0";
> = 10;
uniform float opacity_1 <
ui_type = "slider";
ui_label = "Opacity";
ui_category = "Black & White Blend Mode";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.333;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texColorBuffer : COLOR;
texture texColorNew { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
#if( BW_GAUSSIAN_QUALITY == 0 )
#define SWIDTH BUFFER_WIDTH
#define SHEIGHT BUFFER_HEIGHT
texture texBlurIn { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture texBlurH { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture texBlur { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
#endif
#if( BW_GAUSSIAN_QUALITY == 1 )
#define SWIDTH ( BUFFER_WIDTH / 4 * 3 )
#define SHEIGHT ( BUFFER_HEIGHT / 4 * 3 )
texture texBlurIn { Width = SWIDTH; Height = SHEIGHT; };
texture texBlurH { Width = SWIDTH; Height = SHEIGHT; };
texture texBlur { Width = SWIDTH; Height = SHEIGHT; };
#endif
#if( BW_GAUSSIAN_QUALITY == 2 )
#define SWIDTH ( BUFFER_WIDTH / 2 )
#define SHEIGHT ( BUFFER_HEIGHT / 2 )
texture texBlurIn { Width = SWIDTH; Height = SHEIGHT; };
texture texBlurH { Width = SWIDTH; Height = SHEIGHT; };
texture texBlur { Width = SWIDTH; Height = SHEIGHT; };
#endif
texture texBlurDeband { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerColor { Texture = texColorBuffer; };
sampler samplerColorNew { Texture = texColorNew; };
sampler samplerBlurIn { Texture = texBlurIn; };
sampler samplerBlurH { Texture = texBlurH; };
sampler samplerBlur { Texture = texBlur; };
sampler samplerBlurDeband { Texture = texBlurDeband; };
//// DEFINES ////////////////////////////////////////////////////////////////////
#define Pi 3.141592f
#define Loops 30 * ( float( BUFFER_WIDTH ) / 1920.0f )
#define Quality 0.985f
#define px rcp( SWIDTH )
#define py rcp( SHEIGHT )
//// FUNCTIONS //////////////////////////////////////////////////////////////////
#if( BW_ENABLE_DEBAND == 1 )
uniform int drandom < source = "random"; min = 0; max = 32767; >;
void analyze_pixels(float3 ori, sampler2D tex, float2 texcoord, float2 _range, float2 dir, out float3 ref_avg, out float3 ref_avg_diff, out float3 ref_max_diff, out float3 ref_mid_diff1, out float3 ref_mid_diff2)
{
// South-east
float3 ref = tex2Dlod( tex, float4( texcoord + _range * dir, 0.0f, 0.0f )).rgb;
float3 diff = abs( ori - ref );
ref_max_diff = diff;
ref_avg = ref;
ref_mid_diff1 = ref;
// North-west
ref = tex2Dlod( tex, float4( texcoord + _range * -dir, 0.0f, 0.0f )).rgb;
diff = abs( ori - ref );
ref_max_diff = max( ref_max_diff, diff );
ref_avg += ref;
ref_mid_diff1 = abs((( ref_mid_diff1 + ref ) * 0.5f ) - ori );
// North-east
ref = tex2Dlod( tex, float4( texcoord + _range * float2( -dir.y, dir.x ), 0.0f, 0.0f )).rgb;
diff = abs( ori - ref );
ref_max_diff = max( ref_max_diff, diff );
ref_avg += ref;
ref_mid_diff2 = ref;
// South-west
ref = tex2Dlod( tex, float4( texcoord + _range * float2( dir.y, -dir.x ), 0.0f, 0.0f )).rgb;
diff = abs( ori - ref );
ref_max_diff = max( ref_max_diff, diff );
ref_avg += ref;
ref_mid_diff2 = abs((( ref_mid_diff2 + ref ) * 0.5f ) - ori );
// Normalize avg
ref_avg *= 0.25f;
ref_avg_diff = abs( ori - ref_avg );
}
float permute( in float x )
{
return ((34.0f * x + 1.0f) * x) % 289.0f;
}
float rand( in float x )
{
return frac(x / 41.0f);
}
#endif
float3 darken(float3 c, float3 b) { return min(b, c);}
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:max((1.0f-((1.0f-c)/b)), 0.0f);}
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:min(c/(1.0f-b), 1.0f);}
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 createBlend( float3 c, float3 b, int mode )
{
switch( mode )
{
case 0: return b.xyz;
case 1: return darken( c.xyz, b.xyz);
case 2: return multiply( c.xyz, b.xyz);
case 3: return linearburn( c.xyz, b.xyz);
case 4: return colorburn( c.xyz, b.xyz);
case 5: return lighten( c.xyz, b.xyz);
case 6: return screen( c.xyz, b.xyz);
case 7: return colordodge( c.xyz, b.xyz);
case 8: return lineardodge( c.xyz, b.xyz);
case 9: return overlay( c.xyz, b.xyz);
case 10: return softlight( c.xyz, b.xyz);
case 11: return vividlight( c.xyz, b.xyz);
case 12: return linearlight( c.xyz, b.xyz);
case 13: return pinlight( c.xyz, b.xyz);
default: return b.xyz;
}
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_BlackandWhite(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerColor, texcoord );
// B & W conversion options
// Technique 1: Selection of any RGB to create the B&W image
float gsMult = dot( luminosity.xyz, 1.0f );
float3 greyscale = luminosity.xyz / gsMult;
color.xyz = dot( color.xyz, greyscale.xyz );
// Technique 2: Use multiplification of R G B or Luma channel to create B&W image
// TODO
return float4( color.xyz, 1.0f ); // Writes to texColorNew
}
float4 PS_DownscaleImg(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerColorNew, texcoord );
return float4( color.xyz, 1.0f ); // Writes to texColorNew
}
float4 PS_GaussianH(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBlurIn, texcoord );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float calcOffset = 0.0f;
float2 buffSigma = 0.0f;
float3 Sigma;
float bSigma;
#if( BW_GAUSSIAN_QUALITY == 0 )
bSigma = BlurSigma;
#endif
#if( BW_GAUSSIAN_QUALITY == 1 )
bSigma = BlurSigma * 0.75f;
#endif
#if( BW_GAUSSIAN_QUALITY == 2 )
bSigma = BlurSigma * 0.5f;
#endif
bSigma = bSigma * ( float( BUFFER_WIDTH ) / 1920.0 );
Sigma.x = 1.0f / ( sqrt( 2.0f * Pi ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
color.xyz *= Sigma.x;
SigmaSum += Sigma.x;
Sigma.xy *= Sigma.yz;
for( int i = 0; i < Loops && SigmaSum <= Quality; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2D( samplerBlurIn, texcoord.xy + float2( pxlOffset*px, 0.0f )) * buffSigma.y;
color += tex2D( samplerBlurIn, texcoord.xy - float2( pxlOffset*px, 0.0f )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color.xyz /= SigmaSum;
return float4( color.xyz, 1.0f ); // Writes to texBlurH
}
float4 PS_GaussianV(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBlurH, texcoord );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float calcOffset = 0.0f;
float2 buffSigma = 0.0f;
float3 Sigma;
float bSigma;
#if( BW_GAUSSIAN_QUALITY == 0 )
bSigma = BlurSigma;
#endif
#if( BW_GAUSSIAN_QUALITY == 1 )
bSigma = BlurSigma * 0.75f;
#endif
#if( BW_GAUSSIAN_QUALITY == 2 )
bSigma = BlurSigma * 0.5f;
#endif
bSigma = bSigma * ( float( BUFFER_WIDTH ) / 1920.0 );
Sigma.x = 1.0f / ( sqrt( 2.0f * Pi ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
color.xyz *= Sigma.x;
SigmaSum += Sigma.x;
Sigma.xy *= Sigma.yz;
for( int i = 0; i < Loops && SigmaSum < Quality; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2D( samplerBlurH, texcoord.xy + float2( 0.0f, pxlOffset*py )) * buffSigma.y;
color += tex2D( samplerBlurH, texcoord.xy - float2( 0.0f, pxlOffset*py )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color.xyz /= SigmaSum;
return float4( color.xyz, 1.0f ); // Writes to texBlur
}
#if( BW_ENABLE_DEBAND == 1 )
float4 PS_BloomDeband(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBlur, texcoord );
float avgdiff = 3.4f / 255.0f;
float maxdiff = 6.8f / 255.0f;
float middiff = 3.3f / 255.0f;
float h = permute( permute( permute( texcoord.x ) + texcoord.y ) + drandom / 32767.0f );
float3 ref_avg;
float3 ref_avg_diff;
float3 ref_max_diff;
float3 ref_mid_diff1;
float3 ref_mid_diff2;
float3 ori = color.xyz;
float3 res;
float dir = rand( permute( h )) * 6.2831853f;
float2 o = float2( cos( dir ), sin( dir ));
float range = 6.0f / ( BW_GAUSSIAN_QUALITY + 1 );
for ( int i = 1; i <= 4; ++i )
{
float dist = rand(h) * range * i;
float2 pt = dist * float2( px, py );
analyze_pixels(ori, samplerBlur, texcoord, pt, o,
ref_avg,
ref_avg_diff,
ref_max_diff,
ref_mid_diff1,
ref_mid_diff2);
float3 ref_avg_diff_threshold = avgdiff * i;
float3 ref_max_diff_threshold = maxdiff * i;
float3 ref_mid_diff_threshold = middiff * i;
float3 factor = pow(saturate(3.0 * (1.0 - ref_avg_diff / ref_avg_diff_threshold)) *
saturate(3.0 * (1.0 - ref_max_diff / ref_max_diff_threshold)) *
saturate(3.0 * (1.0 - ref_mid_diff1 / ref_mid_diff_threshold)) *
saturate(3.0 * (1.0 - ref_mid_diff2 / ref_mid_diff_threshold)), 0.1);
res = lerp(ori, ref_avg, factor);
h = permute(h);
}
const float dither_bit = 8.0f;
float grid_position = frac(dot(texcoord, (float2( BUFFER_WIDTH, BUFFER_HEIGHT ) * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0));
float3 dither_shift_RGB = float3(dither_shift, -dither_shift, dither_shift);
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position.
res += dither_shift_RGB;
color.xyz = res.xyz;
return float4( color.xyz, 1.0f ); // Writes to texBlurDeband
}
#endif
float4 PS_BlendImgBlur(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 bwcolor = tex2D( samplerColorNew, texcoord );
float4 bwblur = tex2D( samplerBlur, texcoord );
#if( BW_ENABLE_DEBAND == 1 )
bwblur.xyz = tex2D( samplerBlurDeband, texcoord ).xyz;
#endif
float4 orig = tex2D( samplerColor, texcoord );
float3 base;
float3 blend;
float3 ret;
float3 color;
/*
Color or Targets
0 = Original Color
1 = B&W Image
2 = B&W Gaussian Blur
*/
switch( basecolor_1 )
{
case 0:
base.xyz = orig.xyz;
break;
case 1:
base.xyz = bwcolor.xyz;
break;
case 2:
base.xyz = bwblur.xyz;
break;
default:
base.xyz = bwcolor.xyz;
break;
}
switch( blendcolor_1 )
{
case 0:
blend.xyz = orig.xyz;
break;
case 1:
blend.xyz = bwcolor.xyz;
break;
case 2:
blend.xyz = bwblur.xyz;
break;
default:
base.xyz = bwblur.xyz;
break;
}
ret.xyz = createBlend( base.xyz, blend.xyz, blendmode_1 );
color.xyz = lerp( base.xyz, ret.xyz, opacity_1 );
return float4( color.xyz, 1.0f ); // Final output
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_Black_and_White
{
pass prod80_BlackandWhite
{
VertexShader = PostProcessVS;
PixelShader = PS_BlackandWhite;
RenderTarget = texColorNew;
}
pass prod80_Downscale
{
VertexShader = PostProcessVS;
PixelShader = PS_DownscaleImg;
RenderTarget = texBlurIn;
}
pass prod80_BlurH
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianH;
RenderTarget = texBlurH;
}
pass prod80_Blur
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianV;
RenderTarget = texBlur;
}
#if( BW_ENABLE_DEBAND == 1 )
pass prod80_BlurDeband
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomDeband;
RenderTarget = texBlurDeband;
}
#endif
pass prod80_Blend
{
VertexShader = PostProcessVS;
PixelShader = PS_BlendImgBlur;
}
}
}
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
Added motion to the dither as well.
On update please download both shaders and textures folders, as it has a new texture (bluenoise.png) renamed the old gaussian texture (gaussnoise.png) and it has a helper file now for me to easily load the noise samplers into the files where I want to use them (PD80_00_Noise_Samplers.fxh) so they don't clutter my files or the UI
Enjoy
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
Tojkar wrote:
prod80 wrote:
Tojkar wrote: Hi Prod80.
I really liked the black and white shader as it was when you originally posted it. It was possible to abuse it to create very artistic effects on the screen which are not possible with the new black and white while the new is much better for it's intended use. Would you mind to re-publish the old version as a completely new shader? Combined with some other shaders it was able to make some very painterly effects which was great.
Hey, could you let me know exactly which effect you’re referring to that the old B&W shader had? There were a few versions... also, the effect may still be there, just moved to a different shader (like all the color grading went to the new Color Gradient shader)
This one is the latest version of this iteration I have.
Specifically the ability to select the layers (bw/colored/etc), the strength of gaussian blur and the blend mode are important to me.
Warning: Spoiler!/*
Description : PD80 04 Black & White for Reshade reshade.me/
Author : prod80 (Bas Veth)
License : MIT, Copyright (c) 2020 prod80
Additional credits
- Deband effect by haasn, optimized for Reshade by JPulowski
License: MIT, Copyright (c) 2015 Niklas Haas
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_blackandwhite
{
//// PREPROCESSOR DEFINITIONS ///////////////////////////////////////////////////
#ifndef BW_ENABLE_DEBAND
#define BW_ENABLE_DEBAND 0 // Default is OFF ( 0 ) as only makes sense on wide blur ranges which is generally not needed in this effect
#endif
// Min: 0, Max: 3 | Blur 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/2th size - High
// 2 = 1/4th size - Medium
#ifndef BW_GAUSSIAN_QUALITY
#define BW_GAUSSIAN_QUALITY 1 // Default = High quality (1) which strikes a balance between performance and image quality
#endif
//// UI ELEMENTS ////////////////////////////////////////////////////////////////
uniform float3 luminosity <
ui_type = "color";
ui_label = "Select Color to Convert B&W";
ui_category = "Black & White Techniques";
> = float3(0.6, 1.0, 0.4);
// Gaussian Blur
uniform float BlurSigma <
ui_type = "slider";
ui_label = "Blur Width";
ui_category = "Black & White Blend Mode";
ui_min = 2.0f;
ui_max = 10.0f;
> = 6.0;
uniform int basecolor_1 < __UNIFORM_COMBO_INT1
ui_label = "Base Image";
ui_category = "Black & White Blend Mode";
ui_items = "Original Color\0Black & White\0Black & White Gaussian\0";
> = 1;
uniform int blendcolor_1 < __UNIFORM_COMBO_INT1
ui_label = "Blend Image";
ui_category = "Black & White Blend Mode";
ui_items = "Original Color\0Black & White\0Black & White Gaussian\0";
> = 2;
uniform int blendmode_1 < __UNIFORM_COMBO_INT1
ui_label = "Blend Mode";
ui_category = "Black & White Blend Mode";
ui_items = "Normal\0Darken\0Multiply\0Linearburn\0Colorburn\0Lighten\0Screen\0Colordodge\0Lineardodge\0Overlay\0Softlight\0Vividlight\0Linearlight\0Pinlight\0";
> = 10;
uniform float opacity_1 <
ui_type = "slider";
ui_label = "Opacity";
ui_category = "Black & White Blend Mode";
ui_min = 0.0f;
ui_max = 1.0f;
> = 0.333;
//// TEXTURES ///////////////////////////////////////////////////////////////////
texture texColorBuffer : COLOR;
texture texColorNew { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
#if( BW_GAUSSIAN_QUALITY == 0 )
#define SWIDTH BUFFER_WIDTH
#define SHEIGHT BUFFER_HEIGHT
texture texBlurIn { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture texBlurH { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
texture texBlur { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
#endif
#if( BW_GAUSSIAN_QUALITY == 1 )
#define SWIDTH ( BUFFER_WIDTH / 4 * 3 )
#define SHEIGHT ( BUFFER_HEIGHT / 4 * 3 )
texture texBlurIn { Width = SWIDTH; Height = SHEIGHT; };
texture texBlurH { Width = SWIDTH; Height = SHEIGHT; };
texture texBlur { Width = SWIDTH; Height = SHEIGHT; };
#endif
#if( BW_GAUSSIAN_QUALITY == 2 )
#define SWIDTH ( BUFFER_WIDTH / 2 )
#define SHEIGHT ( BUFFER_HEIGHT / 2 )
texture texBlurIn { Width = SWIDTH; Height = SHEIGHT; };
texture texBlurH { Width = SWIDTH; Height = SHEIGHT; };
texture texBlur { Width = SWIDTH; Height = SHEIGHT; };
#endif
texture texBlurDeband { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; };
//// SAMPLERS ///////////////////////////////////////////////////////////////////
sampler samplerColor { Texture = texColorBuffer; };
sampler samplerColorNew { Texture = texColorNew; };
sampler samplerBlurIn { Texture = texBlurIn; };
sampler samplerBlurH { Texture = texBlurH; };
sampler samplerBlur { Texture = texBlur; };
sampler samplerBlurDeband { Texture = texBlurDeband; };
//// DEFINES ////////////////////////////////////////////////////////////////////
#define Pi 3.141592f
#define Loops 30 * ( float( BUFFER_WIDTH ) / 1920.0f )
#define Quality 0.985f
#define px rcp( SWIDTH )
#define py rcp( SHEIGHT )
//// FUNCTIONS //////////////////////////////////////////////////////////////////
#if( BW_ENABLE_DEBAND == 1 )
uniform int drandom < source = "random"; min = 0; max = 32767; >;
void analyze_pixels(float3 ori, sampler2D tex, float2 texcoord, float2 _range, float2 dir, out float3 ref_avg, out float3 ref_avg_diff, out float3 ref_max_diff, out float3 ref_mid_diff1, out float3 ref_mid_diff2)
{
// South-east
float3 ref = tex2Dlod( tex, float4( texcoord + _range * dir, 0.0f, 0.0f )).rgb;
float3 diff = abs( ori - ref );
ref_max_diff = diff;
ref_avg = ref;
ref_mid_diff1 = ref;
// North-west
ref = tex2Dlod( tex, float4( texcoord + _range * -dir, 0.0f, 0.0f )).rgb;
diff = abs( ori - ref );
ref_max_diff = max( ref_max_diff, diff );
ref_avg += ref;
ref_mid_diff1 = abs((( ref_mid_diff1 + ref ) * 0.5f ) - ori );
// North-east
ref = tex2Dlod( tex, float4( texcoord + _range * float2( -dir.y, dir.x ), 0.0f, 0.0f )).rgb;
diff = abs( ori - ref );
ref_max_diff = max( ref_max_diff, diff );
ref_avg += ref;
ref_mid_diff2 = ref;
// South-west
ref = tex2Dlod( tex, float4( texcoord + _range * float2( dir.y, -dir.x ), 0.0f, 0.0f )).rgb;
diff = abs( ori - ref );
ref_max_diff = max( ref_max_diff, diff );
ref_avg += ref;
ref_mid_diff2 = abs((( ref_mid_diff2 + ref ) * 0.5f ) - ori );
// Normalize avg
ref_avg *= 0.25f;
ref_avg_diff = abs( ori - ref_avg );
}
float permute( in float x )
{
return ((34.0f * x + 1.0f) * x) % 289.0f;
}
float rand( in float x )
{
return frac(x / 41.0f);
}
#endif
float3 darken(float3 c, float3 b) { return min(b, c);}
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:max((1.0f-((1.0f-c)/b)), 0.0f);}
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:min(c/(1.0f-b), 1.0f);}
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 createBlend( float3 c, float3 b, int mode )
{
switch( mode )
{
case 0: return b.xyz;
case 1: return darken( c.xyz, b.xyz);
case 2: return multiply( c.xyz, b.xyz);
case 3: return linearburn( c.xyz, b.xyz);
case 4: return colorburn( c.xyz, b.xyz);
case 5: return lighten( c.xyz, b.xyz);
case 6: return screen( c.xyz, b.xyz);
case 7: return colordodge( c.xyz, b.xyz);
case 8: return lineardodge( c.xyz, b.xyz);
case 9: return overlay( c.xyz, b.xyz);
case 10: return softlight( c.xyz, b.xyz);
case 11: return vividlight( c.xyz, b.xyz);
case 12: return linearlight( c.xyz, b.xyz);
case 13: return pinlight( c.xyz, b.xyz);
default: return b.xyz;
}
}
//// PIXEL SHADERS //////////////////////////////////////////////////////////////
float4 PS_BlackandWhite(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerColor, texcoord );
// B & W conversion options
// Technique 1: Selection of any RGB to create the B&W image
float gsMult = dot( luminosity.xyz, 1.0f );
float3 greyscale = luminosity.xyz / gsMult;
color.xyz = dot( color.xyz, greyscale.xyz );
// Technique 2: Use multiplification of R G B or Luma channel to create B&W image
// TODO
return float4( color.xyz, 1.0f ); // Writes to texColorNew
}
float4 PS_DownscaleImg(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerColorNew, texcoord );
return float4( color.xyz, 1.0f ); // Writes to texColorNew
}
float4 PS_GaussianH(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBlurIn, texcoord );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float calcOffset = 0.0f;
float2 buffSigma = 0.0f;
float3 Sigma;
float bSigma;
#if( BW_GAUSSIAN_QUALITY == 0 )
bSigma = BlurSigma;
#endif
#if( BW_GAUSSIAN_QUALITY == 1 )
bSigma = BlurSigma * 0.75f;
#endif
#if( BW_GAUSSIAN_QUALITY == 2 )
bSigma = BlurSigma * 0.5f;
#endif
bSigma = bSigma * ( float( BUFFER_WIDTH ) / 1920.0 );
Sigma.x = 1.0f / ( sqrt( 2.0f * Pi ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
color.xyz *= Sigma.x;
SigmaSum += Sigma.x;
Sigma.xy *= Sigma.yz;
for( int i = 0; i < Loops && SigmaSum <= Quality; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2D( samplerBlurIn, texcoord.xy + float2( pxlOffset*px, 0.0f )) * buffSigma.y;
color += tex2D( samplerBlurIn, texcoord.xy - float2( pxlOffset*px, 0.0f )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color.xyz /= SigmaSum;
return float4( color.xyz, 1.0f ); // Writes to texBlurH
}
float4 PS_GaussianV(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBlurH, texcoord );
float SigmaSum = 0.0f;
float pxlOffset = 1.5f;
float calcOffset = 0.0f;
float2 buffSigma = 0.0f;
float3 Sigma;
float bSigma;
#if( BW_GAUSSIAN_QUALITY == 0 )
bSigma = BlurSigma;
#endif
#if( BW_GAUSSIAN_QUALITY == 1 )
bSigma = BlurSigma * 0.75f;
#endif
#if( BW_GAUSSIAN_QUALITY == 2 )
bSigma = BlurSigma * 0.5f;
#endif
bSigma = bSigma * ( float( BUFFER_WIDTH ) / 1920.0 );
Sigma.x = 1.0f / ( sqrt( 2.0f * Pi ) * bSigma );
Sigma.y = exp( -0.5f / ( bSigma * bSigma ));
Sigma.z = Sigma.y * Sigma.y;
color.xyz *= Sigma.x;
SigmaSum += Sigma.x;
Sigma.xy *= Sigma.yz;
for( int i = 0; i < Loops && SigmaSum < Quality; ++i )
{
buffSigma.x = Sigma.x * Sigma.y;
buffSigma.y = Sigma.x + buffSigma.x;
color += tex2D( samplerBlurH, texcoord.xy + float2( 0.0f, pxlOffset*py )) * buffSigma.y;
color += tex2D( samplerBlurH, texcoord.xy - float2( 0.0f, pxlOffset*py )) * buffSigma.y;
SigmaSum += ( 2.0f * Sigma.x + 2.0f * buffSigma.x );
pxlOffset += 2.0f;
Sigma.xy *= Sigma.yz;
Sigma.xy *= Sigma.yz;
}
color.xyz /= SigmaSum;
return float4( color.xyz, 1.0f ); // Writes to texBlur
}
#if( BW_ENABLE_DEBAND == 1 )
float4 PS_BloomDeband(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 color = tex2D( samplerBlur, texcoord );
float avgdiff = 3.4f / 255.0f;
float maxdiff = 6.8f / 255.0f;
float middiff = 3.3f / 255.0f;
float h = permute( permute( permute( texcoord.x ) + texcoord.y ) + drandom / 32767.0f );
float3 ref_avg;
float3 ref_avg_diff;
float3 ref_max_diff;
float3 ref_mid_diff1;
float3 ref_mid_diff2;
float3 ori = color.xyz;
float3 res;
float dir = rand( permute( h )) * 6.2831853f;
float2 o = float2( cos( dir ), sin( dir ));
float range = 6.0f / ( BW_GAUSSIAN_QUALITY + 1 );
for ( int i = 1; i <= 4; ++i )
{
float dist = rand(h) * range * i;
float2 pt = dist * float2( px, py );
analyze_pixels(ori, samplerBlur, texcoord, pt, o,
ref_avg,
ref_avg_diff,
ref_max_diff,
ref_mid_diff1,
ref_mid_diff2);
float3 ref_avg_diff_threshold = avgdiff * i;
float3 ref_max_diff_threshold = maxdiff * i;
float3 ref_mid_diff_threshold = middiff * i;
float3 factor = pow(saturate(3.0 * (1.0 - ref_avg_diff / ref_avg_diff_threshold)) *
saturate(3.0 * (1.0 - ref_max_diff / ref_max_diff_threshold)) *
saturate(3.0 * (1.0 - ref_mid_diff1 / ref_mid_diff_threshold)) *
saturate(3.0 * (1.0 - ref_mid_diff2 / ref_mid_diff_threshold)), 0.1);
res = lerp(ori, ref_avg, factor);
h = permute(h);
}
const float dither_bit = 8.0f;
float grid_position = frac(dot(texcoord, (float2( BUFFER_WIDTH, BUFFER_HEIGHT ) * float2(1.0 / 16.0, 10.0 / 36.0)) + 0.25));
float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0));
float3 dither_shift_RGB = float3(dither_shift, -dither_shift, dither_shift);
dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position.
res += dither_shift_RGB;
color.xyz = res.xyz;
return float4( color.xyz, 1.0f ); // Writes to texBlurDeband
}
#endif
float4 PS_BlendImgBlur(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
float4 bwcolor = tex2D( samplerColorNew, texcoord );
float4 bwblur = tex2D( samplerBlur, texcoord );
#if( BW_ENABLE_DEBAND == 1 )
bwblur.xyz = tex2D( samplerBlurDeband, texcoord ).xyz;
#endif
float4 orig = tex2D( samplerColor, texcoord );
float3 base;
float3 blend;
float3 ret;
float3 color;
/*
Color or Targets
0 = Original Color
1 = B&W Image
2 = B&W Gaussian Blur
*/
switch( basecolor_1 )
{
case 0:
base.xyz = orig.xyz;
break;
case 1:
base.xyz = bwcolor.xyz;
break;
case 2:
base.xyz = bwblur.xyz;
break;
default:
base.xyz = bwcolor.xyz;
break;
}
switch( blendcolor_1 )
{
case 0:
blend.xyz = orig.xyz;
break;
case 1:
blend.xyz = bwcolor.xyz;
break;
case 2:
blend.xyz = bwblur.xyz;
break;
default:
base.xyz = bwblur.xyz;
break;
}
ret.xyz = createBlend( base.xyz, blend.xyz, blendmode_1 );
color.xyz = lerp( base.xyz, ret.xyz, opacity_1 );
return float4( color.xyz, 1.0f ); // Final output
}
//// TECHNIQUES /////////////////////////////////////////////////////////////////
technique prod80_04_Black_and_White
{
pass prod80_BlackandWhite
{
VertexShader = PostProcessVS;
PixelShader = PS_BlackandWhite;
RenderTarget = texColorNew;
}
pass prod80_Downscale
{
VertexShader = PostProcessVS;
PixelShader = PS_DownscaleImg;
RenderTarget = texBlurIn;
}
pass prod80_BlurH
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianH;
RenderTarget = texBlurH;
}
pass prod80_Blur
{
VertexShader = PostProcessVS;
PixelShader = PS_GaussianV;
RenderTarget = texBlur;
}
#if( BW_ENABLE_DEBAND == 1 )
pass prod80_BlurDeband
{
VertexShader = PostProcessVS;
PixelShader = PS_BloomDeband;
RenderTarget = texBlurDeband;
}
#endif
pass prod80_Blend
{
VertexShader = PostProcessVS;
PixelShader = PS_BlendImgBlur;
}
}
}
You can get it here: github.com/prod80/prod80-ReShade-Reposit...80_04_BlacknWhite.fx
On Github you have the option to click on "Commits" (top left on the repository) and from there you can browse and view the repository at a specific point in time by clicking on the "<>" symbol behind an update (ie- before a shader was changed) and download previous versions if you wish.
The gaussian blur in the B&W shader didn't add much value for me, and the effect is very heavy. So I moved that one out, and moved the blending modes into Color Gradient shader. You can desaturate the base image from within that shader (same as old B&W shader) and run color effects over it. It only doesn't have the blur.
Please Log in or Create an account to join the conversation.
- klotim
prod80 wrote: Updated the dithering, using blue noise now for better results!
Added motion to the dither as well.
On update please download both shaders and textures folders, as it has a new texture (bluenoise.png) renamed the old gaussian texture (gaussnoise.png) and it has a helper file now for me to easily load the noise samplers into the files where I want to use them (PD80_00_Noise_Samplers.fxh) so they don't clutter my files or the UI
Enjoy
This is awesome, however, bluenoise.png is already used by marty mcfly and his ray tracing shader.
Could you by any chance rename it? Like PD80_blueNoise or something?
Please Log in or Create an account to join the conversation.
- prod80
- Topic Author
New ReShade installer is coming to fix these issues luckily.
It's fixed now. You can re-download.
Please Log in or Create an account to join the conversation.
- Tojkar
Other than that, your shaders became my most used ones immediately after you published them here, so good work on that! They are somewhat easier to configure for wanted results than most other similar shaders and the scope of them happens to be exactly what I want from color grading not including those changes in BW shader. The old BW is great for abusing it's settings and the new one is excellent on it's intended use.
BTW, those sweet words are sincere and not just an attempt to make you give what i want but if that helps, awesome! ;P
Please Log in or Create an account to join the conversation.