# fragment shader median/weigthed sum of neighbors depth values (optimization)

I've implemented a ping pong rendering that does something according to constraints on the current fragment :

(1) The value of the fragment depth is equal to the median of neighbors depth values (2) the value of the fragment depth is equal to a weighted sum of neighbors depth values (3) The point is black

I'll say that the easier part is the (3), but for the 2 others (1) and (2), I have optimization problems (my FPS drop to 1.2 when I use it).

What I do, is if we're in case (1) or (2) I fill an array with all neighbors values that are valid (not the background). for (1), I use Niklaus_wirth algorithm to sort the array and take the median value. For (2), I calculate the weigth for each neighbors and then do a Sum.

Since i'm not very used to work with GPUs, the ways to optimize my program are not known by me. I checked several tuto to improve a shader code, but couldn't find something that fit with me :/ (I saw that I have to remove the most if statement possible, but don't find any ways to do it...) Here's the code :

vec3 PingPongDepth() {
return texture(fillingTexDepth, TexCoords).xyz;
}

//I do the pingpong around "fillingTexDepth". The next function give me the 3-neighbourhood of the current fragment.
vec3 PingPongDepth(int i) {
int x = i % 3;
int y = i / 3;

int rx = x - 1;
int ry = 1 - y;

return texture(fillingTexDepth, TexCoords + vec2(rx*dx, ry*dy)).xyz;
}
//I Put values in my array if they are valid neighbors
void PutInArray() {
for (int i = 0; i < 9; ++i) {
//We don't want to take the current fragment in the calculus
if (i != 4) {
vec3 pIDepth = PingPongDepth(i);
if (isValid(pIDepth)) {
xArray[xSize] = pIDepth.x;
xSize++;
}
}
}


and then, for (1):

void xSwap(int a, int b) {
float tmp = xArray[a];
xArray[a] = xArray[b];
xArray[b] = tmp;
}

void kth_smallest(int k) {
int i, j, l, m;
float x;

l = 0;
m = xSize - 1;
while (l < m) {
x = xArray[k];
i = l;
j = m;
do {
while (xArray[i] < x) i++;
while (x < xArray[j]) j--;
if (i <= j) {
xSwap(i, j);
i++; j--;
}
} while (i <= j);
if (j < k) l = i;
if (k < i) m = j;
}
//retDepth is the vec4 that is returned by my shader
retDepth = vec4(vec3(xArray[k], 0.0f, 0.0f), 1.0f);
}

void Median_NW(vec3 vDepth, vec3 vCol) {
if (xSize == 0) {
retDepth = vec4(vDepth, 1.0f);
retColor = vec4(vCol, 1.0f);
return;
}
else if (xSize == 1) {
retDepth = vec4(vec3(xArray[0], 0.0f, 0.0f), 1.0f);
return;
}
else
kth_smallest(xSize / 2);
}


and for (2)

float xWeight_(vec3 v, int i, float sigma) {
float rI = (i % 2 == 0) ? 1.4142 : 1.0;

return (1.0f - 0.5*rI )*(1 - min(1, abs(xArray[i] - v.x) / sigma));
}

void WeightedSum(vec3 vDepth, vec3 vCol) {
if (xSize == 0) {
retDepth = vec4(vDepth, 1.0f);
return;
}
float weightedDepth = 0.0f;
float xSum = 0.0f;

for (int i = 0; i < xSize; ++i) {
float w_ = xWeight_(vDepth, i, 2.0f);
weightedDepth += xArray[i] * w_;
xSum += w_;
}
retDepth = vec4(vec3(weightedDepth, 0.0f, 0.0f) / xSum, 1.0f);
}


If someone have an idea... (sorry for the long post)