Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL photoshop overlay blend mode

Im trying to implement a particle system (using OpenGL 2.0 ES), where each particle is made up of a quad with a simple texture

the red pixels are transparent

the red pixels are transparent. Each particle will have a random alpha value from 50% to 100%

Now the tricky part is i like each particle to have a blendmode much like Photoshop "overlay" i tried many different combinations with the glBlendFunc() but without luck.

I dont understand how i could implement this in a fragment shader, since i need infomations about the current color of the fragment. So that i can calculate a new color based on the current and texture color.

I also thought about using a frame buffer object, but i guess i would need to re-render my frame-buffer-object into a texture, for each particle since each particle every frame, since i need the calculated fragment color when particles overlap each other.

Ive found math' and other infomations regrading the Overlay calculation but i have a hard time figuring out which direction i could go to implement this.

  • http://www.pegtop.net/delphi/articles/blendmodes/
  • Photoshop blending mode to OpenGL ES without shaders

Im hoping to have a effect like this:

overlapping particles and how they blend together

like image 908
Mads Lee Jensen Avatar asked Oct 18 '13 21:10

Mads Lee Jensen


2 Answers

You can get information about the current fragment color in the framebuffer on an iOS device. Programmable blending has been available through the EXT_shader_framebuffer_fetch extension since iOS 6.0 (on every device supported by that release). Just declare that extension in your fragment shader (by putting the directive #extension GL_EXT_shader_framebuffer_fetch : require at the top) and you'll get current fragment data in gl_LastFragData[0].

And then, yes, you can use that in the fragment shader to implement any blending mode you like, including all the Photoshop-style ones. Here's an example of a Difference blend:

// compute srcColor earlier in shader or get from varying
gl_FragColor = abs(srcColor - gl_LastFragData[0]);

You can also use this extension for effects that don't blend two colors. For example, you can convert an entire scene to grayscale -- render it normally, then draw a quad with a shader that reads the last fragment data and processes it:

mediump float luminance = dot(gl_LastFragData[0], vec4(0.30,0.59,0.11,0.0));
gl_FragColor = vec4(luminance, luminance, luminance, 1.0);

You can do all sorts of blending modes in GLSL without framebuffer fetch, but that requires rendering to multiple textures, then drawing a quad with a shader that blends the textures. Compared to framebuffer fetch, that's an extra draw call and a lot of schlepping pixels back and forth between shared and tile memory -- this method is a lot faster.

On top of that, there's no saying that framebuffer data has to be color... if you're using multiple render targets in OpenGL ES 3.0, you can read data from one and use it to compute data that you write to another. (Note that the extension works differently in GLSL 3.0, though. The above examples are GLSL 1.0, which you can still use in an ES3 context. See the spec for how to use framebuffer fetch in a #version 300 es shader.)

like image 185
rickster Avatar answered Oct 13 '22 10:10

rickster


I suspect you want this configuration: Source: GL_SRC_ALPHA Destination: GL_ONE. Equation: GL_ADD

If not, it might be helpful if you could explain the math of the filter you're hoping to get.

like image 37
Sorin Avatar answered Oct 13 '22 11:10

Sorin