Есть ли способ визуализировать содержимое UIView как текстуры с OpenGL в iOS? Или содержимое CGLayer?
Отображать содержимое UIView как текстуры OpenGL
Ответ 1
Вы можете использовать свойство слоя представления, чтобы получить CALayer и использовать renderInContext: для этого врисовать в контексте CoreGraphics. Вы можете настроить контекст CoreGraphics с выделенной вами памятью, чтобы получить буфер пикселей. Затем вы можете загрузить его в OpenGL обычным способом.
Итак: есть средства для получения содержимого пикселов UIView и OpenGL, которые будут принимать пиксельные буферы. Нет никакой конкретной связи между ними.
Некорректное кодирование, процесс будет примерно таким:
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);
Это не касается проблем, связанных с нестандартными представлениями на аппаратном уровне без расширения текстуры без использования двух сторон и предполагает, что подходящее имя текстуры GL уже создано и связано. Проверяйте сами, но я думаю, что не-power-of-two поддерживается на оборудовании SGX (т.е. IPhone 3GS, iPad и все, кроме 8Gb третьего поколения iPod Touch), но не на MBX.
Самый простой способ справиться с текстурами, отличными от двух тексту, - это, вероятно, создание достаточно большой мощности двух текстур и использование glTexSubImage2D для загрузки только части из вашего исходного UIView.
Ответ 2
Вот еще один способ захвата слоя OpenGL, который должен использовать glReadPixels. Это будет захватывать видимые слои за вашим слоем openGL, а также (в основном, ваш видимый экран). Проверьте этот вопрос: Как захватить изображение из моего EAGLLayer?
Как только у вас есть изображение, оно должно быть изменено до двух. Вы можете попробовать и растянуть изображение, но это вызовет проблемы с качеством, когда вы снова сжимаете его, или если вы делаете это снова и снова. Лучший способ - нарисовать нормальный размер вашего изображения в текстуре base-2 с дополнительными пикселями для создания буфера. Вот код (я изменил это с чужого кода, но я не могу найти исходный код, поэтому, если кто-то увидит исходный код, сообщите мне, откуда он пришел, чтобы дать кредит):
-(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;
}
Теперь, как только это будет сделано, вы будете использовать массив координат текстуры, чтобы ТОЛЬКО вытащить нужный размер из вашего изображения. Например:
GLfloat texCoords[] = {
0.0, (float)frameHeight/2BaseHeight,
0.0, 0.0,
(float)frameWidth/2BaseWidth, (float)frameHeight/2BaseHeight,
(float)frameWidth/2BaseWidth, 0.0
};
И у вас это есть. Снимок экрана с вашего видимого экрана, который теперь является текстурой.