0
\$\begingroup\$

I have many mesh objects in my scene and I have applied an image texture to some objects but I want to set different colors for the other objects. How do I do that? This is my fragment shader

#version 430 core

out vec4 color;


in VS_OUT
{
    vec2 tc;
    vec3 normals;
 
} 

fs_in;


layout(binding=0)uniform sampler2D tex; 


// uniform mat4 model_matrix;



void main(void)
{

color= texture(tex, fs_in.tc); 
}

This is my code

glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    GLint tex_location = glGetUniformLocation(program, "tex");
    glUniform1i(tex_location, 0);
    Fence.Draw();

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, texture[1]);
    GLint tex_location1 = glGetUniformLocation(program, "tex");
    glUniform1i(tex_location1, 1);
    Ground.Draw();

    glActiveTexture(GL_TEXTURE0 + 2);
    glBindTexture(GL_TEXTURE_2D, texture[2]);
    GLint tex_location2 = glGetUniformLocation(program, "tex");
    glUniform1i(tex_location2, 2);  
    O_Roof.Draw();

    glActiveTexture(GL_TEXTURE0 + 3);
    glBindTexture(GL_TEXTURE_2D, texture[3]);
    GLint tex_location3 = glGetUniformLocation(program, "tex");
    glUniform1i(tex_location2, 3);
    O_BlueCandies.Draw();

Say I want to add the color blue to O_BlueCandies object and the color red to another one and so on how can I do that?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You need to implement the change.

There are many ways to do this.

For example, we can swap components. In fact, we could just pass a single int to rotate the components:

    vec4 col = texture(tex, fs_in.tc);
    vec4 rotated_color = vec4(
            col[(0 + rot) % 3],
            col[(1 + rot) % 3],
            col[(2 + rot) % 3],
            col.w
        );
    color = rotated_color; 

Which - given an integer rot - will rotate the RGB components. When rot is set to 0, you get the original coloring. With rot set to 1 green becomes red, red becomes blue, and blue becomes green. With rot set to 2 green becomes blue, blue becomes red, and red becomes green.


Or we could pass a 3 by 3 matrix which will allow all sort of transformations, and transform the color by that:

    vec4 col = texture(tex, fs_in.tc);
    vec4 transformed_color = vec4(m * col.xyz, col.w);
    color = transformed_color; 

In fact, I would argue for adding a translation so the center is at (0.5, 0.5, 0.5) and that way we can rotate without worrying of negatives (this also has the effect that a mirror transformation give you negative colors).

    vec4 col = texture(tex, fs_in.tc);
    vec3 offset = vec3(0.5, 0.5, 0.5);
    vec4 transformed_color = vec4((m * (col.xyz - offset) + offset), col.w);
    color = transformed_color; 

Then you can provide a rotation matrix m that maps the blue axis to the red axis (or viceversa). Of course, the red axis is x, the green axis is y, and the blue axis is z. So we want a rotation around the y axis.


Or you might implement a hue rotation algorithm. See How to change hue of a texture with GLSL?


Depending on the approach you take, You will to pass some data to the GPU about the change.

When does the change happen?

  • Are the blue and red objects two render calls?

    You can add an uniform for that (you already know how to declare and pass data via uniforms). Or they could be entirely different shader programs, but I'm not suggesting that.

  • Are the blue and red objects instances on the same render call?

    You can pass an uniform array or a texture, and access it using the instance id (you get gl_InstanceID in the vertex shader).

  • Are the blue and red objects a single mesh?

    You could use vertex attributes. Or you could pass an uniform array or a texture, and access it using vertex indexes (similarly to gl_InstanceID, in the vertex shader you get gl_VertexID).

This is not an exhaustive list of cases.

Note: You can pass information from the vertex shader to the fragment shader (make an out variable in the vertex shader and a matching in variable in the fragment shader).

See also: How to do instancing the right way in OpenGL

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .