/*
==========================================================================================
Cg Acceleration Research
Optimized: Edgar Velázquez-Armendáriz - edgar [at] graphics [dot] cornell [dot] edu
Original: Eugene Lee (el77 [at] cornell [dot] edu)
------------------------------------------------------------------------------------------
Interpolation5.cg
Performs edge-respecting 5x5 interpolation.
==========================================================================================
*/
// This version: # 214 instructions, 25 R-regs, 9 H-regs
// Original: # 325 instructions, 2 R-regs, 9 H-regs
// Time: 6.3 ms
half4 Interpolation5(in half2 pos : WPOS,
const uniform samplerRECT reachability,
const uniform samplerRECT colorImage,
const uniform samplerRECT prioritySeqnum,
const uniform samplerRECT priorityTable) : COLOR
{
half modulator, centerModulator, weight = 0;
half3 selfColor;
half3 averageColor = float3(0, 0, 0);
half3 reach = round(texRECT(reachability, pos).rgb * 255);
half3 color = float3(0, 0, 0);
half3 rNeighbors[8];
half3 gNeighbors[8];
half3 bNeighbors[8];
half3 rWeights[8];
half3 gWeights[8];
half3 bWeights[8];
rWeights[0] = 1h;
rWeights[1] = 1h;
rWeights[2] = 1h;
rWeights[3] = 1h;
rWeights[4] = 1h;
rWeights[5] = 1h;
rWeights[6] = 4h;
rWeights[7] = 8h;
gWeights[0] = 4h;
gWeights[1] = 1h;
gWeights[2] = 1h;
gWeights[3] = 8h;
// 8h;
gWeights[4] = 8h;
gWeights[5] = 1h;
gWeights[6] = 1h;
gWeights[7] = 4h;
bWeights[0] = 8h;
bWeights[1] = 4h;
bWeights[2] = 1h;
bWeights[3] = 1h;
bWeights[4] = 1h;
bWeights[5] = 1h;
bWeights[6] = 1h;
bWeights[7] = 1h;
rNeighbors[0] = texRECT(colorImage, pos.xy + half2(-2, -2)).rgb;
rNeighbors[1] = texRECT(colorImage, pos.xy + half2(-1, -2)).rgb;
rNeighbors[2] = texRECT(colorImage, pos.xy + half2( 0, -2)).rgb;
rNeighbors[3] = texRECT(colorImage, pos.xy + half2( 1, -2)).rgb;
rNeighbors[4] = texRECT(colorImage, pos.xy + half2( 2, -2)).rgb;
rNeighbors[5] = texRECT(colorImage, pos.xy + half2(-2, -1)).rgb;
rNeighbors[6] = texRECT(colorImage, pos.xy + half2(-1, -1)).rgb;
rNeighbors[7] = texRECT(colorImage, pos.xy + half2( 0, -1)).rgb;
gNeighbors[0] = texRECT(colorImage, pos.xy + half2( 1, -1)).rgb;
gNeighbors[1] = texRECT(colorImage, pos.xy + half2( 2, -1)).rgb;
gNeighbors[2] = texRECT(colorImage, pos.xy + half2( 2, 0)).rgb;
gNeighbors[3] = texRECT(colorImage, pos.xy + half2(-1, 0)).rgb;
gNeighbors[4] = texRECT(colorImage, pos.xy + half2( 1, 0)).rgb;
gNeighbors[5] = texRECT(colorImage, pos.xy + half2( 2, 0)).rgb;
gNeighbors[6] = texRECT(colorImage, pos.xy + half2(-2, 1)).rgb;
gNeighbors[7] = texRECT(colorImage, pos.xy + half2(-1, 1)).rgb;
bNeighbors[0] = texRECT(colorImage, pos.xy + half2( 0, 1)).rgb;
bNeighbors[1] = texRECT(colorImage, pos.xy + half2( 1, 1)).rgb;
bNeighbors[2] = texRECT(colorImage, pos.xy + half2( 2, 1)).rgb;
bNeighbors[3] = texRECT(colorImage, pos.xy + half2(-2, 2)).rgb;
bNeighbors[4] = texRECT(colorImage, pos.xy + half2(-1, 2)).rgb;
bNeighbors[5] = texRECT(colorImage, pos.xy + half2( 0, 2)).rgb;
bNeighbors[6] = texRECT(colorImage, pos.xy + half2( 1, 2)).rgb;
bNeighbors[7] = texRECT(colorImage, pos.xy + half2( 2, 2)).rgb;
// Data for reach.r: 2x4 fmod, 2x4 step operations with those results
const half4 reachRfmod1 = fmod(reach.rrrr, half4(2,4,8,16));
const half4 reachRfmod2 = fmod(reach.rrrr, half4(32,64,128,256));
const half4 reachRstep1 = step(half4(1,2,4,8), reachRfmod1);
const half4 reachRstep2 = step(half4(16,32,64,128), reachRfmod2);
// Data for reach.g: 2x4 fmod, 2x4 step operations with those results
const half4 reachGfmod1 = fmod(reach.gggg, half4(2,4,8,16));
const half4 reachGfmod2 = fmod(reach.gggg, half4(32,64,128,256));
const half4 reachGstep1 = step(half4(1,2,4,8), reachGfmod1);
const half4 reachGstep2 = step(half4(16,32,64,128), reachGfmod2);
// Data for reach.b: 2x4 fmod, 2x4 step operations with those results
const half4 reachBfmod1 = fmod(reach.bbbb, half4(2,4,8,16));
const half4 reachBfmod2 = fmod(reach.bbbb, half4(32,64,128,256));
const half4 reachBstep1 = step(half4(1,2,4,8), reachBfmod1);
const half4 reachBstep2 = step(half4(16,32,64,128), reachBfmod2);
// Data for the rNeighbors.b
const half4 rNeighborsStep1 = step(0.0001.xxxx,
half4(rNeighbors[0].b, rNeighbors[1].b, rNeighbors[2].b, rNeighbors[3].b));
const half4 rNeighborsStep2 = step(0.0001.xxxx,
half4(rNeighbors[4].b, rNeighbors[5].b, rNeighbors[6].b, rNeighbors[7].b));
// Data for the gNeighbors.b
const half4 gNeighborsStep1 = step(0.0001.xxxx,
half4(gNeighbors[0].b, gNeighbors[1].b, gNeighbors[2].b, gNeighbors[3].b));
const half4 gNeighborsStep2 = step(0.0001.xxxx,
half4(gNeighbors[4].b, gNeighbors[5].b, gNeighbors[6].b, gNeighbors[7].b));
// Data for the bNeighbors.b
const half4 bNeighborsStep1 = step(0.0001.xxxx,
half4(bNeighbors[0].b, bNeighbors[1].b, bNeighbors[2].b, bNeighbors[3].b));
const half4 bNeighborsStep2 = step(0.0001.xxxx,
half4(bNeighbors[4].b, bNeighbors[5].b, bNeighbors[6].b, bNeighbors[7].b));
// R - modulators
const half4 rModulator1 = rNeighborsStep1 * reachRstep1;
const half4 rModulator2 = rNeighborsStep2 * reachRstep2;
// G - modulators
const half4 gModulator1 = gNeighborsStep1 * reachGstep1;
const half4 gModulator2 = gNeighborsStep2 * reachGstep2;
// B - modulators
const half4 bModulator1 = bNeighborsStep1 * reachBstep1;
const half4 bModulator2 = bNeighborsStep2 * reachBstep2;
// ****** ROW 0 ******
modulator = rModulator1.x;
averageColor += modulator * rNeighbors[0] * rWeights[0];
weight += modulator * rWeights[0].x;
modulator = rModulator1.y;
averageColor += modulator * rNeighbors[1] * rWeights[1];
weight += modulator * rWeights[1].x;
modulator = rModulator1.z;
averageColor += modulator * rNeighbors[2] * rWeights[2];
weight += modulator * rWeights[2].x;
modulator = rModulator1.w;
averageColor += modulator * rNeighbors[3] * rWeights[3];
weight += modulator * rWeights[3].x;
modulator = rModulator2.x;
averageColor += modulator * rNeighbors[4] * rWeights[4];
weight += modulator * rWeights[4].x;
// ****** ROW 1 ******
modulator = rModulator2.y;
averageColor += modulator * rNeighbors[5] * rWeights[5];
weight += modulator * rWeights[5].x;
modulator = rModulator2.z;
averageColor += modulator * rNeighbors[6] * rWeights[6];
weight += modulator * rWeights[6].x;
modulator = rModulator2.w;
averageColor += modulator * rNeighbors[7] * rWeights[7];
weight += modulator * rWeights[7].x;
modulator = gModulator1.x;
averageColor += modulator * gNeighbors[0] * gWeights[0];
weight += modulator * gWeights[0].x;
modulator = gModulator1.y;
averageColor += modulator * gNeighbors[1] * gWeights[1];
weight += modulator * gWeights[1].x;
// ****** ROW 2 ******
modulator = gModulator1.z;
averageColor += modulator * gNeighbors[2] * gWeights[2];
weight += modulator * gWeights[2].x;
modulator = gModulator1.w;
averageColor += modulator * gNeighbors[3] * gWeights[3];
weight += modulator * gWeights[3].x;
selfColor = texRECT(colorImage, pos).rgb;
centerModulator = step(0.0001, selfColor.b);
averageColor += centerModulator * selfColor * 32;
weight += centerModulator * 32;
modulator = gModulator2.x;
averageColor += modulator * gNeighbors[4] * gWeights[4];
weight += modulator * gWeights[4].x;
modulator = gModulator2.y;
averageColor += modulator * gNeighbors[5] * gWeights[5];
weight += modulator * gWeights[5].x;
// ****** ROW 3 ******
modulator = gModulator2.z;
averageColor += modulator * gNeighbors[6] * gWeights[6];
weight += modulator * gWeights[6].x;
modulator = gModulator2.w;
averageColor += modulator * gNeighbors[7] * gWeights[7];
weight += modulator * gWeights[7].x;
modulator = bModulator1.x;
averageColor += modulator * bNeighbors[0] * bWeights[0];
weight += modulator * bWeights[0].x;
modulator = bModulator1.y;
averageColor += modulator * bNeighbors[1] * bWeights[1];
weight += modulator * bWeights[1].x;
modulator = bModulator1.z;
averageColor += modulator * bNeighbors[2] * bWeights[2];
weight += modulator * bWeights[2].x;
// ****** ROW 4 ******
modulator = bModulator1.w;
averageColor += modulator * bNeighbors[3] * bWeights[3];
weight += modulator * bWeights[3].x;
modulator = bModulator2.x;
averageColor += modulator * bNeighbors[4] * bWeights[4];
weight += modulator * bWeights[4].x;
modulator = bModulator2.y;
averageColor += modulator * bNeighbors[5] * bWeights[5];
weight += modulator * bWeights[5].x;
modulator = bModulator2.z;
averageColor += modulator * bNeighbors[6] * bWeights[6];
weight += modulator * bWeights[6].x;
modulator = bModulator2.w;
averageColor += modulator * bNeighbors[7] * bWeights[7];
weight += modulator * bWeights[7].x;
// Discards pixels without samples in the 5x5 neighborhood
if (weight < 1) discard;
half4 outColor;
outColor.rgb = averageColor / weight;
outColor.a = saturate(weight / 255.0 + centerModulator);
// Priority calculation
const half pWeight = outColor.a;
half priority;
// If this is an invalid point, get its priority from the table,
// else just get its previously stablished priority value
if (pWeight > 64/255.0) { // The value was already normalized!
priority = texRECT(prioritySeqnum, pos).r;
}
else {
priority = texRECT(priorityTable, half2(pWeight * 255 + 0.5, 0.5)).r;
}
outColor.a = priority;
return outColor;
}