diff --git a/shaders/greenscreen-key/shader.json b/shaders/greenscreen-key/shader.json new file mode 100644 index 0000000..500211f --- /dev/null +++ b/shaders/greenscreen-key/shader.json @@ -0,0 +1,90 @@ +{ + "id": "greenscreen-key", + "name": "Greenscreen Key", + "description": "Keys out a green screen background and outputs transparent alpha for compositing.", + "category": "Built-in", + "entryPoint": "shadeVideo", + "parameters": [ + { + "id": "screenColor", + "label": "Screen Color", + "type": "color", + "default": [0.15, 0.85, 0.2, 1.0], + "min": [0.0, 0.0, 0.0, 0.0], + "max": [1.0, 1.0, 1.0, 1.0], + "step": [0.01, 0.01, 0.01, 0.01] + }, + { + "id": "threshold", + "label": "Threshold", + "type": "float", + "default": 0.24, + "min": 0.01, + "max": 0.8, + "step": 0.005 + }, + { + "id": "softness", + "label": "Softness", + "type": "float", + "default": 0.12, + "min": 0.001, + "max": 0.5, + "step": 0.005 + }, + { + "id": "edgeSoftness", + "label": "Edge Softness", + "type": "float", + "default": 0.08, + "min": 0.0, + "max": 0.4, + "step": 0.005 + }, + { + "id": "erodeDilate", + "label": "Erode/Dilate", + "type": "float", + "default": 0.0, + "min": -0.3, + "max": 0.3, + "step": 0.005 + }, + { + "id": "despill", + "label": "Despill", + "type": "float", + "default": 0.45, + "min": 0.0, + "max": 1.5, + "step": 0.01 + }, + { + "id": "edgeBoost", + "label": "Edge Boost", + "type": "float", + "default": 0.08, + "min": -0.2, + "max": 0.3, + "step": 0.005 + }, + { + "id": "clipBlack", + "label": "Clip Black", + "type": "float", + "default": 0.0, + "min": 0.0, + "max": 0.5, + "step": 0.005 + }, + { + "id": "clipWhite", + "label": "Clip White", + "type": "float", + "default": 1.0, + "min": 0.5, + "max": 1.0, + "step": 0.005 + } + ] +} diff --git a/shaders/greenscreen-key/shader.slang b/shaders/greenscreen-key/shader.slang new file mode 100644 index 0000000..646ae5b --- /dev/null +++ b/shaders/greenscreen-key/shader.slang @@ -0,0 +1,40 @@ +float3 safeNormalize(float3 value) +{ + float len = max(length(value), 0.0001); + return value / len; +} + +float luma709(float3 color) +{ + return dot(color, float3(0.2126, 0.7152, 0.0722)); +} + +float4 shadeVideo(ShaderContext context) +{ + float4 src = context.sourceColor; + float3 color = saturate(src.rgb); + + float3 keyColor = safeNormalize(max(screenColor.rgb, float3(0.0001, 0.0001, 0.0001))); + float3 sampleColor = safeNormalize(max(color, float3(0.0001, 0.0001, 0.0001))); + + float chromaDistance = length(sampleColor - keyColor); + float matteCenter = threshold - erodeDilate; + float matteFeather = max(softness + edgeSoftness, 0.0005); + float alpha = smoothstep(matteCenter - matteFeather, matteCenter + matteFeather, chromaDistance); + + alpha = saturate((alpha - clipBlack) / max(clipWhite - clipBlack, 0.0001)); + alpha = saturate(alpha + edgeBoost); + + float greenExcess = max(0.0, color.g - max(color.r, color.b)); + float spillReduction = greenExcess * despill; + + float3 despilled = color; + despilled.g = max(0.0, despilled.g - spillReduction); + + float neutral = luma709(despilled); + despilled.rb += spillReduction * 0.25; + despilled = lerp(float3(neutral, neutral, neutral), despilled, 0.92); + + float3 premultiplied = saturate(despilled) * alpha; + return float4(premultiplied, alpha); +} diff --git a/shaders/temporal-low-fps/shader.json b/shaders/temporal-low-fps/shader.json index d25ba51..a2d10ec 100644 --- a/shaders/temporal-low-fps/shader.json +++ b/shaders/temporal-low-fps/shader.json @@ -6,7 +6,7 @@ "entryPoint": "shadeVideo", "temporal": { "enabled": true, - "historySource": "source", + "historySource": "preLayerInput", "historyLength": 8 }, "parameters": [ diff --git a/shaders/temporal-low-fps/shader.slang b/shaders/temporal-low-fps/shader.slang index d10e289..4c679fd 100644 --- a/shaders/temporal-low-fps/shader.slang +++ b/shaders/temporal-low-fps/shader.slang @@ -8,8 +8,8 @@ float4 shadeVideo(ShaderContext context) int lowerPhase = int(context.frameCount) % lowerHoldLength; int upperPhase = int(context.frameCount) % upperHoldLength; - float4 lowerHeld = lowerPhase == 0 ? context.sourceColor : sampleSourceHistory(lowerPhase - 1, context.uv); - float4 upperHeld = upperPhase == 0 ? context.sourceColor : sampleSourceHistory(upperPhase - 1, context.uv); + float4 lowerHeld = lowerPhase == 0 ? context.sourceColor : sampleTemporalHistory(lowerPhase - 1, context.uv); + float4 upperHeld = upperPhase == 0 ? context.sourceColor : sampleTemporalHistory(upperPhase - 1, context.uv); float4 held = lerp(lowerHeld, upperHeld, fractional); return lerp(context.sourceColor, held, clamp(blendAmount, 0.0, 1.0)); }