1

When reading out rgba(1,1,1,0.1) with glReadPixels will result in rgba(0.1,0.1,0.1,???). The function is reading modified values from the framebuffer, I assume because of alpha blending.

The example I'm using has the following setup:

Fragment shader:

String fragmentShaderSource =
        "  #version 440\n" +
        "  out vec4 gl_FragColor;\n" +
        "  in vec4 gl_FragCoord;  \n" +
        "  varying vec2 v_texCoords;\n" +
        "\n" +
        "  uniform float chunkSize;\n" +
        "  layout(binding=1)uniform sampler2D inputs1;\n" +
        "  layout(binding=2)uniform sampler2D inputs2;\n" +
        "\n" +
        "  void main(void){\n" +
        "    gl_FragColor.r = 1;\n" +
        "    gl_FragColor.g = 1;\n" +
        "    gl_FragColor.b = 1;\n" +
        "    gl_FragColor.a = 0.1;\n" +
        "  }"
        ;

init:

fboHandle = Gdx.gl.glGenFramebuffer();
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fboHandle);

/* Create output texture */
outputTextureHandle = Gdx.gl.glGenTexture();
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
Gdx.gl.glBindTexture(GL20.GL_TEXTURE_2D, outputTextureHandle);
Gdx.gl.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
Gdx.gl.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
Gdx.gl.glTexImage2D(
    GL20.GL_TEXTURE_2D, 0, GL30.GL_RGBA32F,
    width, height, 0, GL20.GL_RGBA, GL20.GL_FLOAT, null
);

/* Configure Framebuffer */
/* Set "renderedTexture" as our colour attachement #0 */
Gdx.gl.glFramebufferTexture2D(
    GL20.GL_FRAMEBUFFER, GL20.GL_COLOR_ATTACHMENT0,
    GL20.GL_TEXTURE_2D, outputTextureHandle, 0
);

after rendering:

Gdx.gl30.glReadPixels(0,0,width, height, GL20.GL_RGBA, GL20.GL_FLOAT, resultBuf);
System.out.println("result r: " + resultBuf.get(0));
System.out.println("result g: " + resultBuf.get(1));
System.out.println("result b: " + resultBuf.get(2));
System.out.println("result a: " + resultBuf.get(3));

Output:

result r: 0.1
result g: 0.1
result b: 0.1
result a: 0.90999997

I can't understand why the alpha values are like this. According to this answer, while rendering to a framebuffer, the alpha channel is lost, and used to modify the pixel values.

My questions:

  • what happens with the alpha channels when the "combination" happens with the rgb values?
  • I understand what happens with the pixel values other, than the alpha, but why is this?
  • Can this behavior be disabled, so the alpha values along with the original pixel values are preserved with glReadPixels ?

Addition: The same behavior is observed when Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO); is called, or blending is disabled with Gdx.gl.glDisable(GL20.GL_BLEND); .

Using renderbuffer instead of a texture color attachement has the same effect.

Dávid Tóth
  • 2,788
  • 1
  • 21
  • 46
  • Do you happen to call `glReadBuffer` to point `glReadPixels` towards your framebuffer object? I think that by default, pixels will read from the backbuffer; to read the values in your FBO, you'd need to call `glReadBuffer(GL_COLOR_ATTACHMENT0);` before reading the pixels. In your example, you correctly request a rendering surface that has alpha value storage, but depending on how you configure your application's default framebuffer (i.e., the one associated with the window by EGL, GLX, ...), it may not include any bits to store alpha values. – radical7 Aug 17 '21 at 07:19
  • I didn't explictly call it, but now I called it and it still produces the same results. Thank you for the suggestion! – Dávid Tóth Aug 17 '21 at 08:13

1 Answers1

0

glReadPixels is not modifying any of the values.

I think your framebuffer's pixels are starting out as rgba(0,0,0,1), then you're rendering with rgba(1,1,1,0.1) with alpha blend enabled .

So you're seeing:

src * srcalpha + dest * (1.0 - srcalpha)

(1,1,1,0.1)*0.1 + (0,0,0,1)*0.9 = (0.1,0.1,0.1,0.901)

You need to disable alpha blending to see the result that you're expecting (I'm assuming you're expecting rgba(1,1,1,0.1)).

It's glDisable(GL_BLEND) or presumably Gdx.gl.glDisable(GL20.GL_BLEND) for your libgdx.

Columbo
  • 6,648
  • 4
  • 19
  • 30
  • I disabled Blending but nothing changed. I never said the function was modifying the pixel values, rather, the function can only read back modified pixel values. I'll clarify that in the question. – Dávid Tóth Aug 14 '21 at 05:17
  • for some reason I thought setting `Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO);` would work, but it still doesn't – Dávid Tóth Aug 14 '21 at 05:31
  • Can I check you're using `Gdx.gl.glDisable(GL20.GL_BLEND)` or `Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO);` prior to the `Gdx.gl.glDraw*` call you're using? – Columbo Aug 15 '21 at 15:45
  • With any combination, the end result is the same. – Dávid Tóth Aug 15 '21 at 17:34