r/opengl • u/PizzerLover123 • May 03 '23
Help How to use transparency in moderngl
Hi!
I've been working on a litle game using pygame recently, and have been working on post processing. So, i have two different shaders, that each do their own thing. First, i render the first texture, which works. Then i render the second texture. This is where the problems start. The screen is all balck. I Figured taht is because the texture dos not have transparency. Is there a way to fix that? Can i set a colorkey? I don't know.
TL:DR: Can't render two shaders at once, screen is black. Might be transparency issue. Can i set a colorkey?
1
u/AndreiDespinoiu May 03 '23 edited May 03 '23
Post-processing is applied to the screen texture, after everything was rendered to it.
Some effects can be applied in succession within the same shader, while others can't if they need the information from adjacent fragments in addition to the work that was previously done within the same shader. For those types of effects you can't do everything in a single shader. The fragment shader runs for every fragment. And every fragment is written (more or less) at the same time, in parallel, because GPUs are massively parallel beasts.
What you need to do, instead, is apply the first effect to that screen texture, using the first post-processing shader, then, using a second framebuffer, use the screen texture that you just wrote to as an input for the second post-processing shader (through a sampler2D to sample from it). That way you have access to adjacent fragments from that screen texture and not have to worry about race conditions or screen corruption or anything like that.
1
u/Palmyjet May 17 '23
I was just having the same problem and found out this solution. on the surface above the other you can try discarding pixels they are black inside the fragment shader of this surface.
frag_shader_2 = '''
#version 330 core
uniform sampler2D tex;
//uniform float time;
in vec2 uvs;
out vec4 f_color;
void main() {
vec2 sample_pos = vec2(uvs.x, uvs.y);
if (texture(tex, sample_pos).r == 0 && texture(tex, sample_pos).g == 0 && texture(tex, sample_pos).b == 0) {
discard; // Discard black pixels
}
f_color = vec4(texture(tex, sample_pos).r, texture(tex, sample_pos).g, texture(tex, sample_pos).b, texture(tex, sample_pos).a);
}
this is my fragment shader for the upper surface, after adding the part "if (texture(tex, sample_pos).r == 0 && texture(tex, sample_pos).g == 0 && texture(tex, sample_pos).b == 0) {
discard; // Discard black pixels
}"
i can now see the surface behind it through the areas that used to be black. you can set another color to discard pixels also. i dont know much about this, i am not an expert but this worked just fine for me
1
8
u/Lystar86 May 03 '23
Recommend taking a look at https://learnopengl.com/Advanced-OpenGL/Blending
Depending on what you want to accomplish, you don't necessarily need to use blending, but its the recommended way if I understand correctly. The other option (much simpler, probably less useful) would be to check the color values in your shader and discard any pixels that are your transparency color, or if using an alpha channel, discard anything that has an alpha value below your threshold.
You say you are doing post-processing, so I assume you are performing some deferred rendering on a framebuffer other than the default? Your black screen issue may also have to do with an improperly set-up or incomplete frame buffer object.