Shaders Properly Making This Shader?

Ragster

Member
I've never worked with Shaders before this, but I managed to get one working and I really doubt it's optimized. The goal of my Shader is to use three custom colors for a sprite, replacing pixels in the sprite that are 100% red, 100% green, and 100% blue. I just used a bunch of if's to do this:

Code:
attribute vec3 in_Position;
attribute vec4 in_Colour;
attribute vec2 in_TextureCoord;
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main() {
    vec4 object_space_pos = vec4(in_Position.x,in_Position.y,in_Position.z,1);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION]*object_space_pos;
    v_vColour = in_Colour;
    v_vTexcoord = in_TextureCoord;
}
//######################_==_YOYO_SHADER_MARKER_==_######################@~
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec3 paletteColorR;
uniform vec3 paletteColorG;
uniform vec3 paletteColorB;
void main() {
    vec4 pixelColor = texture2D(gm_BaseTexture,v_vTexcoord);
    float red = pixelColor.r;
    float green = pixelColor.g;
    float blue = pixelColor.b;
    if (red > 0.0 && green == 0.0 && blue == 0.0) pixelColor = vec4(paletteColorR.r*red,paletteColorR.g*red,paletteColorR.b*red,pixelColor.a);
    else if (red == 0.0 && green > 0.0 && blue == 0.0) pixelColor = vec4(paletteColorG.r*green,paletteColorG.g*green,paletteColorG.b*green,pixelColor.a);
    else if (red == 0.0 && green == 0.0 && blue > 0.0) pixelColor = vec4(paletteColorB.r*blue,paletteColorB.g*blue,paletteColorB.b*blue,pixelColor.a);
    gl_FragColor = v_vColour*pixelColor;
}
It works as intended, but if anyone knows a better way of doing this, I would greatly appreciate the help.
 

SoVes

Member
looks like a good solution to me, but I don't see the need to use floats instead of just using pixelColor.
 

Bart

WiseBart
There's not that much to optimize in that shader.

One thing you can do, which would mainly be useful to improve readability, is to not separate the rgb components into floats. That is because shaders have dedicated functions to work with vectors, so it's better to use those whenever you can.
You can find more on them in the specification of the OpenGL ES Shading Language.

It may also be interesting to read up on some shader documentation that goes a bit more in depth:

https://www.yoyogames.com/blog/14/shaders-overview-part-1
https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/shaders/index.html
 

Ragster

Member
Thanks for the input. I changed the Fragment like so:
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec3 paletteColorR;
uniform vec3 paletteColorG;
uniform vec3 paletteColorB;
void main() {
    vec4 pixelColor = texture2D(gm_BaseTexture,v_vTexcoord);
    if (pixelColor.r > 0.0 && pixelColor.g == 0.0 && pixelColor.b == 0.0) pixelColor = vec4(paletteColorR.r*pixelColor.r,paletteColorR.g*pixelColor.r,paletteColorR.b*pixelColor.r,pixelColor.a);
    else if (pixelColor.r == 0.0 && pixelColor.g > 0.0 && pixelColor.b == 0.0) pixelColor = vec4(paletteColorG.r*pixelColor.g,paletteColorG.g*pixelColor.g,paletteColorG.b*pixelColor.g,pixelColor.a);
    else if (pixelColor.r == 0.0 && pixelColor.g == 0.0 && pixelColor.b > 0.0) pixelColor = vec4(paletteColorB.r*pixelColor.b,paletteColorB.g*pixelColor.b,paletteColorB.b*pixelColor.b,pixelColor.a);
    gl_FragColor = v_vColour*pixelColor;
}
There's probably little-to-no increase in performance, but I suppose it does look nicer :cool:

EDIT: I'm looking into that documentation and found the vector relational functions, but am still trying to figure out how to implement them.
 
Last edited:

NightFrost

Member
You can multiply vectors wholesale when needed. For example the red component would go:
Code:
pixelColor = vec4(paletteColorR * pixelColor.r, pixelColor.a)
And unless you are using extended draw commands to bring in color blend information, you can drop the v_vColour bit too.

TheReverend's shader series is a good source of information.
 
Top