example data store
This commit is contained in:
152
shaders/feedback-data-blocks/shader.slang
Normal file
152
shaders/feedback-data-blocks/shader.slang
Normal file
@@ -0,0 +1,152 @@
|
||||
static const int kProbeCount = 8;
|
||||
static const int kMetadataIndex = 8;
|
||||
|
||||
float2 probeUvForIndex(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
return float2(0.18, 0.28);
|
||||
if (index == 1)
|
||||
return float2(0.39, 0.28);
|
||||
if (index == 2)
|
||||
return float2(0.61, 0.28);
|
||||
if (index == 3)
|
||||
return float2(0.82, 0.28);
|
||||
if (index == 4)
|
||||
return float2(0.18, 0.72);
|
||||
if (index == 5)
|
||||
return float2(0.39, 0.72);
|
||||
if (index == 6)
|
||||
return float2(0.61, 0.72);
|
||||
return float2(0.82, 0.72);
|
||||
}
|
||||
|
||||
float2 cellCenterPixelForIndex(int index)
|
||||
{
|
||||
return float2(1.0 + float(index) * 3.0, 1.0);
|
||||
}
|
||||
|
||||
float2 cellCenterUvForIndex(ShaderContext context, int index)
|
||||
{
|
||||
return (cellCenterPixelForIndex(index) + 0.5) / context.outputResolution;
|
||||
}
|
||||
|
||||
bool pixelIsInsideCell(float2 pixelCoord, int index)
|
||||
{
|
||||
float minX = float(index) * 3.0;
|
||||
float maxX = minX + 3.0;
|
||||
return pixelCoord.x >= minX && pixelCoord.x < maxX && pixelCoord.y >= 0.0 && pixelCoord.y < 3.0;
|
||||
}
|
||||
|
||||
float4 readStoredCell(ShaderContext context, int index)
|
||||
{
|
||||
if (context.feedbackAvailable <= 0)
|
||||
return float4(0.0, 0.0, 0.0, 0.0);
|
||||
return sampleFeedback(cellCenterUvForIndex(context, index));
|
||||
}
|
||||
|
||||
bool shouldRefreshStoredData(ShaderContext context)
|
||||
{
|
||||
if (context.feedbackAvailable <= 0)
|
||||
return true;
|
||||
|
||||
float4 metadata = readStoredCell(context, kMetadataIndex);
|
||||
float previousRefreshBucket = metadata.r;
|
||||
float previousTriggerCount = metadata.g;
|
||||
float refreshInterval = max(refreshSeconds, 0.001);
|
||||
float currentRefreshBucket = floor(context.time / refreshInterval);
|
||||
float currentTriggerCount = float(refresh);
|
||||
|
||||
return currentRefreshBucket > previousRefreshBucket + 0.5 || currentTriggerCount > previousTriggerCount + 0.5;
|
||||
}
|
||||
|
||||
float4 metadataValueForFrame(ShaderContext context, bool refreshNow)
|
||||
{
|
||||
float refreshInterval = max(refreshSeconds, 0.001);
|
||||
float currentRefreshBucket = floor(context.time / refreshInterval);
|
||||
float currentTriggerCount = float(refresh);
|
||||
|
||||
if (!refreshNow && context.feedbackAvailable > 0)
|
||||
return readStoredCell(context, kMetadataIndex);
|
||||
|
||||
return float4(currentRefreshBucket, currentTriggerCount, refreshTime, 1.0);
|
||||
}
|
||||
|
||||
float4 storedProbeValueForFrame(ShaderContext context, int index, bool refreshNow)
|
||||
{
|
||||
float3 liveColor = sampleLayerInput(probeUvForIndex(index)).rgb;
|
||||
if (refreshNow || context.feedbackAvailable <= 0)
|
||||
return float4(liveColor, 1.0);
|
||||
return readStoredCell(context, index);
|
||||
}
|
||||
|
||||
float4 storeProbeData(ShaderContext context)
|
||||
{
|
||||
// Reserve nine 3x3 texel cells along the top edge of the feedback surface:
|
||||
// eight cells for visible probe colors and one hidden metadata cell that
|
||||
// tracks the timed refresh bucket and last trigger count.
|
||||
float2 pixelCoord = floor(context.uv * context.outputResolution);
|
||||
bool refreshNow = shouldRefreshStoredData(context);
|
||||
|
||||
for (int index = 0; index < kProbeCount; ++index)
|
||||
{
|
||||
if (pixelIsInsideCell(pixelCoord, index))
|
||||
return storedProbeValueForFrame(context, index, refreshNow);
|
||||
}
|
||||
|
||||
if (pixelIsInsideCell(pixelCoord, kMetadataIndex))
|
||||
return metadataValueForFrame(context, refreshNow);
|
||||
|
||||
return float4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float rectMask(float2 uv, float2 minUv, float2 maxUv)
|
||||
{
|
||||
if (uv.x < minUv.x || uv.x > maxUv.x)
|
||||
return 0.0;
|
||||
if (uv.y < minUv.y || uv.y > maxUv.y)
|
||||
return 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float borderMask(float2 uv, float2 minUv, float2 maxUv, float thickness)
|
||||
{
|
||||
float outer = rectMask(uv, minUv, maxUv);
|
||||
float inner = rectMask(uv, minUv + thickness, maxUv - thickness);
|
||||
return saturate(outer - inner);
|
||||
}
|
||||
|
||||
float4 displayProbeData(ShaderContext context)
|
||||
{
|
||||
float3 baseColor = sampleLayerInput(context.uv).rgb;
|
||||
float3 swatchColor = baseColor;
|
||||
float swatchMask = 0.0;
|
||||
|
||||
float2 panelOrigin = float2(0.03, 0.04);
|
||||
float2 gap = float2(swatchSize.x + 0.012, swatchSize.y + 0.012);
|
||||
float borderThickness = min(swatchSize.x, swatchSize.y) * 0.08;
|
||||
|
||||
for (int index = 0; index < kProbeCount; ++index)
|
||||
{
|
||||
int column = index % 4;
|
||||
int row = index / 4;
|
||||
float2 swatchMin = panelOrigin + float2(float(column) * gap.x, float(row) * gap.y);
|
||||
float2 swatchMax = swatchMin + swatchSize;
|
||||
float3 storedColor = sampleVideo(cellCenterUvForIndex(context, index)).rgb;
|
||||
float fill = rectMask(context.uv, swatchMin, swatchMax);
|
||||
float outline = borderMask(context.uv, swatchMin, swatchMax, borderThickness);
|
||||
if (fill > 0.5)
|
||||
{
|
||||
swatchColor = storedColor;
|
||||
swatchMask = 1.0;
|
||||
}
|
||||
if (outline > 0.5)
|
||||
{
|
||||
swatchColor = float3(0.0, 0.0, 0.0);
|
||||
swatchMask = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
float opacity = saturate(overlayOpacity) * swatchMask;
|
||||
float3 displayColor = lerp(baseColor, swatchColor, opacity);
|
||||
return float4(saturate(displayColor), 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user