mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-27 09:51:30 +11:00
206 lines
6.3 KiB
C++
206 lines
6.3 KiB
C++
// Adjust to limited RGB
|
|
vec3 tv(vec3 Input)
|
|
{ return Input*((235.0-16.0)/255.0)+16.0/255.0; }
|
|
|
|
// Generate test grid
|
|
vec3 Grid(vec2 Coordinates, float AspectRatio)
|
|
{
|
|
// Grid settings
|
|
#ifndef BoxAmount
|
|
#define BoxAmount 31 // Number of boxes horizontally (choose odd number)
|
|
#endif
|
|
|
|
#ifndef thicknessA
|
|
#define thicknessA 0.25 // White grid thickness
|
|
#endif
|
|
|
|
#ifndef thicknessB
|
|
#define thicknessB 0.125 // Yellow cross thickness
|
|
#endif
|
|
|
|
#ifndef crossColor
|
|
#define crossColor vec3(1.0, 1.0, 0.0) // Center cross color (yellow)
|
|
#endif
|
|
|
|
bool RadialPattern = (SoloLines == 3);
|
|
|
|
vec2 GridCoord = Coordinates;
|
|
GridCoord.y -= 0.5; // Center coordinates vertically
|
|
GridCoord.y /= AspectRatio; // Correct aspect
|
|
GridCoord.y += 0.5; // Center at middle
|
|
|
|
vec2 CrossUV = GridCoord; // Store center cross coordinates
|
|
|
|
vec2 PixelSize; vec3 gridColor;
|
|
// Generate grid pattern
|
|
GridCoord = (RadialPattern) ? vec2(length(GridCoord-0.5)*1.618) : GridCoord; // Switch to radial pattern
|
|
GridCoord = abs(fract(GridCoord*BoxAmount)*2.0-1.0)*(thicknessA+1.0);
|
|
// Anti-aliased grid
|
|
PixelSize = fwidth(GridCoord.xy);
|
|
GridCoord = smoothstep(1.0-PixelSize, 1.0+PixelSize, GridCoord);
|
|
|
|
// Combine/solo vertical and horizontal lines
|
|
switch(SoloLines)
|
|
{
|
|
case 1:
|
|
{ gridColor = vec3(GridCoord.y); break; }
|
|
case 2:
|
|
{ gridColor = vec3(GridCoord.x); break; }
|
|
default:
|
|
{ gridColor = vec3(max(GridCoord.x, GridCoord.y)); break; }
|
|
};
|
|
|
|
// Generate center cross
|
|
CrossUV = 1.0-abs(CrossUV*2.0-1.0);
|
|
CrossUV = CrossUV*(thicknessB/BoxAmount+1.0);
|
|
// Anti-aliased cross
|
|
PixelSize = fwidth(CrossUV);
|
|
CrossUV = smoothstep(1.0-PixelSize, 1.0+PixelSize, CrossUV);
|
|
// Combine vertical and horizontal line
|
|
float CrossMask = max(CrossUV.y, CrossUV.x);
|
|
|
|
// Blend grid and center cross
|
|
gridColor = mix(gridColor, ((RadialPattern) ? vec3(1.0) : crossColor), vec3(CrossMask));
|
|
|
|
// Solo colors
|
|
if(SoloGreen) gridColor.b = 0.0;
|
|
if(SoloBlue) gridColor.g = 0.0;
|
|
|
|
// Reduce grid brightness
|
|
return tv(gridColor);
|
|
}
|
|
|
|
// Divide screen into two halfs
|
|
vec2 StereoVision(vec2 Coordinates, float Center)
|
|
{
|
|
vec2 StereoCoord = Coordinates;
|
|
StereoCoord.x = 0.25 + abs( StereoCoord.x*2.0-1.0 ) * 0.5; // Divide screen in two
|
|
StereoCoord.x -= mix(-0.25, 0.25, Center); // Change center for interpupillary distance (IPD)
|
|
// Mirror left half
|
|
float ScreenSide = step(0.5, Coordinates.x);
|
|
StereoCoord.x *= ScreenSide*2.0-1.0;
|
|
StereoCoord.x += 1.0 - ScreenSide;
|
|
return StereoCoord;
|
|
}
|
|
|
|
// Convert stereo coordinates to mono
|
|
vec2 InvStereoVision(vec2 Coordinates, int ScreenMask, float Center)
|
|
{
|
|
vec2 stereoCoord = Coordinates;
|
|
stereoCoord.x += Center*0.5 * ScreenMask;
|
|
return stereoCoord;
|
|
}
|
|
|
|
// Generate border mask with anti-aliasing from UV coordinates
|
|
float BorderMaskAA(vec2 Coordinates)
|
|
{
|
|
vec2 RaidalCoord = abs(Coordinates*2.0-1.0);
|
|
// Get pixel size in transformed coordinates (for anti-aliasing)
|
|
vec2 PixelSize = fwidth(RaidalCoord);
|
|
|
|
// Create borders mask (with anti-aliasing)
|
|
vec2 Borders = smoothstep(1.0-PixelSize, 1.0+PixelSize, RaidalCoord);
|
|
|
|
// Combine side and top borders
|
|
return max(Borders.x, Borders.y);
|
|
}
|
|
|
|
/*
|
|
// Can't really use this one as RetroArch can't access the depth buffer
|
|
float GetDepth(vec2 texcoord)
|
|
{
|
|
return ReShade::GetLinearizedDepth(texcoord);
|
|
}
|
|
|
|
|
|
// Horizontal parallax offset effect
|
|
vec2 Parallax(vec2 Coordinates, float Offset, float Center, int GapOffset, int Steps)
|
|
{
|
|
// Limit amount of loop steps to make it finite
|
|
#ifndef MaximumParallaxSteps
|
|
#def MaximumParallaxSteps 64
|
|
#endif
|
|
|
|
// Offset per step progress
|
|
float LayerDepth = 1.0 / min(MaximumParallaxSteps, Steps);
|
|
|
|
// Netto layer offset change
|
|
float deltaCoordinates = Offset * LayerDepth;
|
|
|
|
vec2 ParallaxCoord = Coordinates;
|
|
// Offset image horizontally so that parallax is in the depth appointed center
|
|
ParallaxCoord.x += Offset * Center;
|
|
float CurrentDepthMapValue = GetDepth(ParallaxCoord); // Replace function
|
|
|
|
// Steep parallax mapping
|
|
float CurrentLayerDepth = 0.0;
|
|
[loop]
|
|
while(CurrentLayerDepth < CurrentDepthMapValue)
|
|
{
|
|
// Shift coordinates horizontally in linear fasion
|
|
ParallaxCoord.x -= deltaCoordinates;
|
|
// Get depth value at current coordinates
|
|
CurrentDepthMapValue = GetDepth(ParallaxCoord); // Replace function
|
|
// Get depth of next layer
|
|
CurrentLayerDepth += LayerDepth;
|
|
continue;
|
|
}
|
|
|
|
// Parallax Occlusion Mapping
|
|
vec2 PrevParallaxCoord = ParallaxCoord;
|
|
PrevParallaxCoord.x += deltaCoordinates;
|
|
float afterDepthValue = CurrentDepthMapValue - CurrentLayerDepth;
|
|
float beforeDepthValue = GetDepth(PrevParallaxCoord); // Replace function
|
|
// Store depth read difference for masking
|
|
float DepthDifference = beforeDepthValue - CurrentDepthMapValue;
|
|
|
|
beforeDepthValue += LayerDepth - CurrentLayerDepth;
|
|
// Interpolate coordinates
|
|
float weight = afterDepthValue / (afterDepthValue - beforeDepthValue);
|
|
ParallaxCoord = PrevParallaxCoord * weight + ParallaxCoord * (1.0 - weight);
|
|
|
|
// Apply gap masking (by JMF)
|
|
DepthDifference *= GapOffset * Offset * 100.0;
|
|
DepthDifference *= ReShade::PixelSize.x; // Replace function
|
|
ParallaxCoord.x += DepthDifference;
|
|
|
|
return ParallaxCoord;
|
|
};
|
|
*/
|
|
|
|
// Lens projection model (algorithm by JMF)
|
|
float Orthographic(float rFOV, float R){ return tan(asin(sin(rFOV*0.5)*R))/(tan(rFOV*0.5)*R); }
|
|
float Equisolid(float rFOV, float R){ return tan(asin(sin(rFOV*0.25)*R)*2.0)/(tan(rFOV*0.5)*R); }
|
|
float Equidistant(float rFOV, float R){ return tan(R*rFOV*0.5)/(tan(rFOV*0.5)*R); }
|
|
float Stereographic(float rFOV, float R){ return tan(atan(tan(rFOV*0.25)*R)*2.0)/(tan(rFOV*0.5)*R); }
|
|
|
|
// Brown-Conrady radial distortion model (multiply by coordinates)
|
|
float kRadial(float R2, float K1, float K2, float K3, float K4)
|
|
{ return 1.0 + K1*R2 + K2*pow(R2,2) + K3*pow(R2,4) + K4*pow(R2,6); }
|
|
|
|
// Brown-Conrady tangental distortion model (add to coordinates)
|
|
vec2 pTangental(vec2 Coord, float R2, float P1, float P2, float P3, float P4)
|
|
{
|
|
return vec2(
|
|
(P1*(R2+pow(Coord.x,2)*2.0)+2.0*P2*Coord.x*Coord.y)*(1.0+P3*R2+P4*pow(R2,2)),
|
|
(P2*(R2+pow(Coord.y,2)*2.0)+2.0*P1*Coord.x*Coord.y)*(1.0+P3*R2+P4*pow(R2,2))
|
|
);
|
|
}
|
|
|
|
// RGB to YUV709.luma
|
|
float Luma(vec3 Input)
|
|
{
|
|
const vec3 Luma709 = vec3(0.2126, 0.7152, 0.0722);
|
|
return dot(Input, Luma709);
|
|
}
|
|
|
|
// Overlay blending mode
|
|
float Overlay(float LayerA, float LayerB)
|
|
{
|
|
float MinA = min(LayerA, 0.5);
|
|
float MinB = min(LayerB, 0.5);
|
|
float MaxA = max(LayerA, 0.5);
|
|
float MaxB = max(LayerB, 0.5);
|
|
return 2.0 * (MinA * MinB + MaxA + MaxB - MaxA * MaxB) - 1.5;
|
|
}
|