2015-06-16 155 views
12

我试图在我的应用程序中绘制透明纹理(文本)。奇怪的是,它适用于最新的Nexus 7和我的第二代Moto X,但在原始的Nexus 7上,纹理只是黑色。我已启用混合,并且纹理为512x512,因此它不是二次幂的问题。我也只是使用GL10应该支持的一切,对吧?任何原因纹理不适用于这个设备?Android OpenGL透明纹理绘制黑色

gl.glEnable(GL10.GL_BLEND); 
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); 
gl.glEnable(GL10.GL_TEXTURE_2D); 
// text drawn here 
gl.glDisable(GL10.GL_TEXTURE_2D); 
gl.glDisable(GL10.GL_BLEND); 

而这里的质地初始化,我加载纹理图集:

public void loadGlyphs(GL10 gl, Context context) { 
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.text_bitmap); 
    gl.glGenTextures(1, textures, 0); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 

    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 

    bitmap.recycle(); 
} 

顶部显示了旧的Nexus发生了什么7.底部的图片是一个摩托X.

Bad

Good

编辑:这是一个完整的例子。没有透明度,不会在旧Nexus 7上绘制任何东西。如果我摆脱纹理,它会像使用白色一样绘制白色方块。

MainActivity.java

import android.app.Activity; 
import android.opengl.GLSurfaceView; 
import android.os.Bundle; 


public class MainActivity extends Activity { 

    private GLSurfaceView glView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     glView = new TestView(this); 
     setContentView(glView); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     glView.onPause(); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     glView.onResume(); 
    } 
} 

TestView.java

import android.content.Context; 
import android.opengl.GLSurfaceView; 

public class TestView extends GLSurfaceView { 
    private TestRenderer renderer; 

    public TestView(Context context) { 
     super(context); 

     renderer = new TestRenderer(context); 
     setRenderer(renderer); 
    } 
} 

TestRenderer.java

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.opengl.GLSurfaceView; 
import android.opengl.GLU; 
import android.opengl.GLUtils; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

public class TestRenderer implements GLSurfaceView.Renderer { 

    private FloatBuffer floatBuffer; 
    private FloatBuffer textureBuffer; 
    private Context context; 
    private int[] textures; 

    public TestRenderer(Context context) { 
     this.context = context; 
     textures = new int[1]; 
    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     floatBuffer = ByteBuffer.allocateDirect(4 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.rewind(); 

     textureBuffer = ByteBuffer.allocateDirect(4*2*4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     textureBuffer.put(0); 
     textureBuffer.put(1); 
     textureBuffer.put(0); 
     textureBuffer.put(0); 
     textureBuffer.put(1); 
     textureBuffer.put(1); 
     textureBuffer.put(1); 
     textureBuffer.put(0); 
     textureBuffer.rewind(); 

     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.test); 
     gl.glGenTextures(1, textures, 0); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 
     bitmap.recycle(); 
    } 

    public void onSurfaceChanged(GL10 gl, int w, int h) { 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 
     GLU.gluPerspective(gl, 45.0f, (float) w/(float) h, 0.1f, 100.0f); 
     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 
    } 

    public void onDrawFrame(GL10 gl) { 
     gl.glLoadIdentity(); 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 
     gl.glTranslatef(0.0f, 0.0f, -5.0f); 

     gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 

     gl.glEnable(GL10.GL_TEXTURE_2D); 
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
     gl.glFrontFace(GL10.GL_CW); 
     gl.glVertexPointer(2, GL10.GL_FLOAT, 0, floatBuffer); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
     gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); 
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glDisable(GL10.GL_TEXTURE_2D); 
    } 
} 

编辑:这是我在网上找到一个例子。如果我禁用GL_TEXTURE_2D,我会得到一个白色方块。如果我启用了GL_TEXTURE_2D,我什么也得不到。

MainActivity 公共类MainActivity扩展活动{

private GLSurfaceView glSurfaceView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
       WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     glSurfaceView = new GLSurfaceView(this); 

     glSurfaceView.setRenderer(new GlRenderer(this)); 
     setContentView(glSurfaceView); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     glSurfaceView.onResume(); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     glSurfaceView.onPause(); 
    } 

} 

GlRenderer

public class GlRenderer implements Renderer { 

    private Square square; 
    private Context context; 

    public GlRenderer(Context context) { 
     this.context = context; 
     this.square = new Square(); 
    } 

    @Override 
    public void onDrawFrame(GL10 gl) { 
     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
     gl.glLoadIdentity(); 
     gl.glTranslatef(0.0f, 0.0f, -5.0f); 
     square.draw(gl); 
    } 

    @Override 
    public void onSurfaceChanged(GL10 gl, int width, int height) { 
     if(height == 0) { 
      height = 1; 
     } 
     gl.glViewport(0, 0, width, height); 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 

     GLU.gluPerspective(gl, 45.0f, (float)width/(float)height, 0.1f, 100.0f); 

     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 
    } 

    @Override 
    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     square.loadGLTexture(gl, this.context); 

     gl.glEnable(GL10.GL_TEXTURE_2D); 
     gl.glShadeModel(GL10.GL_SMOOTH); 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 
     gl.glClearDepthf(1.0f); 
     gl.glEnable(GL10.GL_DEPTH_TEST); 
     gl.glDepthFunc(GL10.GL_LEQUAL); 
     gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
    } 
} 

广场

public class Square { 

    private FloatBuffer vertexBuffer; 
    private float vertices[] = { 
      -1.0f, -1.0f, 0.0f, 
      -1.0f, 1.0f, 0.0f, 
      1.0f, -1.0f, 0.0f, 
      1.0f, 1.0f, 0.0f 
    }; 

    private FloatBuffer textureBuffer; 
    private float texture[] = { 
      0.0f, 1.0f, 
      0.0f, 0.0f, 
      1.0f, 1.0f, 
      1.0f, 0.0f 
    }; 

    private int[] textures = new int[1]; 

    public Square() { 
     ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 
     vertexBuffer = byteBuffer.asFloatBuffer(); 
     vertexBuffer.put(vertices); 
     vertexBuffer.position(0); 
     byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 
     textureBuffer = byteBuffer.asFloatBuffer(); 
     textureBuffer.put(texture); 
     textureBuffer.position(0); 
    } 

    public void loadGLTexture(GL10 gl, Context context) { 
     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), 
       R.drawable.test); 

     gl.glGenTextures(1, textures, 0); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 

     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 

     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 

     bitmap.recycle(); 
    } 

    public void draw(GL10 gl) { 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
     gl.glFrontFace(GL10.GL_CW); 
     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
     gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3); 
     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    } 
} 
+0

也许这是您使用的纹理类型。显示你的纹理创建/初始化代码。 – MuertoExcobito

+0

@MuertoExcobito添加了代码 –

+0

我一直在找出你正在使用的纹理格式,但GLUtils.texImage2d在内部完成,所以它不是那么有用。但是,也许你的绘图代码取决于它在一个特定的渠道(例如。alpha),它将它置于红色呢?在切换到3.2内核时,这是OpenGL的一个问题,因为不推荐使用“GL_ALPHA”。 – MuertoExcobito

回答

1

很多故障排除之后,我能够通过添加纹理包裹以使得对解决这两个设备(大概所有设备)上的问题:

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); 
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); 

虽然我不确定为什么这对于两个设备是必要的,但是不是另外两个。

2

什么颜色格式是你的纹理使用?它与您着色器期望的颜色格式相匹配吗?

如果你的颜色格式是RGBA8888,着色器需要RGB256,你可以得到像这样的问题。 (它会寻找Alpha通道信息在错误的地方)

+0

我刚刚登录'GLUtils.getInternalFormat(位图)'和回来6408,这相当于GL_RGBA –

+0

嗯,你可以尝试在GIMP打开你的纹理例如和导出在RGB模式下?然后尝试导出灰度并查看差异?我会尝试其他一些事情:尝试将着色器的精度更改为HIGHP浮点数。尝试将alpha通道从第一个位平面切换到最后一个位平面(反之亦然)。你在使用纹理压缩吗?某些压缩算法不支持Alpha通道... – DKIT

+0

RGB和灰度之间的切换完全没有影响它。我将GIMP中的png压缩级别从9更改为0,没有任何区别。我还增加了另一个例子。有趣的是,该示例中没有透明度,图像仍然不显示。难道它不像GLUtils生成它?纹理在其他应用程序中工作,所以我真的不知道这笔交易是什么 –