¿Hay alguna forma de representar el contenido de un UIView como una textura con OpenGL en iOS? ¿O los contenidos de un CGLayer?Renderiza el contenido de UIView como una textura OpenGL
Respuesta
Puede usar la propiedad de capa de la vista para obtener el CALayer y usar renderInContext: para dibujar en un contexto CoreGraphics. Puede configurar un contexto CoreGraphics con la memoria que se asigna para recibir un búfer de píxeles. A continuación, puede cargarlo en OpenGL por el método normal.
Así que: hay un medio para obtener el contenido de píxeles de un UIView y OpenGL aceptará los búferes de píxeles. No hay un vínculo específico entre los dos.
Codificación de manera extemporánea, el proceso sería algo así como:
UIView *view = ... something ...;
// make space for an RGBA image of the view
GLubyte *pixelBuffer = (GLubyte *)malloc(
4 *
view.bounds.size.width *
view.bounds.size.height);
// create a suitable CoreGraphics context
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context =
CGBitmapContextCreate(pixelBuffer,
view.bounds.size.width, view.bounds.size.height,
8, 4*view.bounds.size.width,
colourSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colourSpace);
// draw the view to the buffer
[view.layer renderInContext:context];
// upload to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0,
GL_RGBA,
view.bounds.size.width, view.bounds.size.height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixelBuffer);
// clean up
CGContextRelease(context);
free(pixelBuffer);
Eso no se ocupa de cuestiones relacionadas con la no-poder-de-dos vistas de tamaño en hardware sin el no-poder-de-dos textura extensión y supone que ya se ha generado y enlazado un nombre de textura GL adecuado. Compruébalo tú mismo, pero creo que el hardware SGX no es compatible con el poder-de-dos (es decir, iPhone 3GS en adelante, el iPad y todos excepto el iPod Touch de tercera generación de 8g en adelante) pero no en MBX.
La forma más fácil de tratar las texturas que no son de potencia de dos aquí es probablemente crear una potencia lo suficientemente grande de dos texturas y usar glTexSubImage2D para cargar solo la parte de su UIView de origen.
Aquí hay otro método de agarrar una Capa OpenGL, que es usar glReadPixels. Esto agarrará las capas visibles DETRÁS de su capa openGL, también (básicamente, su pantalla visible). Mira esta pregunta: How do I grab an image form my EAGLLayer ?
Una vez que tengas tu imagen, se debe cambiar el tamaño a la potencia de dos. Puede intentar estirar la imagen, pero eso causará problemas de calidad cuando la reduzca nuevamente, o si lo hace una y otra vez. La mejor manera es dibujar el tamaño normal de su imagen en una textura de base 2 con píxeles adicionales para formar un buffer. Aquí está el código (he modificado esto desde código de otra persona, pero no puedo encontrar el código original, por lo que si alguien ve el código original, por favor hágamelo saber de dónde vino para dar crédito):
-(UIImage*)base2Image:(UIImage *) srcImg {
int frame2Base = 512;
CGSize srcSize = [srcImg size];
CGRect rec = CGRectMake(0, 0, frame2Base, frame2Base);
[srcImg drawInRect:rec blendMode:kCGBlendModeNormal alpha:1.0];
//create a context to do our clipping in
UIGraphicsBeginImageContext(CGSizeMake(frame2Base, frame2Base));
CGContextRef currentContext = UIGraphicsGetCurrentContext();
//create a rect with the size we want to crop the image to
CGRect clippedRect = CGRectMake(0, 0, frame2Base, frame2Base);
CGContextClipToRect(currentContext, clippedRect);
//create a rect equivalent to the full size of the image
CGRect drawRect = CGRectMake(0, 0, srcSize.width, srcSize.height);
//draw the image to our clipped context using our offset rect
CGContextDrawImage(currentContext, drawRect, srcImg.CGImage);
UIImage *dstImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return dstImg;
}
Ahora, una vez hecho esto, usa una matriz de coordenadas de textura para SOLAMENTE extraer la sección de tamaño correcto de su imagen. Tal como este:
GLfloat texCoords[] = {
0.0, (float)frameHeight/2BaseHeight,
0.0, 0.0,
(float)frameWidth/2BaseWidth, (float)frameHeight/2BaseHeight,
(float)frameWidth/2BaseWidth, 0.0
};
Y ya lo tienes. Una captura de pantalla de su pantalla visible que ahora es una textura.
¡Esta es una gran técnica! De hecho, necesito obtener el contenido de una parte de la jerarquía de mi vista, pero aun así, +1. –
- 1. Proyectar una textura en OpenGL
- 2. OpenGL - Interpretación en una textura
- 3. Textura translúcida OpenGL sobre otra textura
- 4. Android opengl textura corrupción
- 5. Voltear la textura OpenGL
- 6. OpenGL y textura monocromática
- 7. Textura OpenGL Cargando
- 8. OpenGL textura invertida
- 9. iOS4: ¿cómo uso el archivo de video como una textura OpenGL?
- 10. Android OpenGL - ES Textura sangrando
- 11. Mostrar un texto como textura con OpenGL ES 2.0
- 12. opengl - mezcla con contenido anterior de framebuffer
- 13. OpenGL: Cargar una textura cambia el color actual
- 14. textura de JuicyPixels cargando en Haskell OpenGL?
- 15. Coordenadas de textura OpenGL en Pixel Space
- 16. Uso de una imagen creada con CGBitmapContextCreate como una textura opengl
- 17. Actualización de una textura en OpenGL con glTexImage2D
- 18. Textura de pantalla completa iPhone OpenGL ES
- 19. Asignación de textura de hemisferio OpenGL
- 20. ¿Cuál es el rango de ID de textura OpenGL?
- 21. Representación de OpenGL ES 2.0 con una textura
- 22. ¿Es 0 una ID de textura OpenGL válida?
- 23. OpenGL textura aleatoriamente no se muestra
- 24. ¿El mapa de textura OpenGL simple no funciona?
- 25. Textura transparente en OpenGL ES para Android
- 26. La textura OpenGL no sigue la geometría
- 27. Android: ¿Por cuánto tiempo OpenGL almacena una textura?
- 28. Convertir la textura OpenGL a OpenCV Mat
- 29. Cargando textura para OpenGL con OpenCV
- 30. Textura negra OpenGL ES en Nexus S
Usando CVOpenGLESTextureCacheCreateTextureForImage debería ser más eficiente que usar glTexImage2D directamente. El buffer de píxeles debe tener definidas las claves 'IOSurfaceProperties' y' OpenGLESCompatibility'. – OrangeDog