这是我用于呈现视频的onDrawFrame()
的当前GLVideoRenderer
代码:
private void drawActual(boolean useFilter) {
Log.i("current_pos", currentFilterPosition+" "+Constant.ILLUSION);
/*
if(currentFilterPosition != Constant.ILLUSION) {
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
} else {
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
}
*/
if(currentFilterPosition != storedFilterPosition)
{
/*Changing fragment shader and resetting the uniform locations*/
storedFilterPosition = currentFilterPosition;
}
Log.e("use_filter", "true");
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
checkGlError("glBindTexture");
Log.i("current_float_timestamp", muTimestampFloatHandle+"");
onPreDrawFrame();
checkGlError("onPreDrawFrame");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
checkGlError("glmuMVPMatrixHandleSetting");
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
checkGlError("glmuSTMatrixHandleSetting");
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
//GLES20.glFinish();
}
这是我用来尝试半透明地渲染视频帧的片段着色器:
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES u_Texture;
varying highp vec2 v_TexCoordinate;
uniform float uParamValue1; //filter strength
void main()
{
vec4 texel = texture2D(u_Texture, v_TexCoordinate).rgba;
texel.a *= 0.2;
/*
if(texel.a > 0.5)
discard;
*/
gl_FragColor += texel;
}
我的问题是我的视频帧中的alpha值必须全部为255或1.0,因为在片段着色器中使用该注释掉的代码进行深度测试时,它或者全部存在,或者全部消失。更糟糕的是,当我使用这段代码时,alpha缩减没有效果 - 渲染器只渲染RGB组件。
我对片段着色器的期望实际上是应用了一点运动模糊效果,所以我希望着色器半透明地渲染视频帧,删除清除函数以防止渲染器在之前清除帧。 / p>
我该怎么做,我的代码丢失了什么?
答案 0 :(得分:0)
如果我正确理解你的目标,你就会缺少混合。查看glBlendFunc
或更有可能glBlendFuncSeparate
。另外,请不要忘记使用glEnable
启用混合。在您的情况下,您可能会发现使用glColorMask
掩盖alpha的有用。
因此,要查看通常的绘图管道,您将使用glClear
或已经绘制的某个场景开始使用背景颜色。现在你希望绘制一些有效混合它的对象。
混合时最常见的功能是使用glBlendFunc(src_alpha, one_minus_src_alpha)
。这意味着它将采用缓冲区中的任何内容,并仅使用即将到来的alpha将其与即将到来的颜色混合。因此,假设缓冲区已被清除为(0,0,0,0)
,并且您正在绘制(1.0, 1.0, 1.0, 0.5)
,这是一种半透明的白色。结果是:
(1.0, 1.0, 1.0, 0.5)*0.5 + (0,0,0,0)*(1.0-0.5) = (0.5, 0.5, 0.5, 0.25)
正如你所看到的那样,0.5
的颜色都很好但是alpha版本很棒0.25
这在导出到某些图片时会出现问题,但在查看时却不是问题在不透明的表面上(大多数情况下),因为在那里简单地忽略了alpha。
所以相比之下,如果我们清除不透明的黑色,我们得到
res = (1.0, 1.0, 1.0, 0.5)*0.5 + (0,0,0,1)*(1.0-0.5) = (0.5, 0.5, 0.5, 0.75)
这确实没有取得更好的结果。
一个解决方案显然是使用glBlendFuncSeparate
,它仅对alpha组件使用单独的参数,可以用作glBlendFuncSeparate(src_alpha, one_minus_src_alpha, gl_zero, gl_one)
。这将在颜色上完全相同,但alpha组件将保持不变,保持在它开始的任何位置。
但是,由于您不想在目标缓冲区上使用alpha,因此您可以使用glColorMask(true, true, true, false)
将其屏蔽掉并处理RGB组件。这不会在任何时候禁用alpha,它只会禁止写入。
所以假设这样的事情应该有效:
glClearColor(0,0,0,1); // Set clear color to opaque black
glClear(); // Clear the buffer
glDisable(blend); // Disable blending to draw background
glColorMask(true, true, true, false); // Disable writing to alpha component
glDraw(originalVideoFrame); // Draw the background
glEnable(blend); // Enable blending
glBlendFunc(src_alpha, one_minus_src_alpha); // Set standard blending function
glColorMask(true, true, true, false); // Redundant call, may be removed
glDraw(semitransparentFrame); // Draw semitransparent part
要使用单个像素进行检查,我们假设第一部分将绘制一个有点透明的红色(1, 0, 0, 0.75)
,然后与黄色半透明像素(1, 1, 0, 0.5)
混合,这将会发生:< / p>
(0.0, 0.0, 0.0, 1.0)
来自明确(1.0, 0.0, 0.0, 1.0)
画出红色。 alpha和混合都被禁用,因此只复制颜色而忽略其他所有内容(1.0, 0.5, 0.0, 1.0)
使用混合作为(1, 1, 0, 0.5)*0.5 + (1.0, 0.0, 0.0, 1.0)*(1.0-0,5) = (0.5, 0.5, 0.0, 0.25) + (0.5, 0.0, 0.0, 0.5) = (1.0, 0.5, 0.0, 0.75)
绘制黄色,再次忽略对alpha的更改。我希望这可以帮助您了解混合并解决您的问题。