Getting rid of orphan pixels using a shader?

F

Forestherd

Guest
Hello!

I made a fluid looking lighting system based off of this example here: http://multiverselabyrinth.tumblr.c...silly-question-but-what-engine-do-you-use-how

But I have this ugly looking problem where, if two light sources are aalmost about to connect up, they start connecting up in this really fuzzy fashion - there are some stray pixels all around the connection point and overall it looks really out of place. Here is a gif:
giffy.gif

You'll see what I mean when you look at the three middle light rings. They blend just fine if they are already connected, but if they are in the process of that, it looks super ugly.
I though about maybe making a shader that would remove the stray pixels based on what color pixel surrounded it, but that would only be a semi-fix and even then I don't really have a good enough understanding of shaders to actually make something like that. Any help would be really appreciated!
 

Neptune

Member
I don't think it would take many lines of code to have a shader do this. You could just check up,down,left,right of each pixel and say "If im not touching a pixel of similar color, then convert to orange."
Unfortunately doing something simple like checking left,right,up,down of the shader's target pixel is kind of a pain.
 

Joe Ellis

Member
you'd have to send the application_surface to a shader that reads it and then draws the cleaned up result, which isnt that hard but might impact performance too much, depends what else is going on in the game, if theres plenty of memory left it shouldnt be too bad
looking at that picture you'd need to get the mode(most common) color from each of the 8 neighbour pixels, and write that to the shader's pixel
 
F

Forestherd

Guest
I don't think it would take many lines of code to have a shader do this. You could just check up,down,left,right of each pixel and say "If im not touching a pixel of similar color, then convert to orange."
Unfortunately doing something simple like checking left,right,up,down of the shader's target pixel is kind of a pain.
you'd have to send the application_surface to a shader that reads it and then draws the cleaned up result, which isnt that hard but might impact performance too much, depends what else is going on in the game, if theres plenty of memory left it shouldnt be too bad
looking at that picture you'd need to get the mode(most common) color from each of the 8 neighbour pixels, and write that to the shader's pixel
Yeah, I though of the same solution. Tho I'll have to check the pixel 2 pixels over, because the game is actually scaled a bit. In any case, if you guys have any good resource that could help me with the whole v_vTexcoords business and how to check pixels in a shader (because as mentioned, its a pain), it would be a big help if you could link it here!
 

CMAllen

Member
The only thing a shader would need to do this is the dimensions of the surface or image being operated on (but only if the surface size on which it is operating is variable in size -- otherwise you can calculate this value yourself and write it straight into the shader). Once the shader has that information, it's a simple matter to convert relative coordinate space into absolute pixel space.

v_vTextcoords exists as an X/Y vector value ranging between 0.0 to 1.0. The coordinate that gets passed into the fragment shader is that of the current pixel being read, but you can read from adjacent pixels by adding or subtracting from that X/Y vector. Note: you can add/subtract outside the valid ranges of 0.0 and 1.0, but the shader (or GM) automatically clamps to that range. For example, the following code:
Code:
v_vTextcoords.x-=0.1;
v_vTextcoords.y-=0.1;
will read from a pixel area that's 10% of the surface/image's total x and y dimensions up and to the left (I believe that's the correct orientation of the coordinate space -- someone feel free to correct me if not). This is where needing to know how large the surface is comes in. Since the v_vTextcoord exists as, essentially, a percentage value of the surface's height and width, getting the exact size of an individual pixel is just dividing 1.0 by the surface/image width and height. For example, a surface that is 640px wide has a pixel width of 0.0015625, so to read from a pixel to the left or right, you'd subtract or add 0.0015625 with the v_vTextcoord.x.

In fact, you can use a simple add/subtract method to create a crude blurring effect by reading from the surrounding pixels, averaging their respective channel values together, and outputting the results as the gl_FragColor. (you don't even need to know how large a pixel is for it to work -- larger distances just result in greater blurring!
 

Joe Ellis

Member
Yeah thats the basic method to get the 'texel width\height'

Heres the basic code for sampling the surrounding pixels of a texture:

Code:
varying vec2 UV;

uniform vec2 Screen_Size;

void main()
{

//Get Texel Size
float tx = 1 / Screen_Size.x;
float ty = 1 / Screen_Size.y;

vec3 p1 = texture2D( gm_BaseTexture, vec2(UV.x + tx, UV.y) );
vec3 p2 = texture2D( gm_BaseTexture, vec2(UV.x + tx, UV.y + ty) );
vec3 p3 = texture2D( gm_BaseTexture, vec2(UV.x, UV.y + ty) );
vec3 p4 = texture2D( gm_BaseTexture, vec2(UV.x - tx, UV.y + ty) );
vec3 p5 = texture2D( gm_BaseTexture, vec2(UV.x - tx, UV.y) );
vec3 p6 = texture2D( gm_BaseTexture, vec2(UV.x - tx, UV.y - ty) );
vec3 p7 = texture2D( gm_BaseTexture, vec2(UV.x, UV.y - ty) );
vec3 p8 = texture2D( gm_BaseTexture, vec2(UV.x + tx, UV.y - ty) );

gl_FragColor = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8) * 0.125;

}
You'll have to work out getting the mode yourself as I've never done it, and cant think of a good way of doing off the top of my head, it could be done with alot of ifs, but thats generally bad for performance in a shader, cus if you think how many pixels there are on a screen (1000 x 1000 = 1 million) doing 27 million ifs every frame is ridiculous

About what you said with the scaling, it shouldnt need to be altered for the shader if set up properly, the scaling should be applied after the shader has been used
 
Top