2
$\begingroup$

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)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.