uniform int isWellBehaved; uniform int isSwapped; uniform int isNativelyFocal; uniform half invR1; // 1/r1 uniform half fx; // focalX = r0/(r0-r1) half4 main(float2 p) { float t = -1; half v = 1; // validation flag,set to negative to discard fragment later float x_t = -1; if (bool(isFocalOnCircle)) { x_t = dot(p, p) / p.x; } else if (bool(isWellBehaved)) { x_t = length(p) - p.x * invR1; } else { float temp = p.x * p.x - p.y * p.y; // Only do sqrt if temp >= 0; this is significantly slower than // checking temp >= 0 in the if statement that checks r(t) >= 0. // But GPU may break if we sqrt a negative float. (Although I // haven't observed that on any devices so far, and the old // approach also does sqrt negative value without a check.) If // the performance is really critical, maybe we should just // compute the area where temp and x_t are always valid and drop // all these ifs. if (temp >= 0) { if (bool(isSwapped) || !bool(isRadiusIncreasing)) { x_t = -sqrt(temp) - p.x * invR1; } else { x_t = sqrt(temp) - p.x * invR1; } } } // The final calculation of t from x_t has lots of static // optimizations but only do them when x_t is positive (which // can be assumed true if isWellBehaved is true) if (!bool(isWellBehaved)) { // This will still calculate t even though it will be ignored // later in the pipeline to avoid a branch if (x_t <= 0.0) { v = -1; } } if (bool(isRadiusIncreasing)) { if (bool(isNativelyFocal)) { t = x_t; } else { t = x_t + fx; } } else { if (bool(isNativelyFocal)) { t = -x_t; } else { t = -x_t + fx; } } if (bool(isSwapped)) { t = 1 - t; } return half4(half(t), v, 0, 0); }