Transparency
This commit is contained in:
@@ -320,10 +320,14 @@ bool OpenGLComposite::InitDeckLink()
|
|||||||
BSTR modelNameBstr = NULL;
|
BSTR modelNameBstr = NULL;
|
||||||
if (deckLinkAttributes->GetString(BMDDeckLinkModelName, &modelNameBstr) == S_OK && modelNameBstr != NULL)
|
if (deckLinkAttributes->GetString(BMDDeckLinkModelName, &modelNameBstr) == S_OK && modelNameBstr != NULL)
|
||||||
{
|
{
|
||||||
_bstr_t modelNameWrapper(modelNameBstr, false);
|
const int requiredBytes = WideCharToMultiByte(CP_UTF8, 0, modelNameBstr, -1, NULL, 0, NULL, NULL);
|
||||||
const char* modelNameChars = modelNameWrapper;
|
if (requiredBytes > 1)
|
||||||
if (modelNameChars != NULL)
|
{
|
||||||
modelName = modelNameChars;
|
std::vector<char> utf8Name(static_cast<std::size_t>(requiredBytes), '\0');
|
||||||
|
if (WideCharToMultiByte(CP_UTF8, 0, modelNameBstr, -1, utf8Name.data(), requiredBytes, NULL, NULL) > 0)
|
||||||
|
modelName.assign(utf8Name.data());
|
||||||
|
}
|
||||||
|
SysFreeString(modelNameBstr);
|
||||||
}
|
}
|
||||||
deckLinkAttributes->Release();
|
deckLinkAttributes->Release();
|
||||||
deckLinkAttributes = NULL;
|
deckLinkAttributes = NULL;
|
||||||
@@ -525,6 +529,13 @@ bool OpenGLComposite::InitDeckLink()
|
|||||||
error:
|
error:
|
||||||
if (!bSuccess)
|
if (!bSuccess)
|
||||||
{
|
{
|
||||||
|
if (mDLKeyer != NULL)
|
||||||
|
{
|
||||||
|
mDLKeyer->Disable();
|
||||||
|
mDLKeyer->Release();
|
||||||
|
mDLKeyer = NULL;
|
||||||
|
mDeckLinkExternalKeyingActive = false;
|
||||||
|
}
|
||||||
if (mDLInput != NULL)
|
if (mDLInput != NULL)
|
||||||
{
|
{
|
||||||
mDLInput->Release();
|
mDLInput->Release();
|
||||||
@@ -990,6 +1001,23 @@ bool OpenGLComposite::Stop()
|
|||||||
if (mControlServer)
|
if (mControlServer)
|
||||||
mControlServer->Stop();
|
mControlServer->Stop();
|
||||||
|
|
||||||
|
if (mDLKeyer != NULL)
|
||||||
|
{
|
||||||
|
mDLKeyer->Disable();
|
||||||
|
mDeckLinkExternalKeyingActive = false;
|
||||||
|
if (mRuntimeHost)
|
||||||
|
{
|
||||||
|
mRuntimeHost->SetDeckLinkOutputStatus(
|
||||||
|
mDeckLinkOutputModelName,
|
||||||
|
mDeckLinkSupportsInternalKeying,
|
||||||
|
mDeckLinkSupportsExternalKeying,
|
||||||
|
mDeckLinkKeyerInterfaceAvailable,
|
||||||
|
mRuntimeHost->ExternalKeyingEnabled(),
|
||||||
|
mDeckLinkExternalKeyingActive,
|
||||||
|
"External keying has been disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mDLInput->StopStreams();
|
mDLInput->StopStreams();
|
||||||
mDLInput->DisableVideoInput();
|
mDLInput->DisableVideoInput();
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"shaderLibrary": "shaders",
|
"shaderLibrary": "shaders",
|
||||||
"serverPort": 8080,
|
"serverPort": 8080,
|
||||||
"autoReload": true,
|
"autoReload": true,
|
||||||
"maxTemporalHistoryFrames": 12
|
"maxTemporalHistoryFrames": 12,
|
||||||
|
"enableExternalKeying": true
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
shaders/dvd-bounce/DVD_Logo.png
Normal file
BIN
shaders/dvd-bounce/DVD_Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
54
shaders/dvd-bounce/shader.json
Normal file
54
shaders/dvd-bounce/shader.json
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"id": "dvd-bounce",
|
||||||
|
"name": "DVD Bounce",
|
||||||
|
"description": "A transparent DVD-style logo that bounces endlessly and changes color on each screen hit.",
|
||||||
|
"category": "Built-in",
|
||||||
|
"entryPoint": "shadeVideo",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"id": "logoScale",
|
||||||
|
"label": "Logo Scale",
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.28,
|
||||||
|
"min": 0.12,
|
||||||
|
"max": 0.5,
|
||||||
|
"step": 0.01
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bounceSpeed",
|
||||||
|
"label": "Bounce Speed",
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.22,
|
||||||
|
"min": 0.02,
|
||||||
|
"max": 0.8,
|
||||||
|
"step": 0.01
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "edgePadding",
|
||||||
|
"label": "Edge Padding",
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.018,
|
||||||
|
"min": 0.0,
|
||||||
|
"max": 0.08,
|
||||||
|
"step": 0.001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "glowAmount",
|
||||||
|
"label": "Glow",
|
||||||
|
"type": "float",
|
||||||
|
"default": 0.18,
|
||||||
|
"min": 0.0,
|
||||||
|
"max": 0.75,
|
||||||
|
"step": 0.01
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "baseAlpha",
|
||||||
|
"label": "Alpha",
|
||||||
|
"type": "float",
|
||||||
|
"default": 1.0,
|
||||||
|
"min": 0.05,
|
||||||
|
"max": 1.0,
|
||||||
|
"step": 0.01
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
116
shaders/dvd-bounce/shader.slang
Normal file
116
shaders/dvd-bounce/shader.slang
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
float sdBox(float2 p, float2 b)
|
||||||
|
{
|
||||||
|
float2 d = abs(p) - b;
|
||||||
|
return length(max(d, float2(0.0, 0.0))) + min(max(d.x, d.y), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdRoundedBox(float2 p, float2 b, float r)
|
||||||
|
{
|
||||||
|
return sdBox(p, b - r) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdSegment(float2 p, float2 a, float2 b)
|
||||||
|
{
|
||||||
|
float2 pa = p - a;
|
||||||
|
float2 ba = b - a;
|
||||||
|
float h = saturate(dot(pa, ba) / max(dot(ba, ba), 0.0001));
|
||||||
|
return length(pa - ba * h);
|
||||||
|
}
|
||||||
|
|
||||||
|
float pingPong(float x, float lengthValue)
|
||||||
|
{
|
||||||
|
float safeLength = max(lengthValue, 0.0001);
|
||||||
|
float period = safeLength * 2.0;
|
||||||
|
float wrapped = x - floor(x / period) * period;
|
||||||
|
return wrapped <= safeLength ? wrapped : (period - wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 hsvToRgb(float3 hsv)
|
||||||
|
{
|
||||||
|
float3 p = abs(frac(hsv.x + float3(0.0, 0.6666667, 0.3333333)) * 6.0 - 3.0);
|
||||||
|
float3 rgb = saturate(p - 1.0);
|
||||||
|
return hsv.z * lerp(float3(1.0, 1.0, 1.0), rgb, hsv.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float letterD(float2 p, float scale)
|
||||||
|
{
|
||||||
|
float2 offset = p;
|
||||||
|
float stem = sdBox(offset + float2(scale * 0.18, 0.0), float2(scale * 0.065, scale * 0.47));
|
||||||
|
float outer = sdRoundedBox(offset + float2(scale * 0.03, 0.0), float2(scale * 0.30, scale * 0.47), scale * 0.23);
|
||||||
|
float inner = sdRoundedBox(offset + float2(scale * 0.11, 0.0), float2(scale * 0.15, scale * 0.24), scale * 0.12);
|
||||||
|
float bowl = max(outer, -inner);
|
||||||
|
return min(stem, bowl);
|
||||||
|
}
|
||||||
|
|
||||||
|
float letterV(float2 p, float scale)
|
||||||
|
{
|
||||||
|
float leftStroke = sdSegment(p, float2(-scale * 0.30, -scale * 0.48), float2(0.0, scale * 0.48)) - scale * 0.085;
|
||||||
|
float rightStroke = sdSegment(p, float2(scale * 0.30, -scale * 0.48), float2(0.0, scale * 0.48)) - scale * 0.085;
|
||||||
|
return min(leftStroke, rightStroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
float logoLetters(float2 p, float scale)
|
||||||
|
{
|
||||||
|
float left = letterD(p + float2(scale * 0.92, 0.0), scale);
|
||||||
|
float middle = letterV(p, scale);
|
||||||
|
float right = letterD(p - float2(scale * 0.92, 0.0), scale);
|
||||||
|
return min(left, min(middle, right));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 shadeVideo(ShaderContext context)
|
||||||
|
{
|
||||||
|
float2 resolution = max(context.outputResolution, float2(1.0, 1.0));
|
||||||
|
float minDimension = min(resolution.x, resolution.y);
|
||||||
|
|
||||||
|
float safeScale = max(logoScale, 0.05);
|
||||||
|
float2 logoHalfSize = float2(minDimension * safeScale * 0.82, minDimension * safeScale * 0.28);
|
||||||
|
float2 paddingPx = float2(minDimension * max(edgePadding, 0.0), minDimension * max(edgePadding, 0.0));
|
||||||
|
float2 minCenterPx = logoHalfSize + paddingPx;
|
||||||
|
float2 maxCenterPx = resolution - logoHalfSize - paddingPx;
|
||||||
|
float2 travelPx = max(maxCenterPx - minCenterPx, float2(1.0, 1.0));
|
||||||
|
|
||||||
|
float2 velocityPx = float2(
|
||||||
|
max(20.0, bounceSpeed * minDimension * 1.00),
|
||||||
|
max(24.0, bounceSpeed * minDimension * 0.77));
|
||||||
|
float2 motionPx = context.time * velocityPx;
|
||||||
|
float2 centerPx = minCenterPx + float2(
|
||||||
|
pingPong(motionPx.x, travelPx.x),
|
||||||
|
pingPong(motionPx.y, travelPx.y));
|
||||||
|
|
||||||
|
int xHits = int(floor(motionPx.x / max(travelPx.x, 1.0)));
|
||||||
|
int yHits = int(floor(motionPx.y / max(travelPx.y, 1.0)));
|
||||||
|
int totalHits = max(0, xHits + yHits);
|
||||||
|
|
||||||
|
float hue = frac(0.09 + float(totalHits) * 0.173);
|
||||||
|
float3 badgeColor = hsvToRgb(float3(hue, 0.86, 1.0));
|
||||||
|
float3 glowColor = hsvToRgb(float3(frac(hue + 0.06), 0.72, 1.0));
|
||||||
|
|
||||||
|
float2 fragPx = context.uv * resolution;
|
||||||
|
float2 p = fragPx - centerPx;
|
||||||
|
|
||||||
|
float badgeDist = sdRoundedBox(p, logoHalfSize, logoHalfSize.y * 0.42);
|
||||||
|
float innerBadgeDist = sdRoundedBox(p, logoHalfSize - float2(minDimension * 0.012, minDimension * 0.012), logoHalfSize.y * 0.34);
|
||||||
|
|
||||||
|
float letterScale = logoHalfSize.y * 0.88;
|
||||||
|
float letterDist = logoLetters(p, letterScale);
|
||||||
|
|
||||||
|
float aa = 1.5;
|
||||||
|
float badgeMask = 1.0 - smoothstep(0.0, aa, badgeDist);
|
||||||
|
float rimMask = 1.0 - smoothstep(0.0, aa, abs(badgeDist + minDimension * 0.01));
|
||||||
|
float innerShade = 1.0 - smoothstep(0.0, aa, innerBadgeDist);
|
||||||
|
float lettersMask = 1.0 - smoothstep(0.0, aa, letterDist);
|
||||||
|
float glowMask = (1.0 - smoothstep(0.0, minDimension * 0.04, badgeDist)) * glowAmount;
|
||||||
|
|
||||||
|
float3 color = float3(0.0, 0.0, 0.0);
|
||||||
|
color += glowColor * glowMask * 0.55;
|
||||||
|
color = lerp(color, badgeColor * 0.95, badgeMask);
|
||||||
|
color = lerp(color, badgeColor * 0.55 + float3(0.08, 0.08, 0.1), innerShade * 0.35);
|
||||||
|
color = lerp(color, float3(1.0, 1.0, 1.0), rimMask * 0.8);
|
||||||
|
color = lerp(color, float3(0.98, 0.99, 1.0), lettersMask);
|
||||||
|
|
||||||
|
float alpha = max(badgeMask, glowMask * 0.45);
|
||||||
|
alpha = max(alpha, lettersMask);
|
||||||
|
alpha *= saturate(baseAlpha);
|
||||||
|
|
||||||
|
return float4(saturate(color), saturate(alpha));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user