Hi! For my new OIT rendering technique I need to compute the alpha value in a separate texture.
When I compute colors it’s good :
const std::string addSrcColorFragShader =
"#version 130
"
"in mat4 projMat;"
"uniform vec3 resolution;"
"uniform sampler2D frontBuffer;"
"uniform sampler2D depthBuffer;"
"uniform sampler2D stencilBuffer;"
"uniform sampler2D texture;"
"uniform float haveTexture;"
"void main() {"
"vec2 position = (gl_FragCoord.xy / resolution.xy);"
"vec4 front_color = texture2D(frontBuffer, position);"
"float max_z = texture2D(depthBuffer, position).z;"
"float nbLayers = texture2D (stencilBuffer, position).a;"
"vec4 texel = texture2D(texture, gl_TexCoord[0].xy);"
"float z = (gl_FragCoord.w != 1.f) ? (inverse(projMat) * vec4(0, 0, 0, gl_FragCoord.w)).w : gl_FragCoord.z;"
"vec4 colors[2];"
"colors[1] = texel * gl_Color;"
"colors[0] = gl_Color;"
"bool b = (haveTexture > 0.9);"
"vec4 color = colors[int(b)];"
"colors[1] = vec4(color.rgb * (1 - front_color.a), 1);"
"colors[0] = vec4(0, 0, 0, 0);"
"b = (z < max_z);"
"gl_FragColor = colors[int(b)];"
"}";
const std::string addDstColorFragShader =
"#version 130
"
"in mat4 projMat;"
"uniform vec3 resolution;"
"uniform sampler2D frontBuffer;"
"uniform sampler2D depthBuffer;"
"uniform sampler2D stencilBuffer;"
"uniform sampler2D texture;"
"uniform float haveTexture;"
"void main() {"
"vec2 position = (gl_FragCoord.xy / resolution.xy);"
"vec4 front_color = texture2D(frontBuffer, position);"
"float max_z = texture2D(depthBuffer, position).z;"
"float nbLayers = texture2D(stencilBuffer, position).a;"
"vec4 texel = texture2D(texture, gl_TexCoord[0].xy);"
"float z = (gl_FragCoord.w != 1.f) ? (inverse(projMat) * vec4(0, 0, 0, gl_FragCoord.w)).w : gl_FragCoord.z;"
"vec4 colors[2];"
"colors[1] = texel * gl_Color;"
"colors[0] = gl_Color;"
"bool b = (haveTexture > 0.9);"
"vec4 color = colors[int(b)];"
"colors[1] = vec4(front_color.rgb * front_color.a, 1);"
"colors[0] = vec4(0, 0, 0, 0);"
"b = (z < max_z || (z >= max_z && nbLayers <=1));"
"gl_FragColor = colors[int(b)];"
"}";
const std::string avgFragShader =
"#version 130
"
"in mat4 projMat;"
"uniform sampler2D texture;"
"uniform sampler2D stencilBuffer;"
"uniform vec2 resolution;"
"void main() {"
"vec2 position = (gl_FragCoord.xy / resolution.xy);"
"vec4 color = texture2D(texture, gl_TexCoord[0].xy);"
"float nbLayers = texture2D(stencilBuffer, position).a;"
"vec4 colors[2];"
"colors[0] = vec4(0, 0, 0, 0);"
"colors[1] = vec4(color.r / nbLayers, color.g / nbLayers, color.b / nbLayers, 1);"
"bool b = (nbLayers > 0);"
"gl_FragColor = colors[int(b)];"
"}";
But when I want to compute the alpha here to add the correct alpha value to the final texture the values here are always equal to one.
const std::string setAlphaFragShader =
"#version 130
"
"uniform vec3 resolution;"
"uniform sampler2D texture;"
"uniform sampler2D frameBuffer;"
"void main() {"
"vec2 position = (gl_FragCoord.xy / resolution.xy);"
"float alpha = texture2D(texture, gl_TexCoord[0].xy).a;"
"vec4 color = texture2D(frameBuffer, position);"
"gl_FragColor = vec4(color.rgb * alpha, alpha);"
"}";
I draw every nearest sprites first because I need to blend every sprites with the nearest, in one shader I perform addition of all SRCCOLCOR * (ONE_MINUS_SRC_COLOR) with a dethtest to don’t blend the sprite with itselfs. (So I use additive blending)
In another shader, I add every DSTCOLOR * DSTALPHA I do a dethtest to don’t blend the sprite with itselfs but I need to draw it if it’s the single fragment at this position.
In another shader a compute the average color of the sum of SRCCOLCOR * (ONE_MINUS_SRC_COLOR) and I compute the average of the sum of DSTCOLOR * DSTALPHA and then I add the two averaged values with additive blending.
(Ok colours are correct when I dispaly the final texture)
I set alpha to 1 because if I do the average of DSTALPHA and SRCALPHA * ONEMINUSDSTALPHA, it doesn’t get me the correct final alpha. So I need to compute it in a separate texture.
I draw the scene here :
[code=cpp]
for (unsigned int i = 0; i < m_instances.size(); i++) {
if (m_instances[i].getMaterial().getTexture() == nullptr)
depthBufferGenerator.setParameter(“haveTexture”, 0);
else
depthBufferGenerator.setParameter(“haveTexture”, 1);
currentStates.shader=&depthBufferGenerator;
currentStates.texture=m_instances[i].getMaterial().getTexture();
depthBuffer.draw(m_instances[i].getAllVertices(),currentStates);
currentStates.shader = nullptr;
currentStates.blendMode = BlendNone;
frontBuffer.draw(m_instances[i].getAllVertices(), currentStates);
stencilBuffer.draw(m_instances[i].getAllVertices(),currentStates);
}
frontBuffer.display();
frontBufferSprite.setCenter(view.getPosition());
And later ...
[code=cpp]
currentStates.blendMode = sf::BlendMode(sf::BlendMode::Factor::Zero, sf::BlendMode::Factor::Zero, sf::BlendMode::Equation::Add, sf::BlendMode::Factor::One, sf::BlendMode::Factor::Zero, sf::BlendMode::Equation::Add);
alpha.draw(frontBufferSprite, currentStates);
currentStates.blendMode = sf::BlendMode(sf::BlendMode::Factor::Zero,sf::BlendMode::Factor::Zero,sf::BlendMode::Equation::Add,sf::BlendMode::Factor::OneMinusDstAlpha, sf::BlendMode::Factor::One, sf::BlendMode::Equation::Add);
currentStates.shader=&frameBufferGenerator;
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();
alpha.draw(m_instances[i].getAllVertices(), currentStates);
}
alpha.display();
alphaSprite.setCenter(view.getPosition());
The problem : when I compute the final color here :
const std::string setAlphaFragShader =
"#version 130
"
"uniform vec3 resolution;"
"uniform sampler2D texture;"
"uniform sampler2D frameBuffer;"
"void main() {"
"vec2 position = (gl_FragCoord.xy / resolution.xy);"
"float alpha = texture2D(texture, gl_TexCoord[0].xy).a;"
"vec4 color = texture2D(frameBuffer, position);"
"gl_FragColor = vec4(color.rgb * alpha, alpha);"
"}";
If I display only alpha values here, it’s an all white texture so all alpha values are set to one. (even if my sprite are transparent)
Why ? Isn’t the blending supposed to write the correct alpha value in the rendertexture ? (if I use glOne * SrcAlpha for my blending equation)
This is what it does when I use sf::BlendNone.