First of all, let me explain what I am really trying to achieve. In a post-effect shader acting on a camera-renderer, I want to change the color of each fragment depending on how many green (RGBA = 0,~1,0,1) fragments there are nearby.
So, for the sake of simplicity, let's imagine my screen is all black, with some (~10k) green points spread around. In the fragment shader, for each fragment I have to find how many green fragments there are within a given distance and then change the color of the current fragment being evaluated depending on that number of surrounding green fragments.
I began with the most naïve approach one could think of: for each fragment, I calculated the coordinates of the 10th neighbor fragments to each side: right, left, up and down (which gives a surrounding square, then I discarded the corners from the computation to get a surrounding circle of radius ~10pixels, centered at the current fragment). Then I tested which of the fragments within such "surrounding bounding circle" was green (i.e. color.g > 0.9f). In affirmative case, I increased a counter variable.
In my way of thinking, that would be doing a brute force and in order to visualize the result, I then painted each fragment with the RGBA color (counter*0.1f, 0, counter*0.1f, 1). Here is the code snippet:
uniform sampler2D _MainTex;
static float2 _Pixels = float2(_ScreenParams.x, _ScreenParams.y); //gets the Screen width and height
static half sx = 1 / _ScreenParams.x; //defines the measure of a fragment at the X axis of the viewport
static half sy = 1 / _ScreenParams.y; //defines the measure of a fragment at the Y axis of the viewport
float4 frag(v2f_img input) : COLOR{
fixed2 uv = round(input.uv * _Pixels) / _Pixels;
float counter = 0.0f;
float i; float j;
float thrsh = 0.8f;
[unroll(10)]for (i = zero; i<10;i++) //loop trough 10 fragments horizontally
{
[unroll(10)]for (j = zero; j < 10; j++) //loop trough 10 fragments vertically
{
//the following lines cut (very roughly) the corners of the surrounding square ixj to approximate a surrounding circle of radius ~10fragments. But this is less important: if such lines are commented, the problem that I will show later will still happen, just with a surrounding square instead of a surrounding circle
if ((i == 4 || i == 5) && j > 9) j = 0; else if ((i == 6) && j > 8) j = 0; else if ((i == 7) && j > 7) j = 0;
else if ((i == 8) && j > 6) j = 0; else if ((i == 9) && j > 5) j = 0; else if (i == 10 && j > 4) j = 0;
else if (j > 0) { //so, let's continue only if current iteration does not relate to the corners of the surrounding square, i.e. outside the surrounding circle with radius ~10 fragments
float tl = tex2D(_MainTex, uv + fixed2(-sx*i, +sy*j)).g; //gets the top-left neighbor times i and j
float cl = tex2D(_MainTex, uv + fixed2(-sx*i, 0)).g; //gets the center-left neighbor times i and j
float bl = tex2D(_MainTex, uv + fixed2(-sx*i, -sy*j)).g; //gets the bottom-left neighbor times i and j
float tc = tex2D(_MainTex, uv + fixed2(0, +sy*j)).g; //gets the top-center neighbor times i and j
float cc = tex2D(_MainTex, uv + fixed2(0, 0)).g; //gets the current fragment bein evaluated (i.e. center-center)
float bc = tex2D(_MainTex, uv + fixed2(0, -sy*j)).g; //gets the bottom-center neighbor times i and j
float tr = tex2D(_MainTex, uv + fixed2(+sx*i, +sy*j)).g; //gets the top-right neighbor times i and j
float cr = tex2D(_MainTex, uv + fixed2(+sx*i, 0)).g; //gets the center-right neighbor times i and j
float br = tex2D(_MainTex, uv + fixed2(+sx*i, -sy*j)).g; //gets the bottom-right neighbor times i and j
//Now, for each fragment surrounding that is above the Green threshold, we increase the counter
if (tl > thrsh) counter++;
if (cl > thrsh) counter++;
if (bl > thrsh) counter++;
if (tc > thrsh) counter++;
if (bc > thrsh) counter++;
if (tr > thrsh) counter++;
if (cr > thrsh) counter++;
if (br > thrsh) counter++;
}
}
}
if (counter > 0)
{
return float4(counter *0.1f, 0, counter *0.1f, 1); //in case at least one surrounding fragment was green, paint the fragments pink-ish in proportion to how many green there were in the surrounding circle
} else {
return tex2D(_MainTex, float4(0,0,0,1)); //otherwise, paint black
}
However, besides very inefficient, the solution above is also not working correctly. Obvioulsy, I was expecting to get, around each green point at the screen, something like a pink-ish circle that is of stronger intensity when close to the center and fades away at the border, i.e. away from the center. Instead, this is what I get (in actual and zoomed sizes):
Now, I tried everything I could think of but I don't get:
1) why it is not working properly. What am I doing wrong? Could anyone shed some light?
2) also, if there is any obvious more performant way of achieving what I want, please do let me know too (the current solution is taking 12ms in a non HD resolution). Or if you prefer, I can come with a different question for that later, after the operational problem described above is solved.
Thanks anyways for your time.