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

474 lines
16 KiB
HLSL

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