GMS 2 Please, help optimizing my shader

Petrik33

Member
I have recently posted a thread where I had asked to help me making one shader, now I guess I have understood how to make it, but as I am very poor at Shading Language(GLSL if I am not mistaken), I really have troubles with syntax, so here is the working shader code and I will aslo attach the result:
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float pixelH;
uniform float pixelW;
uniform float inside_alpha;


void main()
{
    vec2 offsetx;
    offsetx.x = pixelW;
    vec2 offsety;
    offsety.y = pixelH;
   
    vec3 outline_color = vec3(0.13,0.64,0.86);//1st question
    vec3 inside_color = vec3(0.13,0.64,0.90);//1st question
 
    float alpha = texture2D(gm_BaseTexture, v_vTexcoord).a;
    float surrounding_max_alpha1 = max(texture2D(gm_BaseTexture, v_vTexcoord + offsetx).a,texture2D(gm_BaseTexture, v_vTexcoord - offsetx).a);
    float surrounding_max_alpha2 = max(texture2D(gm_BaseTexture, v_vTexcoord + offsety).a,texture2D(gm_BaseTexture, v_vTexcoord - offsety).a);
    float surrounding_max_alpha = max(surrounding_max_alpha1,surrounding_max_alpha2);
   
    vec4 base_col = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord);
   
    if((surrounding_max_alpha - alpha) >= 1.0)
    {
        base_col = vec4(outline_color,1.0);
    }
    else
    {
        if(alpha>=0.0001)//2nd question
        {
            base_col = vec4(base_col.rgb * inside_color,inside_alpha);
        }
    }
   
    gl_FragColor = base_col;
}
So I have a few questions, first of course how can I make it better. But now much more particular ones:
1. Is it ok to have such things if I need a color that will always be the same for my shader, I mean should it be changed with some constant or something and if yes how do I do it?
2. Why the compiler was saying to me that if(alpha == 0) is an error? And if I really can't make an equality check how do I replace this line of code? Honestly right now when I was writing this thread I came up with the idea to set alpha value to (inside_alpha * alpha) and it worked, but the question with equality check remains opened for me.
3. Is there any difference between arrays and vectors and how do I create an array in the shader?
4. And of course is there any other way to check for the outline pixels rather than this(this one is a slightly changed Shaun Spalding's one)?

Edit: The original Purpose of this shader is to create a cursor for an entity, so if you know any better way to do this let me know please.
 

Attachments

Simon Gust

Member
1. It's fine if you only need one color for everything. But similar to normal script you can submit arguments called "uniforms" into your shader. Exactly like pixelH, pixelW and inside_alpha.
The only adaptation you have to do is change the type from float (singular value) to vec4 (color + alpha value). On the other side where you call shader_set_uniform, you provide 4 values instead of 1. The first 3 being red, green, blue and 4th being alpha.

2. You are trying to compare alpha (floating point value) to 0 (integer value) which is illegal. Here there is no Game Maker to save you from this, you have to be aware of that.
It will work if you compare alpha to 0.0 indicating that "0" should be a float rather than an int.

3. Array and vector are similar. The vectors you can use are vec2 for x, y, vec3 for x, y, z and vec4 for r, g, b, a. If you need more values you can create an array uniform.
Code:
uniform float time[6];
gml side
Code:
var array = [10, 19, 14.5, 0.22, 11, 15];

shader_set_uniform_f_array( shader_get_uniform( shader name , "time" ) , array );
4. The method is the only one I know of, probably good enough.
 

Petrik33

Member
1. It's fine if you only need one color for everything. But similar to normal script you can submit arguments called "uniforms" into your shader. Exactly like pixelH, pixelW and inside_alpha.
The only adaptation you have to do is change the type from float (singular value) to vec4 (color + alpha value). On the other side where you call shader_set_uniform, you provide 4 values instead of 1. The first 3 being red, green, blue and 4th being alpha.

2. You are trying to compare alpha (floating point value) to 0 (integer value) which is illegal. Here there is no Game Maker to save you from this, you have to be aware of that.
It will work if you compare alpha to 0.0 indicating that "0" should be a float rather than an int.

3. Array and vector are similar. The vectors you can use are vec2 for x, y, vec3 for x, y, z and vec4 for r, g, b, a. If you need more values you can create an array uniform.
Code:
uniform float time[6];
gml side
Code:
var array = [10, 19, 14.5, 0.22, 11, 15];

shader_set_uniform_f_array( shader_get_uniform( shader name , "time" ) , array );
4. The method is the only one I know of, probably good enough.
Very very big thank you! Honestly, can't express how grateful am I! Still one question, what is more efficient: to pass a uniform or to have like I have now?(to the 1st question)
 

Simon Gust

Member
Very very big thank you! Honestly, can't express how grateful am I! Still one question, what is more efficient: to pass a uniform or to have like I have now?(to the 1st question)
Any information traffic between cpu and gpu is slow by nature, so creating the value inside the shader is faster I presume.
The GPU is designed to take on many parallel calculations unlike the CPU, which also means that many if-statements can eat away at your performance.
 

Joe Ellis

Member
You could also replace the 2 if statements with these:

Code:
base_col = mix(base_col, vec4(base_col.rgb * inside_color,inside_alpha), sign(max(0.0, alpha - 0.0001)));
base_col = mix(base_col, vec4(outline_color,1.0), sign(max(0.0, (surrounding_max_alpha - alpha) - 0.0039215686274509803921568627451)));
By subtracting the value you're checking if alpha is more than, if it's less than that it will become < 0, so then by using max to clamp it to 0, then sign to make the value either 0 or 1 depending whether it's 0 or anything above 0, you can then use that as the mix ratio and it produces the same result as the if statement, but is faster. At least I think it's faster, I remember a couple of times where I replaced if statements with these and it stopped it from lagging. I think with shaders, math calculations with floating point numbers are a lot faster than things like integer handling and if statements, probably cus they were optimizing with that as the priority as it's the thing they're used for most often.
 
Top