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

Discussion in 'Programming' started by zendraw, Sep 10, 2019.

Tags:
  1. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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)];
     
  2. NightFrost

    NightFrost Member

    Joined:
    Jun 24, 2016
    Posts:
    1,921
    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.
     
  3. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    well what do i do? it doesnt let me to simply color[0]/255.
     
  4. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    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.
     
  5. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    how do i do that? make_color_rgb?
     
  6. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    Make color RGB will use red, greed and blue values and gives you a single number.

    What you want is color_get_red, color_get_green and color_get_blue.
     
  7. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    but how do i pass this as an array to the shader?
     
  8. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    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)]
     
    zendraw and Bart like this.
  9. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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..
     
  10. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    165
    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 :)
     
    zendraw likes this.
  11. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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: Sep 10, 2019
  12. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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;
    }
    
     
  13. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    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.
     
  14. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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.
     
  15. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    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];
    
     
    zendraw likes this.
  16. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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();
     
  17. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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
     
  18. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    What is this doing?

    Cool
     
  19. zendraw

    zendraw Member

    Joined:
    Jun 20, 2016
    Posts:
    1,362
    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.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice