OpenGL ES – glReadPixels

Estoy tomando una captura de pantalla con glReadPixels para realizar un efecto "cross-over" entre dos imágenes.

En el simulador SDK de Marmalade, la captura de pantalla se toma muy bien y el efecto "cross-over" funciona como un regalo: Introduzca aquí la descripción de la imagen

Sin embargo, esto es cómo se ve en iOS y dispositivos Android – corrompido: http://www.eikona.info/images/81269689420703803966.png

Siempre leo la pantalla como RGBA 1 byte / canal, como la documentación dice que siempre se acepta.

Aquí está el código usado para tomar la captura de pantalla:

uint8* Gfx::ScreenshotBuffer(int& deviceWidth, int& deviceHeight, int& dataLength) { /// width/height deviceWidth = IwGxGetDeviceWidth(); deviceHeight = IwGxGetDeviceHeight(); int rowLength = deviceWidth * 4; /// data always returned by GL as RGBA, 1 byte/each dataLength = rowLength * deviceHeight; // set the target framebuffer to read glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); uint8* buffer = new uint8[dataLength]; glReadPixels(0, 0, deviceWidth, deviceHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer); return buffer; } void Gfx::ScreenshotImage(CIwImage* img, uint8*& pbuffer) { int deviceWidth, deviceHeight, dataLength; pbuffer = ScreenshotBuffer(deviceWidth, deviceHeight, dataLength); img->SetFormat(CIwImage::ABGR_8888); img->SetWidth(deviceWidth); img->SetHeight(deviceHeight); img->SetBuffers(pbuffer, dataLength, 0, 0); } 

Eso es un error de controlador. Simple como eso.

El conductor consiguió el tono de la superficie en la memoria de vídeo mal. Usted puede ver claramente esto en las líneas superiores. También la basura que ves en la parte inferior de la imagen es la memoria donde el conductor piensa que la imagen se almacena, pero hay diferentes datos allí. Texturas / datos Vertex tal vez.

Y lo siento, no sé de ninguna manera de arreglar eso. Puede tener mejor suerte con un formato de superficie diferente o activando / desactivando el multisampling.

Al final, fue la falta de memoria. El "nuevo uint8 [dataLength];" Nunca devolvió un puntero existente, así todo el proceso se corrompió.

TomA, tu idea de limpiar el buffer realmente me ayudó a resolver el problema. Gracias.

No sé sobre androide o el SDK que usted está utilizando, pero en IOS cuando tomo una captura de pantalla tengo que hacer el almacenador intermediario el tamaño de la textura siguiente del POT, algo como esto:

 int x = NextPot((int)screenSize.x*retina); int y = NextPot((int)screenSize.y*retina); void *buffer = malloc( x * y * 4 ); glReadPixels(0,0,x,y,GL_RGBA,GL_UNSIGNED_BYTE,buffer); 

La función NextPot sólo me da el siguiente tamaño POT, así que si el tamaño de la pantalla era 320×480, el x, y sería 512×512.

Tal vez lo que su ver es la envoltura de la memoria intermedia, ya que espera un tamaño de búfer más grande?

También esto podría ser una razón para que funcione en el simulador y no en el dispositivo, mi tarjeta gráfica no tiene la limitación de tamaño POT y me sale similar (aspecto extraño) resultado.

Lo que supongo que está sucediendo es que está intentando usar glReadPixels en la ventana que está cubierta. Si el área de vista está cubierta, entonces el resultado de glReadPixels es indefinido.

Consulte ¿Cómo se utilizan glDrawPixels () y glReadPixels ()? Y el problema de la propiedad del pixel .

Como se ha dicho aquí :

La solución es hacer un búfer fuera de pantalla (FBO) y renderizar a la FBO.

Otra opción es asegurarse de que la ventana no esté cubierta cuando utilice glReadPixels .

Estoy consiguiendo el screenshoot de mi juego del androide sin ningunos problemas en el dispositivo android usando glReadPixels.

Todavía no estoy seguro de cuál es el problema en su caso, necesito más información. Así que vamos a empezar:

  1. Te recomiendo que no especifiques el formato de PixelStore. Estoy preocupado por su alineación en 1 byte, ¿realmente lo "usa" / "sabe lo que hace"? Parece que obtiene exactamente lo que usted especifica – un byte extra (mirar su imagen, hay un píxel extra todo el tiempo!) En lugar de la imagen totalmente lleno. Por lo tanto, intente eliminar esto:

    GlPixelStorei (GL_UNPACK_ALIGNMENT, 1); GlPixelStorei (GL_PACK_ALIGNMENT, 1);

  2. No estoy seguro en código C, ya que estaba trabajando sólo en java, pero esto parece posible:

    // width / height deviceWidth = IwGxGetDeviceWidth (); DeviceHeight = IwGxGetDeviceHeight ();

¿Está consiguiendo el tamaño del dispositivo? Debe utilizar su tamaño de superficie OpenGL, como esto:

 public void onSurfaceChanged(GL10 gl, int width, int height) { int surfaceWidth = width; int surfaceHeight = height; } 
  1. ¿Qué haces ahora con la imagen capturada? ¿Sabe que el bloque de memoria que obtuvo de opengl es RGBA, pero todas las operaciones de imagen no-opengl esperan ARGB? Por ejemplo aquí en tu código esperas que alfa sea el primer bit, no el último:

    Img-> SetFormat (CIwImage :: ABGR_8888);

  2. En caso de que si 1, 2 y 3 no le ayudan, puede que desee guardar la pantalla capturada en el teléfono sdcard para examinarla más tarde. Tengo un programa que convierte el bloque de RGBGL del opengl al mapa de bits normal para examinar en la PC. Puedo compartirlo con usted.

No tengo una solución para arreglar glReadPixels. Mi sugerencia es que cambie su algoritmo para evitar la necesidad de leer los datos de la pantalla.

Echa un vistazo a esta página . Estos chicos han hecho un efecto de tapa de página todo en Flash. Está todo en 2D, la ilusión se logra sólo con gradientes de sombra.

Creo que se puede utilizar un enfoque similar, pero un poco mejor en 3D. Básicamente, usted tiene que dividir el efecto en tres partes: el frente frente a la página superior (nubes), la página inferior (la niña) y la parte posterior de la portada. Tienes que dibujar cada parte por separado. Puede dibujar con facilidad la página superior y la página inferior juntos en la misma pantalla, sólo tiene que invocar el código de dibujo para cada uno con una región de recorte preajustada que esté alineada con la línea de división donde se dobla la página superior. Después de que usted tiene que las secciones de la tapa y de la página trasera dibujadas, usted puede dibujar la parte posterior que mira hacia atrás gris, también alineada a la línea de la fractura.

Con este enfoque, lo único que pierdes es un poco de deformación donde la imagen de las nubes comienza a doblarse, por supuesto, ninguna deformación ocurrirá con mi método. Esperemos que eso no disminuya el efecto, creo que las sombras son mucho más importantes para dar el efecto de profundidad y ocultar esta incoherencia menor.

  • La GPU del emulador no funciona
  • ¿Por qué está bloqueando glClear en OpenGLES?
  • ¿Los OpenGL Point Sprites funcionan en Android?
  • ¿Puedo hacer una aplicación C ++ bastante nativa con Android?
  • Texturas OpenGL de Android: crearlas y borrarlas al vuelo
  • Instalar OpenGL ES y código de compilación para android
  • ¿Qué es JNI Graphics o cómo usarlo?
  • ¿Por qué los colores de los píxeles no son correctos en OpenGL ES 2.0 en Android?
  • Android OpenGL textura de origen no local utilizando Rajawali3D?
  • Alternativa para glBlitFrameBuffer () en OpenGL ES 2.0
  • Screen Recorder Plugin para Android en Unity
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.