mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-30 03:11:31 +11:00
197 lines
5.7 KiB
Plaintext
197 lines
5.7 KiB
Plaintext
#version 450
|
|
|
|
// license:BSD-3-Clause
|
|
// copyright-holders:Ryan Holtz,ImJezze
|
|
//-----------------------------------------------------------------------------
|
|
// Shadowmask Effect
|
|
//-----------------------------------------------------------------------------
|
|
|
|
layout(push_constant) uniform Push
|
|
{
|
|
vec4 SourceSize;
|
|
vec4 OriginalSize;
|
|
vec4 OutputSize;
|
|
uint FrameCount;
|
|
} params;
|
|
|
|
#include "mame_parameters.inc"
|
|
|
|
#define TargetDims params.OutputSize.xy
|
|
#define SourceDims params.OriginalSize.xy
|
|
float TargetScale = 1.0;//max(TargetDims.x / SourceDims.x, TargetDims.y / SourceDims.y);
|
|
|
|
float HumBarAlpha = global.humbaralpha;
|
|
float TimeMilliseconds = float(mod(params.FrameCount, 1000));
|
|
vec3 BackColor = vec3(global.backcolor_r, global.backcolor_g, global.backcolor_b);
|
|
int ShadowTileMode = int(global.shadowtilemode); // 0 based on screen (quad) dimension, 1 based on source dimension
|
|
float ShadowAlpha = global.shadowalpha;
|
|
vec2 ShadowCount = vec2(global.shadowcount_x, global.shadowcount_y);
|
|
vec2 ShadowUV = vec2(global.shadowuv_x, global.shadowuv_y);
|
|
vec2 ShadowDims = vec2(global.mask_width, global.mask_height);
|
|
vec2 ShadowUVOffset = vec2(global.mask_offset_x, global.mask_offset_y);
|
|
int ChromaMode = int(global.chromamode);
|
|
vec3 ConversionGain = vec3(global.conversiongain_x, global.conversiongain_y, global.conversiongain_z);
|
|
vec3 Power = vec3(global.power_r, global.power_g, global.power_b);
|
|
vec3 Floor = vec3(global.floor_r, global.floor_g, global.floor_b);
|
|
bool PrepareBloom = bool(global.preparebloom);
|
|
|
|
#define MONOCHROME 1
|
|
#define DICHROME 2
|
|
#define TRICHROME 3
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constants
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const float PI = 3.1415927;
|
|
const float HalfPI = PI * 0.5;
|
|
|
|
float HumBarDesync = 60.0 / 59.94 - 1.0; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC)
|
|
|
|
vec2 GetAdjustedCoords(vec2 coord)
|
|
{
|
|
// center coordinates
|
|
coord -= 0.5;
|
|
|
|
// apply screen scale
|
|
coord *= ScreenScale;
|
|
|
|
// un-center coordinates
|
|
coord += 0.5;
|
|
|
|
// apply screen offset
|
|
coord += ScreenOffset;
|
|
|
|
return coord;
|
|
}
|
|
|
|
vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord)
|
|
{
|
|
// base-target dimensions (without oversampling)
|
|
vec2 BaseTargetDims = TargetDims / TargetScale;
|
|
BaseTargetDims = SwapXY
|
|
? BaseTargetDims.yx
|
|
: BaseTargetDims.xy;
|
|
|
|
vec2 canvasCoord = ShadowTileMode == 0
|
|
? TargetCoord + ShadowUVOffset / BaseTargetDims
|
|
: SourceCoord + ShadowUVOffset / SourceDims;
|
|
vec2 canvasTexelDims = ShadowTileMode == 0
|
|
? 1.0 / BaseTargetDims
|
|
: 1.0 / SourceDims;
|
|
|
|
vec2 shadowDims = ShadowDims;
|
|
vec2 shadowUV = ShadowUV;
|
|
vec2 shadowCount = ShadowCount;
|
|
|
|
// swap x/y in screen mode (not source mode)
|
|
canvasCoord = ShadowTileMode == 0 && SwapXY
|
|
? canvasCoord.yx
|
|
: canvasCoord.xy;
|
|
|
|
// swap x/y in screen mode (not source mode)
|
|
shadowCount = ShadowTileMode == 0 && SwapXY
|
|
? shadowCount.yx
|
|
: shadowCount.xy;
|
|
|
|
vec2 shadowTile = canvasTexelDims * shadowCount;
|
|
|
|
vec2 shadowFrac = fract(canvasCoord / shadowTile);
|
|
|
|
// swap x/y in screen mode (not source mode)
|
|
shadowFrac = ShadowTileMode == 0 && SwapXY
|
|
? shadowFrac.yx
|
|
: shadowFrac.xy;
|
|
|
|
vec2 shadowCoord = (shadowFrac * shadowUV);
|
|
shadowCoord += ShadowTileMode == 0
|
|
? vec2(0.5) * (vec2(1.0) / shadowDims) // fix half texel offset (DX9)
|
|
: vec2(0.0);
|
|
|
|
return shadowCoord;
|
|
}
|
|
|
|
#pragma stage vertex
|
|
layout(location = 0) in vec4 Position;
|
|
layout(location = 1) in vec2 TexCoord;
|
|
layout(location = 0) out vec2 vTexCoord;
|
|
|
|
void main()
|
|
{
|
|
gl_Position = global.MVP * Position;
|
|
vTexCoord = TexCoord;
|
|
}
|
|
|
|
#pragma stage fragment
|
|
layout(location = 0) in vec2 vTexCoord;
|
|
layout(location = 0) out vec4 FragColor;
|
|
layout(set = 0, binding = 2) uniform sampler2D Source;
|
|
layout(set = 0, binding = 3) uniform sampler2D MaskTexture;
|
|
|
|
#define DiffuseSampler Source
|
|
#define ShadowSampler MaskTexture
|
|
//#define ScreenCoord vTexCoord
|
|
|
|
void main()
|
|
{
|
|
vec2 ScreenCoord = vTexCoord;
|
|
vec2 BaseCoord = GetAdjustedCoords(ScreenCoord);
|
|
|
|
// Color
|
|
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
|
|
BaseColor.a = 1.0;
|
|
/*
|
|
// clip border
|
|
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 ||
|
|
BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
|
|
{
|
|
// we don't use the clip function, because we don't clear the render target before
|
|
return vec4(0.0, 0.0, 0.0, 1.0);
|
|
}
|
|
*/
|
|
// Color Compression (may not affect bloom)
|
|
if (!PrepareBloom)
|
|
{
|
|
// increasing the floor of the signal without affecting the ceiling
|
|
BaseColor.rgb = Floor + (1.0f - Floor) * BaseColor.rgb;
|
|
}
|
|
|
|
// Color Power (may affect bloom)
|
|
BaseColor.r = pow(BaseColor.r, Power.r);
|
|
BaseColor.g = pow(BaseColor.g, Power.g);
|
|
BaseColor.b = pow(BaseColor.b, Power.b);
|
|
|
|
// Hum Bar Simulation (may not affect vector screen)
|
|
if (!PrepareBloom && !VectorScreen && HumBarAlpha > 0.0)
|
|
{
|
|
float HumBarStep = fract(TimeMilliseconds * HumBarDesync);
|
|
float HumBarBrightness = 1.0 - fract(BaseCoord.y + HumBarStep) * HumBarAlpha;
|
|
BaseColor.rgb *= HumBarBrightness;
|
|
}
|
|
|
|
// Mask Simulation (may not affect bloom)
|
|
if (!PrepareBloom && ShadowAlpha > 0.0)
|
|
{
|
|
vec2 ShadowCoord = GetShadowCoord(ScreenCoord, BaseCoord);
|
|
|
|
vec4 ShadowColor = texture(ShadowSampler, ShadowCoord);
|
|
vec3 ShadowMaskColor = mix(vec3(1.0), ShadowColor.rgb, ShadowAlpha);
|
|
float ShadowMaskClear = (1.0 - ShadowColor.a) * ShadowAlpha;
|
|
|
|
// apply shadow mask color
|
|
BaseColor.rgb *= ShadowMaskColor;
|
|
// clear shadow mask by background color
|
|
BaseColor.rgb = mix(BaseColor.rgb, BackColor, ShadowMaskClear);
|
|
}
|
|
|
|
// Preparation for phosphor color conversion
|
|
if (ChromaMode == MONOCHROME) {
|
|
BaseColor.r = dot(ConversionGain, BaseColor.rgb);
|
|
BaseColor.gb = vec2(BaseColor.r, BaseColor.r);
|
|
} else if (ChromaMode == DICHROME) {
|
|
BaseColor.r = dot(ConversionGain.rg, BaseColor.rg);
|
|
BaseColor.g = BaseColor.r;
|
|
}
|
|
|
|
FragColor = BaseColor;
|
|
} |