Change all opaque pixels from a texture to red

hello
i’m trying to learn GLSL. right now what I want to do is convert all opaque colors of a texture (sampler2D) to a solid red, and leave full transparent pixels unchanged.
I have this so far:

#version 460

uniform sampler2D tex;
out vec4 frag_color_out;

void main(){
    vec4 pixel = texture2D(tex, vec2(10, 10));
    if(pixel.a != 0.0){
        frag_color_out = vec4(1.0,0.0,0.0,1.0);
    }
}

right now, it just turns the whole window to red… and I’m not so sure that the second parameter of the vec4 pixel should be that.

i don’t know if it helps, but i’m calling this shader from inside a SFML program, and I have no errors in the execution.
sorry if it is a too newbie question, but i have been struggling with this for days now… and almost all tutorials i found were talking about gl_FragColor, which seems to be deprecated (and returns me an error if I try to use it)

thanks in advance!

That’s probably because you’re sampling the same texel for every fragment. If you want to map a texture, you need texture coordinates. These are often obtained simply by interpolating vertex attributes, but they can be obtained from arbitrarily complex expressions (usually involving vertex attributes, but sometimes from gl_FragCoord).

I suggest first learning how to just map textures without any kind of processing.

Apart from that, not writing to a fragment shader output doesn’t make the fragment transparent. It just means that the colour will be undefined. If you want to leave a particular pixel in the framebuffer unchanged, use a discard statement. If you just want to leave the colour unchanged (while updating the depth buffer and/or stencil buffer), set the output colour to something with a zero alpha component and enable blending.

hi! thanks for your answer
I made some changes then, but its not perfect yet. i couldn’t find exactly how to map the texture…

uniform sampler2D tex;
in vec2 tex_coord;
out vec4 frag_color_out;

void main(){
    vec4 pixel = texture2D(tex, tex_coord);
    if(pixel.a != 0.0){
        frag_color_out = vec4(1.0, 0.0, 0.0, 1.0);
    }
    else{
        //frag_color_out = vec4(0.0, 0.0, 0.0, 0.0);
        discard;
    }
}

now I have a flickering screen:
flick

its pattern changes based on the texture I use, so its starting to make sense, I guess…

Whatever is causing that, it isn’t the fragment shader.

Read a tutorial that covers texture mapping.

I did read some things, but couldn’t get it right. for some reason this works:

uniform sampler2D texture;
uniform vec4 color_id;

void main(){
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
    if(pixel.a != 0.0){
        gl_FragColor = color_id;
    }
    else{
        discard;
    }
}

but this does not:

#version 460

uniform sampler2D texture;
uniform vec4 color_id;
in vec2 tex_coord;
out vec4 frag_color_out;

void main(){
    vec4 pixel = texture2D(texture, tex_coord);
    if(pixel.a != 0.0){
        frag_color_out = color_id;
    }
    else{
        discard;
    }
}
  1. Does your implementation support 4.6?
  2. Have you configured the attribute array corresponding to tex_coord?
  3. Have you bound frag_color_out to a colour attachment?

1 - probably yes, I get no error regarding that. but the results are the same using version 330
2- no, and i can’t find how to. “tex_coord[0].xy” does not work (probably it uses only the first element of the whole array?)
3- isn’t that what I get by declaring the “out vec4”?

this tutorial (www.lighthouse3d. com/tutorials/glsl-tutorial/texture-coordinates - sorry, I cant include links in posts) seemed to do something like I need, but based on it I got the flickering results. the only way I can see to make it work is iterating over all pixels in the texture (maybe with a for loop), would be that the solution? I just wanted to avoid that because i did read somewhere that using this kind of loops in GLSL is not a good idea, as the aplication may become really slow.

Replace

glTexCoordPointer(size, type, stride, pointer);
glEnable(GL_TEXTURE_COORD_ARRAY);

with

GLuint index = glGetAttribLocation(program, "tex_coord");
glVertexAttribPointer(index, size, type, GL_TRUE, stride, pointer);
glEnableVertexAttribArray(index);

If you’re using glBegin/glEnd, replace glTexCoord or glMultiTexCoord with glVertexAttrib.

Just tex_coord is correct.

You need to specify the association between fragment shader outputs and colour attachments. If you only have the one output and one attachment, the output will probably be bound to colour attachment 0, but you should force the case with glBindFragDataLocation in the client or a layout(location=...) qualifier in the shader.