La textura transparente de Android OpenGL dibuja negro
Estoy tratando de dibujar texturas transparentes (texto) en mi aplicación. Curiosamente, funciona en el nuevo Nexus 7 y en mi segunda generación de Moto X, pero en el Nexus 7 original las texturas son sólo negras. Tengo la mezcla habilitada y la textura es 512×512 por lo que no es un problema de poder-de-dos. También estoy usando GL10 que debe ser apoyado en todo, ¿verdad? Cualquier razón las texturas no funcionaría en sólo este dispositivo?
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);
Y aquí está la inicialización de la textura, donde carga el atlas de texturas:
- Error: Theme.Translucent & FLAG_ACTIVITY_REORDER_TO_FRONT
- Barra de navegación translúcida Lollipop (fitsSystemWindows = "true")
- Android: Hacer el botón holo predeterminado opaco
- Hacer un botón semitransparente tal que el color del botón debe ser visible y el fondo debe ser visible
- ¿Cómo puedo configurar el valor alfa de una vista completa en el nivel 7 de api (Android 2.1)
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(); }
Top muestra lo que sucede en el viejo Nexus 7. La imagen de abajo es un Moto X.
Edit: He aquí un ejemplo completo. No hay transparencia, no dibuja nada en el viejo Nexus 7. Si me deshago de la materia de textura que dibuja el cuadrado en blanco como debería.
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); } }
Edit: He aquí un ejemplo que encontré en línea. Si desactivo GL_TEXTURE_2D obtengo un cuadrado blanco. Si habilito GL_TEXTURE_2D no obtengo nada.
MainActivity clase pública MainActivity extends Actividad {
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(); } }
Glander
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); } }
Cuadrado
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); } }
- Android-transparent RelativeLayout
- OpenGL ES 2.0 PNG canal alfa
- Frontera blanca junto con la transparencia en "LinearLayout"
- Android Image transparency - alternativa para setAlpha obsoleto para API <11
- Cómo obtener una imagen semi transparente en la parte superior de otra imagen para mantener el texto en android (captura de pantalla proporcionada)
- Transparente widget de fondo?
- Cómo hacer que el botón transparente en mi aplicación sea visible
- Android - Ocultar vistas
¿Qué formato de color es su textura está usando? ¿Concuerda con el formato de color que espera su shader?
Si su formato de color es RGBA8888 y el shader espera RGB256 puede obtener problemas como este. (Se buscará la información del canal alfa en el lugar equivocado)
Después de mucha solución de problemas, pude resolver el problema en ambos dispositivos (y presumiblemente todos los dispositivos) agregando la textura que envuelve como si:
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);
No estoy seguro de por qué esto era necesario para dos dispositivos, pero no los otros dos, sin embargo.
- Cómo terminar la actividad destruida
- ¿Cómo utilizar a los trabajadores de servicio en la aplicación Android de Cordova?