Подтвердить что ты не робот

Отображать содержимое UIView как текстуры OpenGL

Есть ли способ визуализировать содержимое UIView как текстуры с OpenGL в iOS? Или содержимое CGLayer?

4b9b3361

Ответ 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
};

И у вас это есть. Снимок экрана с вашего видимого экрана, который теперь является текстурой.