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:
- El método onFrameAvailable () de SurfaceTexture siempre se llama demasiado tarde
- Desarrollo de juegos Android 2D sin motor
- Trazado gráfico dinámico con openGL en Android
- OBJ vs 3DS - ¿Cuál es el mejor formato para Android 3D de Desarrollo
- ¿Puedo usar gloss en Android?
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); }
- Creación de una pantalla apropiada de Splash / Loading de Android
- NDK OpenGL indefinido referencia a glVertexPointer
- ¿Es posible realizar llamadas de OpenGL ES desde su código C ++ y Java?
- ¿Qué versiones de GLSL puedo usar en OpenGL ES 2.0?
- ¿Soporta el emulador de Android OpenGL ES 2.0?
- Cómo lograr mancha como efecto de imagen en Android
- OnSurfaceCreated () se llama cambios de orientación cada vez
- Androide. Cómo reproducir video en Surface (OpenGL)
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:
-
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);
-
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; }
-
¿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);
-
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.
- Android Studio muestra Errores (Traducción perdida) después de actualizar
- FragmentTransaction.remove no tiene efecto