2013-10-23 30 views
0

我使用GLKit,並在24幀我需要一個CGImageRef(沒有alpha層)和應用另一個CGImageRef(無alpha層)作爲它的掩碼(黑色和白色圖像)並將結果渲染爲GLKit紋理。GLKit遮罩或混合兩個紋理都來自jpegs沒有alphas

一開始我嘗試這個辦法:分配所產生的UIImage到一個UIImageView時

CGImageRef actualMask = CGImageMaskCreate(CGImageGetWidth(maskRef), 
              CGImageGetHeight(maskRef), 
              CGImageGetBitsPerComponent(maskRef), 
              CGImageGetBitsPerPixel(maskRef), 
              CGImageGetBytesPerRow(maskRef), 
              CGImageGetDataProvider(maskRef), NULL, false); 
CGImageRef masked = CGImageCreateWithMask(imgRef, actualMask); 

雖然會工作,這將不作爲GLKit質感工作(掩碼將不適用)。不過,如果我使用重繪圖像:

UIImage *maskedImg = [UIImage imageWithCGImage:masked]; 
UIGraphicsBeginImageContext(maskedImg.size); 
[maskedImg drawInRect:CGRectMake(0, 0, maskedImg.size.width, maskedImg.size.height)]; 
UIImage* resultImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

由此產生的圖像將被屏蔽,並在GLKit質地正確呈現。但是,這會將iPhone 4S的性能降低至6 fps左右。

我試過this masking approach沒有成功。

我已經嘗試過沒有Core Graphics並且使用GLKit混合,如this example by Ray Wenderlich所示。但是,這需要面具上的alpha透明度,這對我來說是一個難題。

我還發現了一個有趣的例子,我正在做一個名爲AVAnimator的庫和一個名爲KittyBoom的例子。這裏他們正在手動替換像素。我想用GLKit得到相同的結果。

任何進一步的方向或指導將在這裏有所幫助。提前致謝。

回答

2

GLKit是一個包含四個主要組件的框架,它們可以一起使用或分開使用:視圖/視圖控制器,數學庫,紋理加載器和效果。我從你的問題推測你所關心的問題GLKBaseEffect

有人可能會說GLKBaseEffect的生活目的是讓日常事情變得簡單。它主要是OpenGL ES 1.1固定功能流水線的替代品,以及一些常見的技巧。

你所追求的不是一個例行的固定功能流水線任務,所以要做到這一點意味着超越GLKBaseEffect的基本功能並編寫自己的着色器。這是個壞消息。好消息是,一旦進入着色器世界,這很容易。另一個好消息是,你可以期待出色的性能 - 而不是使用CPU來做CoreGraphics混合,你可以在GPU上做到這一點。

如果您不熟悉OpenGL ES 2.0(或3.0)着色器,則「硬」部分將用自定義代碼替換由GLKBaseEffect提供的客戶端OpenGL ES代碼和頂點着色器。儘管如此,還有很多示例代碼和教程。 (既然你已經跟隨光芒Wenderlich的網站,我敢肯定你會發現some goodones there),你需要做的主要事情是:

  1. 從頂點變換座標您使用的空間你的glDraw命令進入剪輯空間。對於2D的東西,這很容易,因爲你可以使用與GLKBaseEffecttransform屬性相同的矩陣設置。
  2. 加載你的兩個紋理(GLKTextureLoader可以在這裏幫助你很多)並將它們綁定到兩個紋理單元。
  3. 在您的客戶端代碼中,將每個頂點與一些紋理座標相關聯。(您可能已經這樣做了。)
  4. 在您的頂點着色器中,從uniform輸入中獲取紋理座標,並將它們傳遞給varying輸出。 (除非由於某些原因,您不需要做任何其他操作,除非您想轉換座標。)

經過所有設置之後,實際完成後續效果的部分非常簡單,都在你的片段着色器:

// texture units bound in client code 
uniform sampler2D colorTexture; 
uniform sampler2D maskTexture; 

// texture coordinate passed in from vertex shader 
// (and automatically interpolated across the face of the polygon) 
varying mediump vec2 texCoord; 

void main() { 
    // read a color from the color texture 
    lowp vec3 color = texture2D(colorTexture, texCoord).rgb; 

    // read a gray level from the mask texture 
    // (the mask is grayscale, so we only need one component 
    // of its color because the others are the same) 
    lowp float maskLevel = texture2D(maskTexture, texCoord).r; 

    // use the gray level from the mask as the alpha value in the output color 
    gl_FragColor = vec4(color, maskLevel); 
} 

而且,既然你提到這樣以24 fps,它建議你使用視頻。在這種情況下,你可以削減中間人 - 視頻幀已經在GPU上處理,並將它們放在CPU上的CGImages中,這會降低你的速度。看看CVOpenGLESTexture類和GLCameraRipple示例代碼,以幫助將視頻轉換爲紋理。

+0

感謝您的答覆。我肯定會進一步調查你在這裏提供的新信息。至於你最後一個關於GLCameraRipple的評論,這個應用程序獲取相機的視頻源。這也可能來自視頻文件嗎?再次感謝。 –

+0

該示例代碼從攝像頭捕獲中涉及的'AVCaptureOutput'出售的樣本緩衝區創建'CVOpenGLESTexture'。您還可以使用'AVAssetReader'從文件中獲取樣本緩衝區。儘管如此,有關這方面的細節仍然是一個單獨問題的佐證。 – rickster