使用 glReadPixels 读取 rgb 值时,OpenGLES Alpha 值会修改它们
Posted
技术标签:
【中文标题】使用 glReadPixels 读取 rgb 值时,OpenGLES Alpha 值会修改它们【英文标题】:OpenGLES Alpha value modifies rgb values when reading them out with glReadPixels 【发布时间】:2021-08-13 19:02:16 【问题描述】:当使用glReadPixels
读取 rgba(1,1,1,0.1) 时,将导致 rgba(0.1,0.1,0.1,???)。该函数正在从帧缓冲区读取修改后的值,我假设是因为 alpha 混合。
我使用的示例具有以下设置:
片段着色器:
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" +
" "
;
初始化:
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
);
渲染后:
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));
输出:
result r: 0.1
result g: 0.1
result b: 0.1
result a: 0.90999997
我不明白为什么 alpha 值是这样的。根据this answer 的说法,在渲染到帧缓冲区时,alpha 通道会丢失,并用于修改像素值。
我的问题:
当 rgb 值发生“组合”时,Alpha 通道会发生什么情况? 我了解除了 alpha 以外的像素值会发生什么情况,但这是为什么呢? 是否可以禁用此行为,以便使用glReadPixels
保留 alpha 值和原始像素值?
补充:当Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO);
被调用,或使用Gdx.gl.glDisable(GL20.GL_BLEND);
禁用混合时,观察到相同的行为。
使用渲染缓冲区代替纹理颜色附件具有相同的效果。
【问题讨论】:
您是否碰巧调用glReadBuffer
将glReadPixels
指向您的帧缓冲区对象?我认为默认情况下,像素将从后台缓冲区中读取;要读取 FBO 中的值,您需要在读取像素之前调用 glReadBuffer(GL_COLOR_ATTACHMENT0);
。在您的示例中,您正确请求了一个具有 alpha 值存储的渲染表面,但取决于您如何配置应用程序的默认帧缓冲区(即,通过 EGL、GLX 等与窗口关联的帧缓冲区),它可能不包括任何用于存储 alpha 值的位。
我没有明确地调用它,但现在我调用了它,它仍然产生相同的结果。谢谢你的建议!
【参考方案1】:
glReadPixels
没有修改任何值。
我认为您的帧缓冲区的像素一开始是 rgba(0,0,0,1),然后您使用启用了 alpha 混合的 rgba(1,1,1,0.1) 进行渲染。
所以你看到了:
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)
您需要禁用 alpha 混合才能看到您期望的结果(我假设您期望 rgba(1,1,1,0.1)
)。
你的 libgdx 是 glDisable(GL_BLEND)
或大概是 Gdx.gl.glDisable(GL20.GL_BLEND)
。
【讨论】:
我禁用了混合,但没有任何改变。我从未说过该函数正在修改像素值,而是该函数只能读回修改后的像素值。我会在问题中澄清这一点。 出于某种原因,我认为设置Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO);
会起作用,但它仍然不起作用
我可以在您正在使用的Gdx.gl.glDraw*
呼叫之前检查您正在使用Gdx.gl.glDisable(GL20.GL_BLEND)
或Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ZERO);
吗?
任意组合,最终结果都是一样的。以上是关于使用 glReadPixels 读取 rgb 值时,OpenGLES Alpha 值会修改它们的主要内容,如果未能解决你的问题,请参考以下文章