Transparency
This commit is contained in:
@@ -320,10 +320,14 @@ bool OpenGLComposite::InitDeckLink()
|
||||
BSTR modelNameBstr = NULL;
|
||||
if (deckLinkAttributes->GetString(BMDDeckLinkModelName, &modelNameBstr) == S_OK && modelNameBstr != NULL)
|
||||
{
|
||||
_bstr_t modelNameWrapper(modelNameBstr, false);
|
||||
const char* modelNameChars = modelNameWrapper;
|
||||
if (modelNameChars != NULL)
|
||||
modelName = modelNameChars;
|
||||
const int requiredBytes = WideCharToMultiByte(CP_UTF8, 0, modelNameBstr, -1, NULL, 0, NULL, NULL);
|
||||
if (requiredBytes > 1)
|
||||
{
|
||||
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 = NULL;
|
||||
@@ -525,6 +529,13 @@ bool OpenGLComposite::InitDeckLink()
|
||||
error:
|
||||
if (!bSuccess)
|
||||
{
|
||||
if (mDLKeyer != NULL)
|
||||
{
|
||||
mDLKeyer->Disable();
|
||||
mDLKeyer->Release();
|
||||
mDLKeyer = NULL;
|
||||
mDeckLinkExternalKeyingActive = false;
|
||||
}
|
||||
if (mDLInput != NULL)
|
||||
{
|
||||
mDLInput->Release();
|
||||
@@ -990,6 +1001,23 @@ bool OpenGLComposite::Stop()
|
||||
if (mControlServer)
|
||||
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->DisableVideoInput();
|
||||
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"shaderLibrary": "shaders",
|
||||
"serverPort": 8080,
|
||||
"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