# Shader blending ( Get previous pixel )

This topic is 2039 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello.

I want to control the way opengl blend transparent surfaces.

#version 120
varying vec2 texcoord;

void main()
{
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
texcoord = gl_MultiTexCoord0.xy;
}


#version 120
uniform sampler2D img;
varying vec2 texcoord;

void main()
{
vec4 tex = texture2D ( img, texcoord );
gl_FragColor = tex;
}


Those are my basic texture rendering codes.
What i need is to get somehow the pixel what is behind that thing what is correctly in shader.

It would be so good to have control over it.
Also readed the basics of shaders, did not get any ideas how to do it.

Reading on internet, they said that opengl offers some blend functions. Already tried them.
Its nothing wrong with them but the way they act doesnt pleasure me. I really need to controll how pixels are blended.
Is there someone wise who have solution to my problem?
Thanks!

##### Share on other sites

http://wiki.delphigl.com/index.php/glBlendFunc

You need to set "GL_ONE" for dfactor, and depending on how you want to apply the new pixel it will probably also bee "GL_ONE" for sfactor (the first param).

##### Share on other sites

That is a really good source yet not exactly what i wanted.
Il give you code example:

#version 120
uniform sampler2D img;
varying vec2 texcoord;

void main()
{
vec4 tex = texture2D ( img, texcoord );
vec4 behindpixel = ?
gl_FragColor = (behindpixel * 0.5 ) + (tex * 0.5 );
}


In theory i can blend pixels without using glBlendFunc.
Getting the that pixel what is behind will give me so much control. I can make so many new nice blending types.

If i can somehow know where the pixel will be in screen ( the pixel origin in screen ( x, y coords ) )
Then i can store them and use them. Also the order will not matter ( if the back pixel is rendered first or the front one )
I can figure it out somehow.

Edited by Gyiove

##### Share on other sites

AFAIK fragment shaders cannot read framebuffers directly. However, you can use an FBO with a texture attached as color target in a first pass, and bind those texture for sampling in a second pass. That should give you the access you need.

Just for curiosity, what are those kinds of blending you are not able to create with the standard blend-functions?

Edited by haegarr

##### Share on other sites

Nope, that can't be done. You can't read and write to the same texture due to how desktop GPUs work. It can however be done on tile based mobile GPUs.

##### Share on other sites

AFAIK fragment shaders cannot read framebuffers directly. However, you can use an FBO with a texture attached as color target in a first pass, and bind those texture for sampling in a second pass. That should give you the access you need.

I'm familiar with that way and im afraid that it will be ineffective.
Not sure how fast the function is but still believe that there are some other ways, there must be something.

Just for curiosity, what are those kinds of blending you are not able to create with the standard blend-functions?

For example one is that if you are looking out of the window, pixels will be different color but the window texture will be white for example.

##### Share on other sites

You can't read from the same target that you currently render to. In order to make what you want to work, you would need to use two rendertargets, and ping-pong between them. First write to #1, and in the next pass you set #1 as uniform sampler and write to #2, and so on.

However, are you sure you really need this? What you wrote here:

gl_FragColor = (behindpixel * 0.5 ) + (tex * 0.5 );


can be realised using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MIN_SRC_ALPHA) and outputting

void main()
{
vec3 tex = texture2D ( img, texcoord ).rgb;
gl_FragColor = vec4(tex, 0.5f);
}


I belive that for effects that only need the underlying pixel of the current operation and only want to modify that value in a way you posted, then glBlendFunc is all you need. Really look closely at the page I posted you and look at the available options, there is almost everything you could need. Otherwise, you can take my first suggestion.

EDIT:

I'm familiar with that way and im afraid that it will be ineffective.
Not sure how fast the function is but still believe that there are some other ways, there must be something.

Its as fast as switching input textures can be, FBOs are standard and used so widley for advanced graphical effects that the overhead is neglectible. Handling the swapping can be a little awkward to handle, thats all about it.

For example one is that if you are looking out of the window, pixels will be different color but the window texture will be white for example.

This looks like a standard-way for alpha blending, I even more belive now that you will be fine if you just use glBlendFunc correctly.

Edited by Juliean

##### Share on other sites

That thing what make the wall yellow.
The color depens on that texture what is right now in the fragment shader.
As far, you guys have been really helpful, im glad you want to help me. Thank you so much!
Anyway, i'm really beginner, yet dont know the ways and functions.
I've tried all options of glBlendfunc yet did not succeed in creating the effect you see up, right in the corner.

##### Share on other sites

I've tried all options of glBlendfunc yet did not succeed in creating the effect you see up, right in the corner.

Did you call glEnable(GL_BLEND) anywhere? This is definately doable with standard blending, people would have gotten insane if they required to pingpong rendertargets in order for simple glass effects.

##### Share on other sites

The one ohter problem is:

// vertex shader

#version 120
varying vec2 texcoord;

void main()
{
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
texcoord = gl_MultiTexCoord0.xy;
}

#version 120
uniform sampler2D img;
varying vec2 texcoord;

void main()
{
vec4 tex = texture2D ( img, texcoord );
if( tex.r < 0.3 && tex.g < 0.3 && tex.b > 0.6 ) tex *= 0.0;
else tex.a = 1.0;
gl_FragColor = tex;
}


glUniform1i(glGetUniformLocation(program,"img"),0);
glBindTexture(GL_TEXTURE_2D, triangles[a].texture);
glActiveTexture(GL_TEXTURE0);
if(triangles[a].texture == 1) // The first texture is not supposed to be transparent
{
glDisable(GL_BLEND);
}
else
{
glEnable (GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
}

glBegin(GL_TRIANGLES);
for( c = 0; c < 3; c++ )
{
glTexCoord2d(triangles[a].uvmap[c][0], -triangles[a].uvmap[c][1]);
glNormal3d(triangles[a].normals[c][0], triangles[a].normals[c][1], triangles[a].normals[c][2]);
glVertex3d(-triangles[a].vertex[c][1], triangles[a].vertex[c][2],triangles[a].vertex[c][0]);
}
glEnd();


The one reason why i really wanted to get that pixel what is behind.
Tried all those blending flags what are in the page you gave.

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 16
• 13
• 9
• 11
• 15