Making a sprite of different colors

I try to make games. I write code, try to draw and want to learn how to make music. I drew the character and I needed to make it so that he could change the color of his clothes. The solution came at first one thing, but then came up with a simpler one.





The first solution I thought of was to make the walls have different transparency, and then you can set the transparency with the help of a shader. In the shader, the transparency is already checked and the specified color is indicated. You may be interested in this, but I will still give the code for the sprite class and shader. I like the gray color and I usually draw something in its shades. Here I drew a little man.





. . .





human colors
-------------------------------------------
body front #6a6a6a 0.41 0.41 0.41
body up #959595 0.58 0.58 0.58
arm #a6a6a6  0.65 0.65 0.65
arm blick  #c1c1c1  0.75 0.75 0.75
arm blacked #8a8a8a  0.23
body down #5b5b5b 0.35 0.35 0.35
left legs blacked #4c4c4c 0.29 0.29 0.29
left legs blick #5c5c5c 0.36 0.36 0.36
right legs blacked #656565 0.39 0.39 0.39
right legs blick #808080 0.50 0.50 0.50
      
      



.





Sprite::Sprite (int x, int y, int z, const char *path) {
    this->visibility = true;
    this->isAnimate = false;
    this->animator = new Animator ();
    this->check = 0;
    this->commonData = nullptr;
    this->frame = nullptr;
    this->trigger_shadow = 0;
    
    this->z = glm::vec2 ((float) z, 1.0f);
    
    GameObject::ortho = glm::ortho (0.0f, 1.0f, 1.0f, 0.0f, -100.0f, 100.0f);
    
    float xx = ((float) x) / ((float) mea_width);
    float yy = ((float) y) / ((float) mea_height);
    float zz = z;
    GameObject::pos = glm::translate (glm::mat4(1.0f), glm::vec3 (xx, yy, zz));

    GameObject::model = glm::mat4(1.0f);

    this->shader = shaderController->program[SHADERS::SPRITE];
    this->type_shader = SHADERS::SPRITE;

    gl::UseProgram (shaderController->program[SHADERS::SPRITE]);
    this->location_view = gl::GetUniformLocation (shaderController->program[SHADERS::SPRITE], "view");
    this->location_tex = gl::GetUniformLocation (shaderController->program[SHADERS::SPRITE], "tex");
    this->location_pos = gl::GetUniformLocation (shaderController->program[SHADERS::SPRITE], "pos");
    this->location_model = gl::GetUniformLocation (shaderController->program[SHADERS::SPRITE], "model");
    this->location_scale = gl::GetUniformLocation (shaderController->program[SHADERS::SPRITE], "scale");
    this->location_z = gl::GetUniformLocation (shaderController->program[SHADERS::SPRITE], "zCoord");

    

    if (path != nullptr) loadSprite (path);
}
      
      



, 1920x1080 - mea_width = 1920 mea_height = 1080. Ortho 1.0f , , mea_*. full hd . 1920x1080, 1.0f. , .





float xx = ((float) x) / ((float) mea_width);
float yy = ((float) y) / ((float) mea_height);
      
      



, .





void Sprite::setShader (int shader) {
    this->type_shader = shader;

    switch (shader) {
        case SHADERS::SPRITE:
            this->shader = shaderController->program[SHADERS::SPRITE];
            shader = this->shader;
            gl::UseProgram (shader);
            this->location_view = gl::GetUniformLocation (shader, "view");
            this->location_tex = gl::GetUniformLocation (shader, "tex");
            this->location_pos = gl::GetUniformLocation (shader, "pos");
            this->location_model = gl::GetUniformLocation (shader, "model");
            this->location_scale = gl::GetUniformLocation (shader, "scale");
            this->location_z = gl::GetUniformLocation (shader, "zCoord");
        break;
        case SHADERS::SPRITE_WITH_ALPHA_COLORS:
            this->shader = shaderController->program[SHADERS::SPRITE_WITH_ALPHA_COLORS];
            shader = this->shader;
            gl::UseProgram (shader);
            this->location_view = gl::GetUniformLocation (shader, "view");
            this->location_tex = gl::GetUniformLocation (shader, "tex");
            this->location_pos = gl::GetUniformLocation (shader, "pos");
            this->location_model = gl::GetUniformLocation (shader, "model");
            this->location_scale = gl::GetUniformLocation (shader, "scale");
            this->location_z = gl::GetUniformLocation (shader, "zCoord");
            this->location_one = gl::GetUniformLocation (shader, "color_wall");
            this->location_two = gl::GetUniformLocation (shader, "color_floor");
        break;
        case SHADERS::SPRITE_HUMAN:
            this->shader = shaderController->program[SHADERS::SPRITE_HUMAN];
            shader = this->shader;
            gl::UseProgram (shader);
            this->location_view = gl::GetUniformLocation (shader, "view");
            this->location_tex = gl::GetUniformLocation (shader, "tex");
            this->location_pos = gl::GetUniformLocation (shader, "pos");
            this->location_model = gl::GetUniformLocation (shader, "model");
            this->location_scale = gl::GetUniformLocation (shader, "scale");
            this->location_z = gl::GetUniformLocation (shader, "zCoord");
            this->location_one = gl::GetUniformLocation (shader, "color_up");
            this->location_two = gl::GetUniformLocation (shader, "color_down");
        break;
    }
    
}
      
      



, within 1920x1080.





void Sprite::setPos (int x, int y, int z) {
    float xx = ((float) x) / ((float) mea_width);
    float yy = ((float) y) / ((float) mea_height);
    float zz = z;
    GameObject::pos = glm::translate (glm::mat4(1.0f), glm::vec3 (xx, yy, zz));
    this->x = x;
    this->y = y;
}
      
      



I use the same calculation to set the size of the sprite, but I probably won't give the code here.





rendering occurs as a sprite and here is an example of rendering with the desired frame.





void Sprite::draw_frame_with_color (int frame) {

    gl::UseProgram (this->shader);

    gl::Uniform1i (this->location_tex, 0);

    gl::ActiveTexture (gl::TEXTURE0);

    gl::BindTexture (gl::TEXTURE_2D, this->frame[frame]);
   
    gl::Uniform3f (this->location_one, this->color_one.r, this->color_one.g, this->color_one.b);
    gl::Uniform3f (this->location_two, this->color_two.r, this->color_two.g, this->color_two.b);

    gl::UniformMatrix4fv (this->location_view, 1, gl::FALSE_, &GameObject::ortho[0][0]);

    gl::UniformMatrix4fv (this->location_pos, 1, gl::FALSE_, &GameObject::pos[0][0]);

    gl::UniformMatrix4fv (this->location_model, 1, gl::FALSE_, &GameObject::model[0][0]);
    gl::UniformMatrix4fv (this->location_scale, 1, gl::FALSE_, &GameObject::scale[0][0]);

    gl::Uniform2f (this->location_z, this->z[0], this->z[1]);

    gl::BindVertexArray (this->vao);

    gl::EnableVertexAttribArray (0);
    gl::EnableVertexAttribArray (1);

    gl::DrawArrays (gl::TRIANGLES, 0, 6);   
}
      
      



As you can see from the code, I am passing two uniform variables to the shader, color_one and color_two. They just serve the purpose of specifying the color for the character's clothing. The fragment shader turned out like this.





#version 330 core

out vec4 fragColor;

in vec2 texCoord;

uniform sampler2D tex;

uniform vec3 color_up;
uniform vec3 color_down;

void main () {
    vec3 color = texture (tex, texCoord).rgb;
    float r = color.r;
    float g = color.g;
    float b = color.b;
    r *= 100;
    g *= 100;
    b *= 100;
    int rr = int(r);
    int gg = int(g);
    int bb = int(b);
    r = rr;
    g = gg;
    b = bb;
    r *= 0.01;
    g *= 0.01;
    b *= 0.01;
    color = vec3 (r, g, b);

    if (color == vec3 (0.41, 0.41, 0.41)) {
        fragColor = vec4 (color_up, 1.0);
    } else if (color == vec3 (0.58, 0.58, 0.58)) {
        vec3 col = color_up + vec3 (0.17, 0.17, 0.17);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.65, 0.65, 0.65)) {
        vec3 col = color_up + vec3 (0.24, 0.24, 0.24);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.75, 0.75, 0.75)) {
        vec3 col = color_up + vec3 (0.34, 0.34, 0.34);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.23, 0.23, 0.23)) {
        vec3 col = color_up - vec3 (0.18, 0.18, 0.18);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.35, 0.35, 0.35)) {
        fragColor = vec4 (color_down, 1.0);
    } else if (color == vec3 (0.29, 0.29, 0.29)) {
        vec3 col = color_down - vec3 (0.06, 0.06, 0.06);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.36, 0.36, 0.36)) {
        vec3 col = color_down + vec3 (0.01, 0.01, 0.01);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.39, 0.39, 0.39)) {
        vec3 col = color_down + vec3 (0.04, 0.04, 0.04);
        fragColor = vec4 (col, 1.0);
    } else if (color == vec3 (0.50, 0.50, 0.50)) {
        vec3 col = color_down + vec3 (0.15, 0.15, 0.15);
        fragColor = vec4 (col, 1.0);
    } else {
        fragColor = texture (tex, texCoord);
    }
}
      
      



As you can see from the code, it just checks for a color shade and plus or minus the shade to get the correct color. I connected the same shader for the tables, and now when the character comes to the table and disappears, he transfers his colors to the table and the table already indicates the desired color by these shades. And it begins to seem that the character is really the one who came to the table.








All Articles