Shaders [SOLVED] Coloring parts of an image depending on value

Z

zendraw

Guest
So each part of this image, that is colored in teal, has max green and blue, but red varies betwean 0-255, and depending on that it shuld load a color from an array that contains the colors, but for some reason it remains white, while the parts shuld be colored in red.
here is the image
s_alefmask31.png

here is the code
https://cdn.discordapp.com/attachments/466249643865538569/620764465901862922/unknown.png

this is in the create event
Code:
for (var i=0; i<56; i++)
{
    col[i]=c_red;
}
also for some reason this doesnt let the game to compile and throws an error in the compiler
colr=color[floor((oc.r*255.0)/5.0)];
 

NightFrost

Member
I recall from some earlier testing I did, c_red evaluates to value 255, so what your array loop does is fill all array entries with 255. (That number also standing for red only has relevance to commands that accept such color codings, for everything else it is just a number like any other.) Shaders however deal color values as floats from 0 to 1, and everything beyond gets clamped to those. So in practise, for the shader, your array is filled with value 1. I'm not sure why colr=color[0] is not throwing an error since you've declared it as vec4 before and are now reading a single value into it. In any case as the input is not changing, the shader should be outputting a single solid color. Not sure what color since the part where you set it should fail to compile.

The part however that is throwing an error for you... I have dealt with arrays in shaders only one or two times but I'm pretty sure that's because you're trying to use a float as array index (floored yes, but still a float) instead of casting it as integer first, which array indices have to be.
 
Z

zendraw

Guest
well what do i do? it doesnt let me to simply color[0]/255.
 

GMWolf

aka fel666
C_red is a single number.
Shaders will expect multiple numbers (one for r, g, and b).
You need to convert your single number c_red to RGB data.
 
Z

zendraw

Guest
C_red is a single number.
Shaders will expect multiple numbers (one for r, g, and b).
You need to convert your single number c_red to RGB data.
how do i do that? make_color_rgb?
 

GMWolf

aka fel666
I'm not sure, bu i think if you have an array of values, and set it to a uniform of vec3s, then it will fill them in in groups of threes

So if your array is [0,1,2,3,4,5,6,7,8]
You will get the shader array [vec3(0,1,2), vec3(3,4,5), vec3(6,7,8)]
 
Z

zendraw

Guest
i will try that out later, right now i managed to make the shader work but i get weird resaults which i suspect is inacuracies in calculating which color to pick
here is video
https://www.dropbox.com/s/lle8v8cai7z4uki/2019-09-10 13-43-23.mkv?dl=0

and here is my shader code
Code:
//
// Simple passthrough fragment shader
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec4 col0;
uniform vec4 col1;
uniform vec4 col2;
uniform vec4 col3;
...
uniform vec4 col52;
uniform vec4 col53;
uniform vec4 col54;
uniform vec4 col55;

//uniform vec4 color[56];

void main()
{
    vec4 oc=texture2D(gm_BaseTexture, v_vTexcoord);
   
    vec4 colr=vec4(1.0, 1.0, 1.0, oc.a);
    int ie=int(floor(oc.r*56.0));
   
    //floor((oc.r*255.0)/5.0);
   
    if (ie==0) {colr=col0;}
    if (ie==1) {colr=col1;}
    if (ie==2) {colr=col2;}
....
    if (ie==52) {colr=col52;}
    if (ie==53) {colr=col53;}
    if (ie==54) {colr=col54;}
    if (ie==55) {colr=col55;}
   
    //colr=color[ie];
   
    gl_FragColor=colr;
}
the picking color code works fine, ive debuged it.

also another strange thing, the orange color appears white for some reason..
 

Bart

WiseBart
In the shader you define a vec4 array color, in which each vec4 consists of 4 floats.
If you send in the color values using a float array then that array should have a size of 56*4, assuming that you want to include the alpha value as well. 4 being the size in floats of a vec4.

Each four floats in the array then make up a single color, either rgba, argb or whichever way you decide to order them.

It may also be easier to directly send in the color components as values between 0 and 1.
Code:
col = array_create(56*4);    // 4 components per colour: r, g, b, a. Each four of them make up a vec4
for (var i=0; i<56; i+=1)
{
    var _colour = c_red;
   
    col[i*4+0]=colour_get_red(_colour)/255;
    col[i*4+1]=colour_get_green(_colour)/255;
    col[i*4+2]=colour_get_blue(_colour)/255;
    col[i*4+3]=1.0;          // alpha
}
Here's a small example to show how it looks:
Code:
|0   |1   |2   |3   |4   |5   |6   |7   |8   |9   |10  |11  |    // Index in col array (in this case: col = array_create(3*4))
|r1  |g1  |b1  |a1  |r2  |g2  |b2  |a2  |r3  |g3  |b3  |a3  |    // color component at index in col array
|vec4               |vec4               |vec4               |    // defined as uniform vec4 color[3];
|color[0]           |color[1]           |color[2]           |    // access inside shader
The same thing is true for vec3s or vec2s or even matrices.

Hope this clarifies it a bit :)
 
Z

zendraw

Guest
yeah that makes sense, also i fixed the coloring misplacement where you press on one part but it colors another, it was a calculation inprecision.

only thing left is why is the orange color white?

edit: this method works great, even the orange color is orange and not white but now i get the inprecise color fillings again, as seen from the video. im testing some numbers now, i hope i nail it.
 
Last edited:
Z

zendraw

Guest
is this the right way to get the right color? i tryed from 50 to 250+ and culdnt get the right number where it wuld color the piece it shuld.
Code:
uniform vec4 color[56];

uniform float multi;

void main()
{
    vec4 oc=texture2D(gm_BaseTexture, v_vTexcoord);
    
    vec4 colr=vec4(1.0, 1.0, 1.0, oc.a);
    
    int ie=int(floor((oc.r*multi)));
    
    colr=color[ie];
    
    gl_FragColor=colr;
}
 

GMWolf

aka fel666
Yeah that's because you don't have all the precision you need for 56 / 255.


Why have your colours range from 0-255 if a you need are 56 colours?
So, your sprite store RGB data as a value from 0-255, but your shader will see it as a value from 0-1.
What you can do is just multiply that value by 255 to have it in the 0-255 range again.

So if in the image editor you chose a value of '45', you will get 45 again in the shader.
 
Z

zendraw

Guest
i dont know really... i think some time ago from some calculations it resaulted in 55. but that shuldnt matter since i dont take the array in account.
i did try this floor((oc.r*255.0)/5.0); but fell flat again. i willt ry it again and see what happens.
 

GMWolf

aka fel666
Just oc.r * 255.
This will mean you have values between 0 and 255.

Then, in the sprite editor, when you choose your colours, choose the actual index values you want. Not multiplying or anything.

So, if you want to draw the 56th colour, in the sprite editor, choose a colour value of 56.
The shader will see this as (56/255).
So by multiplying it by 255, you get 56 again.
Now you can use that directly for your array..

To re-iterate:
In sprite editor, choose index values like 1, 5, 56, etc...
If you have 56 total colours in the array, then all your sprite colours will be between 0 and 55.
Then in shader:
Code:
int index = int(oc.r * 255);
colr =color[index];
 
Z

zendraw

Guest
effect is the same.
culd this be the problem? as written it makes sense to me but dunno
Code:
    var c=shader_get_uniform(shd_coloring, "color");
    var m=shader_get_uniform(shd_coloring, "multi");
    
    var ccol = array_create(56*4);    // 4 components per colour: r, g, b, a. Each four of them make up a vec4
    var ccl=0;
    for (var i=0; i<56; i+=1)
    {
        ccl=other.col[floor(i/4)];//<<<<<<<<<<<<???
    
        ccol[i*4+0]=colour_get_red(ccl)/255;
        ccol[i*4+1]=colour_get_green(ccl)/255;
        ccol[i*4+2]=colour_get_blue(ccl)/255;
        ccol[i*4+3]=1.0;          // alpha
    }
    
    shader_set_uniform_f_array(c, ccol);
    shader_set_uniform_f(m, other.multi);
    
    draw_self();
 
Z

zendraw

Guest
omg that was it, dont know why i decided to divide it by 4.... it all works perfectly now! ill mark the thread as solved
 
Z

zendraw

Guest
it simply stores the color from the array into that temp variable. col[] is the array where i store all the colors that i get from the surface.
 
Top