Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/208.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java OpenGL ES 2.0-在运行时创建位图,用作纹理-具有透明度_Java_Android_Bitmap_Opengl Es 2.0_Transparency - Fatal编程技术网

Java OpenGL ES 2.0-在运行时创建位图,用作纹理-具有透明度

Java OpenGL ES 2.0-在运行时创建位图,用作纹理-具有透明度,java,android,bitmap,opengl-es-2.0,transparency,Java,Android,Bitmap,Opengl Es 2.0,Transparency,目前,我正在研究具有透明度的动态纹理(即在运行时创建的纹理)。我当前创建的位图如下所示: b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Canvas c = new Canvas(b); c.drawColor(0, PorterDuff.Mode.CLEAR); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

目前,我正在研究具有透明度的动态纹理(即在运行时创建的纹理)。我当前创建的位图如下所示:

b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
c.drawColor(0, PorterDuff.Mode.CLEAR);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
c.save();
c.translate(paddingLeft, paddingTop);
view.draw(c);
c.restore();
GLES20.glClearColor(0, 0, 0, 0);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
因为我正在创建一个视图,我需要它作为位图,然后将它用作平面的纹理。这工作很好,我收到一个位图。如果我将它添加到ImageView中并将其放在布局的顶部,就我所见,它也是透明的

我使用的是
getHolder().setFormat(PixelFormat.半透明)GLSurfaceView
中的code>,以及
setEGLConfigChooser(8,8,8,16,0)

纹理的生成如下所示:

GLES20.glGenTextures(1, textureHandle, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// GLES20 tex parameters here as well... (min/mag filter)
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bmp, 0);
在片段着色器中,出于测试目的,我只是简单地应用

gl_FragColor = texture2D(u_Texture, v_TexCoordinate);
所以没有灯光,只需要纹理的颜色

但是它不是透明的,它有一个黑色的边框——因为我创建的位图是二的幂。这意味着,如果我的视图大小为300x300,纹理将为512x512,带有透明边框,在OpenGL ES 2.0中绘制为黑色

在我的渲染器中,我按如下方式启用混合:

b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
c.drawColor(0, PorterDuff.Mode.CLEAR);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
c.save();
c.translate(paddingLeft, paddingTop);
view.draw(c);
c.restore();
GLES20.glClearColor(0, 0, 0, 0);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
但我不确定这是否是正确的搅拌机功能

因此,最终,透明度被忽略,显示为黑色


你知道我可能错过了什么/做错了什么吗?非常感谢。

如果我正确理解您的操作,那么问题似乎不是纹理问题。这是你添加的填充,将其四舍五入为二的幂,这是不透明的

我最初以为您没有清除整个位图,但是您的
c.DrawColor()
调用应该会解决这个问题。为确保安全,您可以在创建位图后立即尝试以下操作,看看是否会有所不同:

b.eraseColor(Color.TRANSPARENT);
我能想到的另一种方法更干净、更好:在渲染过程中,不要使用添加的纹理部分填充大小。通过调整纹理坐标,仅对包含视图的纹理部分进行采样,可以做到这一点。使用示例中的尺寸(绘制到512x512纹理中的300x300视图),用于渲染的纹理坐标范围应为每个方向上的
0.0f
300.0f/512.0f
,而不是通常的
0.0f
1.0f


您使用的混合函数看起来不错。

将alpha纹理从Android位图类加载到OpenGL ES并不能真正正常工作,因为位图预乘alpha,而OpenGL ES采用非预乘格式。当你做更多的混合时,你会看到这个问题。加载OpenGL ES的纹理时,可以在着色器代码中反转预乘或避免使用位图类。这方面还有更多的内容。

没错,从OpenGL中看,填充显然是不透明的。我已经尝试了几种使位图透明的方法,但没有一种有效,所以我将尝试更改纹理坐标!谢谢你的提示,很有效!只需计算百分比偏移(0..1),更新纹理缓冲区,添加适当的缩放,不再需要透明度。