2023-09-23 14:39:09 +06:00

410 lines
15 KiB
HLSL

/*=============================================================================
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;
}
}