2010-11-07 34 views

Trả lời

19

Bạn có thể sử dụng thuộc tính lớp của chế độ xem để có được CALayer và sử dụng renderInContext: trên đó để vẽ vào ngữ cảnh CoreGraphics. Bạn có thể thiết lập một bối cảnh CoreGraphics với bộ nhớ bạn phân bổ chính mình để nhận được một bộ đệm pixel. Sau đó, bạn có thể tải nó lên OpenGL bằng phương pháp thông thường.

Vì vậy: có phương tiện để lấy nội dung pixel của UIView và OpenGL sẽ chấp nhận bộ đệm pixel. Không có liên kết cụ thể giữa hai người.

Mã hóa extemporaneously, quá trình này sẽ là một cái gì đó như:

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); 

Điều đó không đối phó với các vấn đề xung quanh không quyền lực-of-hai quan điểm có kích thước trên phần cứng mà không có sự không quyền lực-of-hai kết cấu mở rộng và giả sử một tên kết cấu GL phù hợp đã được tạo và ràng buộc. Kiểm tra cho chính mình, nhưng tôi nghĩ rằng không phải điện-of-hai được hỗ trợ trên phần cứng SGX (ví dụ, iPhone 3GS trở đi, iPad và tất cả, nhưng iPod Touch thế hệ thứ ba 8gb trở đi) nhưng không phải trên MBX. Cách đơn giản nhất để xử lý các kết cấu không có điện hai chiều ở đây có lẽ là tạo ra sức mạnh đủ lớn của hai kết cấu và sử dụng glTexSubImage2D để tải lên chỉ phần từ nguồn UIView của bạn.

+0

Sử dụng CVOpenGLESTextureCacheCreateTextureForImage phải hiệu quả hơn việc sử dụng trực tiếp glTexImage2D. Bộ đệm pixel phải có các khóa 'IOSurfaceProperties' và' OpenGLESCompatibility' được định nghĩa. – OrangeDog

5

Đây là một phương pháp khác để lấy một lớp OpenGL, sử dụng glReadPixels. Điều này sẽ lấy các lớp có thể nhìn thấy BEHIND lớp OpenGL của bạn, cũng như (về cơ bản, màn hình hiển thị của bạn). Xem câu hỏi này: How do I grab an image form my EAGLLayer ?

Khi bạn đã có hình ảnh của mình, nó phải được thay đổi kích thước thành hai. Bạn có thể thử và kéo giãn hình ảnh, nhưng điều đó sẽ gây ra các vấn đề về chất lượng khi bạn thu nhỏ lại hoặc nếu bạn lặp lại nhiều lần. Cách tốt nhất là vẽ kích thước hình ảnh bình thường của bạn thành một kết cấu cơ sở-2 với các pixel bổ sung để tạo bộ đệm. Đây là mã (tôi sửa đổi này từ mã của người khác, nhưng tôi không thể tìm thấy mã gốc, vì vậy nếu ai đó nhìn thấy mã gốc, xin vui lòng cho tôi biết nó đến từ đâu để cung cấp tín dụng):

-(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; 
} 

Bây giờ, một khi đã xong, bạn sử dụng một mảng tọa độ kết cấu để CHỈ kéo phần có kích thước chính xác ra khỏi hình ảnh của bạn. Chẳng hạn như:

GLfloat texCoords[] = { 
    0.0, (float)frameHeight/2BaseHeight, 
    0.0, 0.0, 
    (float)frameWidth/2BaseWidth, (float)frameHeight/2BaseHeight, 
    (float)frameWidth/2BaseWidth, 0.0 
}; 

Và ở đó bạn có nó. Ảnh chụp màn hình từ màn hình hiển thị của bạn hiện là kết cấu.

+0

Đây là một kỹ thuật tuyệt vời! Tôi thực sự chỉ cần lấy nội dung của một phần phân cấp chế độ xem của tôi, nhưng vẫn còn, +1. –

Các vấn đề liên quan