I have been working on how the GPU does parellel processing, and branching. However I am not yet to the point where I know how to make this shader more efficent. Essentially I dont know enough about how it works.

Anyway I have the following shader:

precision highp float;

varying vec3 o_color; //Color it should be
varying vec2 texture_coord; //Interpolated value 0-1
varying float ratio_out; //This is the height / width of the capsule on screen
varying float rdistOut; //This number is used to fill in all pixels when particle is slow enough for the geometry to be a square but still has some distance from last position.

void main()
{

vec2 yCoord = vec2(0.5);
float yScale = ratio_out;

vec2 my = texture_coord * vec2(1.0, yScale);

vec2 del = yCoord - my;

float len = del.x * del.x + del.y * del.y;
if ((!(my.y > 1.0) && (len < 0.25)) || (my.y > yCoord.y && my.y < rdistOut))
{
gl_FragColor = vec4(o_color, 1.0);
}
else
{
gl_FragColor.a = 0.0;
}
}


What it does is draw capsules on the screen. Basically these capsules connect where the particle was to where it is.

On the cpu I compute the vertices of this with some linear algebra, but in screen space terms the rectangle we will be shading has a maximum width of W and a minimum height of W. If the capsule is moving faster then W/2 then the capsules geometry will start to get longer to accommodate.

Here are some diagrams of what is going on:

This is an image of a single capsule. Because the distance between the current and last position is not large enough so the screen-space geometry is a square. You can see that to compensate that lighter area is shaded in as well to connect the two points.

Here are some more examples of what could happen

The thing is these capsules are all individual, sometimes every capsule will be elongated, sometimes it will only be a small percent. This shader needs to be as steady fps as possible.

Now here are some tips that are useful and might help make things more efficent:

1. The dot product is NEVER needed past the point where the circle part is done.
2. If the scaleFactor is greater then 1 then the dot product is never needed past the center of the circle.

This is shown in this diagram. In this case none of the grey area needs to preform the dot product.

Explanation of variables:

o_color: is the color that that particle is

texture_coord: these are the exact same as if you were going to texture this, they go from 0-1

ratio_out: height / width. Will never be less then 1

Inside the main function to get the coordinates in screen scale we simply multiply the y texture coordinate by the scale factor. That makes the center of the circle part a 0.5, 0.5.

rdistOut is the tiny area that the particle sometimes has when it is a square but still moving. Things should be shaded from 0.5-rdistOut.

Could you please help me remove un-needed dot product computations and comparisons as well as get rid of branching?

Please include an explanation of how you got the GPU to skip dot product calculations or why you did what you did. Next time I hope to be able to do this myself.

• To clarify, is the dot product you are referring to "len"? – aces Sep 3 '16 at 3:41
• Yes, I have used dot(delta, delta) before in place of dist * dist. I just did the dot product that way to simplify things. – J.Doe Sep 3 '16 at 3:43
• What is the average speed of the particle? Is it normal to be the same size as that blue diagram at the bottom? I'm just trying to get a good idea of the use cases. – aces Sep 3 '16 at 4:02
• @J.Doe: The only way you could avoid the dot product would be... by using a conditional branch around it. Which could wind up being slower than just doing the dot product. And let's face facts: a 2D vector dot-product is trivially fast on GPUs these days. – Nicol Bolas Sep 4 '16 at 3:49
• This shader looks like it should be super fast already, can't think of any further optimizations really. If / else branches will only really hurt you in a shader if you have a fair bit of code in each branch, here you're not even doing any arithmetic in the branches, just returning values, so the performance hit should be negligible. You could always replace it with a ternary operator, as in gl_FragColor = (condition) ? true_value : false_value. This compiles to a conditional move rather than a branch, so might get you a small speed boost. – russ Sep 5 '16 at 3:14