Reputation: 4770
I have the following fragment shader written in both GLSL & HLSL (here written in HLSL, but the implementations are almost identical):
sampler2D input : register(s0);
float3 lowerBounds : register(c0);
float3 higherBounds : register(c1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(input, uv);
float y = clamp(0.299 * color.r + 0.587 * color.g + 0.1140 * color.b, 0.0, 1.0);
float u = clamp(-0.169 * color.r - 0.331 * color.g + 0.5000 * color.b, 0.0, 1.0);
float v = clamp(0.500 * color.r - 0.419 * color.g - 0.0813 * color.b, 0.0, 1.0);
if (((y >= lowerBounds.x && y <= higherBounds.x) && (u >= lowerBounds.y && u <= higherBounds.y)) && (v >= lowerBounds.z && v <= higherBounds.z))
{
color = 0;
}
return color;
}
As you can see, the shader simply checks if a color fall within two YUV colors, and if it does, the fragment is filtered out.
I understand that conditional statements can be really bad for performance so I'm wondering if the above is an example of a "bad" conditional and/or it can be optimized to not use an if statement.
Edit: The final optimized code looks like so:
sampler2D input : register(s0);
float3 lowerBounds : register(c0);
float3 higherBounds : register(c1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(input, uv);
float y = clamp(0.299 * color.r + 0.587 * color.g + 0.1140 * color.b + 0.0627, 0.0, 1.0);
float u = clamp(-0.169 * color.r - 0.331 * color.g + 0.5000 * color.b, -0.5, 0.5);
float v = clamp(0.500 * color.r - 0.419 * color.g - 0.0813 * color.b, -0.5, 0.5);
float3 yuv = { y, u, v };
// Calculate and apply mask from background range
float3 mask = step(lowerBounds, yuv) * step(yuv, higherBounds);
color *= 1.0 - (mask.x * mask.y * mask.z);
return color;
}
Upvotes: 0
Views: 1727
Reputation: 1234
I think this code should do the trick:
vec3 yuv = vec3(y, u, v);
color = step(lowerBounds, yuv ) * step(yuv, upperBounds) * color;
if yuv is < to lowerBounds it will return 0 same as yuv >= lowerBounds
if upperBounds is < to yuv it will return 0 same as yuv <= upperBounds
Upvotes: 1