[英]Render YpCbCr iPhone 4 Camera Frame to an OpenGL ES 2.0 Texture in iOS 4.3
我正試圖在iPhone 4上的iOS 4.3中將原生平面圖像渲染為OpenGL ES 2.0紋理。然而,紋理全部變黑。 我的相機配置如下:
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]
forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
我將像素數據傳遞給我的紋理,如下所示:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_RGB_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, CVPixelBufferGetBaseAddress(cameraFrame));
我的fragement着色器是:
varying highp vec2 textureCoordinate;
uniform sampler2D videoFrame;
void main() {
lowp vec4 color;
color = texture2D(videoFrame, textureCoordinate);
lowp vec3 convertedColor = vec3(-0.87075, 0.52975, -1.08175);
convertedColor += 1.164 * color.g; // Y
convertedColor += vec3(0.0, -0.391, 2.018) * color.b; // U
convertedColor += vec3(1.596, -0.813, 0.0) * color.r; // V
gl_FragColor = vec4(convertedColor, 1.0);
}
我的頂點着色器是
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
}
當我使用BGRA圖像時,這很好用,而我的片段着色器只能這樣做
gl_FragColor = texture2D(videoFrame, textureCoordinate);
如果我在這里遺失了什么? 謝謝!
好。 我們在這里取得了成功。 關鍵是將Y和UV作為兩個單獨的紋理傳遞給片段着色器。 這是最終的着色器:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 textureCoordinate;
uniform sampler2D videoFrame;
uniform sampler2D videoFrameUV;
const mat3 yuv2rgb = mat3(
1, 0, 1.2802,
1, -0.214821, -0.380589,
1, 2.127982, 0
);
void main() {
vec3 yuv = vec3(
1.1643 * (texture2D(videoFrame, textureCoordinate).r - 0.0625),
texture2D(videoFrameUV, textureCoordinate).r - 0.5,
texture2D(videoFrameUV, textureCoordinate).a - 0.5
);
vec3 rgb = yuv * yuv2rgb;
gl_FragColor = vec4(rgb, 1.0);
}
您需要像這樣創建紋理:
int bufferHeight = CVPixelBufferGetHeight(cameraFrame);
int bufferWidth = CVPixelBufferGetWidth(cameraFrame);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferWidth, bufferHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddressOfPlane(cameraFrame, 0));
glBindTexture(GL_TEXTURE_2D, videoFrameTextureUV);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddressOfPlane(cameraFrame, 1));
然后像這樣傳遞它們:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, videoFrameTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, videoFrameTextureUV);
glActiveTexture(GL_TEXTURE0);
glUniform1i(videoFrameUniform, 0);
glUniform1i(videoFrameUniformUV, 1);
男孩,我松了一口氣!
PS yuv2rgb矩陣的值來自http://en.wikipedia.org/wiki/YUV ,我從這里復制代碼http://www.ogre3d.org/forums/viewtopic.php?f=5&t=25877找出如何獲得正確的YUV值。
您的代碼似乎嘗試將444-plus-unused-byte中的32位顏色轉換為RGBA。 這不會太好用。 我不知道任何輸出“YUVA”的東西。
此外,我認為返回的alpha通道對於BGRA相機輸出為0,而不是1,所以我不確定它為什么會起作用(IIRC將其轉換為CGImage,您需要使用AlphaNoneSkipLast)。
420“雙平面”輸出結構如下:
CVPixelBufferGetBaseAddressOfPlane()
和朋友使用) bytes_per_row_1
大約是width
, bytes_per_row_2
大約是width/2
,但是你需要使用CVPixelBufferGetBytesPerRowOfPlane()來獲得健壯性(你也可以查看..GetHeightOfPlane和... GetWidthOfPlane的結果)。
您可以將它視為單組分寬*高紋理和雙組分寬度/ 2 *高/ 2紋理。 您可能希望檢查每行字節數並處理不僅僅是寬度*組件數的情況(盡管對於大多數視頻模式可能都是如此)。 AIUI,您還需要在調用CVPixelBufferUnlockBaseAddress()之前刷新GL上下文。
或者,您可以將其全部復制到內存中以達到預期的格式(優化此循環可能有點棘手)。 復制的優點是,在解鎖像素緩沖區后,您無需擔心訪問內存的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.