How to compute the average color of fragments drawn at the same place.

Hi! For oit rendering I do something like this :

Sprite 1 : (1,0,0,0.25) Z = 0.
Sprite 2 : (0,0,1,0.5) Z = 1.
Sprite 3 : (0,1,0,0.75) Z = 2.

The basic alpha blending with sorted sprites gives :

Sprite1 blended with sprite2 :
(1,0,0)0.5+(0,0,1)(1-0.5) = (0.5,0,0)+(0,0,0.5)=(0.5,0,0.5)
And final result is :
(0,1,0)0.75+(0.5,0,0.5)(1-0.75)=(0,0.75,0)+(0.125,0.75,0.125)

sprite 1 (DSTCOLOR) with sprite 3 (SRCCOLOR) :
I use back to front blending because sprite3 is before sprite1 so the correct equation is : SRCCOLOR * SRCALPHA + DSTCOLOR * (1-SRCALPHA)
SRCCOLOR (0,1,0)0.75=(0,0.75,0)
DSTCOLOR (1,0,0)
(1-0.75)=(0.25,0,0)
sprite 2 (DSTCOLOR) with sprite 3 (SRCCOLOR) :
I use front to back blending because sprite2 is behind sprite3 so the correct equation is : SRCCOLOR * DSTALPHA + DSTCOLOR * (1-SRCALPHA)
SRCCOLOR (0,1,0)0.75=(0,0.75,0)
DSTCOLOR (0,0,1)
(1-0.75)=(0,0,0.25)

Then I want to compute the average of the two parts of the equations and store it into two textures in an optimized way.

Texture1 :
((0,0.75,0)+(0,0.75,0))0.5=(0,1.5,0)0.5=(0,0.75,0)
(DSTCOLOR
ONE+SRCCOLOR
SRCALPHA)*0.5

Texture2 :
(0.25,0,0)+(0,0,0.25)=(0.25,0,0.25)0.5=(0.125,0,0.125)
(DSTCOLOR
ONE+SRCCOLOR*ONEMINUSSRCALPHA)*0.5

I need to read the color of the framebuffer, it requires one draw per sprite so it’s slow, so I need to perform all additions in once and then divide by the number of sprites but the max value of a texture color is 1, I’m afraid it’s not enougth.

The color of the final texture we’ll be :

Texture :

(0,0.75,0)+(0.125,0,0.125)=(0.125,0.75,0.125)

It’s the same color so it’s correct.

It’s since a couple of years that I’m searching how to perform optimized OIT rendering with a compatible openGL version (I have an old graphic card) for my game engine, first it worked but only with two layers, now I’ve found the solution for multiple layers but I don’t know how to perform it in an optimized way. (Drawing every sprites with a single draw call)

Mmmm…I tried glClampColor and set the fragment color clamp to false but it’s not working.

Ok I’ve implemented my solution, it works for semi-transparent sprites but I’ve a problem with opaque sprites.


sprite 1 (1, 0, 0, 1)
sprite 2 (0, 0, 1, 1)
sprite 3 (0, 1, 0, 1)
sprite 1 (SRCCOLOR) with sprite 3 (DSTCOLOR) :
SRCCOLOR (1,0,0) * (1-1) =(0,0,0)
DSTCOLOR (0,1,0) * 1 = (0,1,0)
sprite 2 (SRCCOLOR) with the frame buffer color. (DSTCOLOR, blue here) :
SRCCOLOR (0,0,1)*(1-1)=(0,0,0)
DSTCOLOR (0,1,0)*0.1=(0,1,0)

Texture1 : 
((0,0,0)+(0,0,0))*0.5=(0,0,0)*0.5=(0,0,0)
(DSTCOLOR*ONE+SRCCOLOR*ONEMINUSDSTALPHA)*0.5

Texture2 : 
(0,1,0)+(0,1,0)=(0,2,0)*0.5=(0,1,0)
(DSTCOLOR*ONE+SRCCOLOR*DSTALPHA)*0.5

Texture : 
(0,0,0)+(0,1,0)=(0,1,0)



Normaly this blending equation I set up for rendering texture 2 :


currentStates.blendMode=sf::BlendMode(sf::BlendMode::Factor::DstAlpha,sf::BlendMode::Factor::One, sf::BlendMode::Equation::Add, sf::BlendMode::Factor::OneMinusDstAlpha, sf::BlendMode::Factor::One, sf::BlendMode::Equation::Add);
            unsigned int nb = 0;
            for (unsigned int i = 0; i < m_instances.size(); i++) {
                if (m_instances[i].getMaterial().getTexture() == nullptr)
                    frameBufferGenerator.setParameter("haveTexture", 0);
                else
                    frameBufferGenerator.setParameter("haveTexture", 1);
                currentStates.texture = m_instances[i].getMaterial().getTexture();
                averageBlendEqPart2.draw(m_instances[i].getAllVertices(), currentStates);
                nb += m_instances[i].getVertexArrays().size();
            }


Should give me blue but it doesn’t give me blue as excpected it gives me semi-transparent blue. So when I’m performing the additive blending at the end it adds me blue with semi-transparent blue so the texture is semi-transparent. :confused:

Why the blending equation gives me semi-transparent sprite or I don’t have any semi-transparent sprite here!

Ok now I have made it working!