I’m having trouble mapping the iPhone camera output on a simple plane in OpenGLES 2.0. For some reason the OpenGL texture generated through the CVOpenGLESTextureCacheCreateTextureFromImage is flipped and rotated.
Here’s my situation: I made a Wavefront .obj loader that parses this simple plane object:
v -0.5 -0.5 0
v 0.5 -0.5 0
v -0.5 0.5 0
v 0.5 0.5 0
vt 0 0 0
vt 1 0 0
vt 0 1 0
vt 1 1 0
f 4/4 3/3 1/1
f 2/2 4/4 1/1
As far as I’m concerned my texture mapping works like it has to. I’ve verified this by mapping a simple png image onto the plane. It shows up correctly.
(Just for the record: I loaded the image in the iPhone coordinate system, flipped the image pixels to match the OpenGL’s top-left texture coordinate system and mapped everything). Result: works!
So, after shuffling my code around a bit and feeding the camera pixel buffer into my texture unit something goes wrong (or maybe this is intended behavior and I should counter that in one way or another? Any suggestions are welcome, as long as it isn’t CPU heavy code).
Here’s my code: some of it is inspired by Brad Larson‘s ColorTracking example and Apple’s GLCameraRipple example.
Code to capture the output:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
[self.delegate processNewCameraFrame:pixelBuffer];
}
After passing around the image buffer ref it ends up here:
- (void)updateCameraFrame:(CVImageBufferRef)pCameraFrame
{
if(cameraTextureMaterial)
{
cameraTextureMaterial->updateWithCameraFrame(pCameraFrame);
}
}
CamerTextureMaterial:
void CameraTextureMaterial::updateWithCameraFrame(CVImageBufferRef pixelBuffer)
{
if(!_videoTextureCache)
{
cout << "No video texture cache" << endl;
return;
}
cleanup();
CVReturn err;
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
glActiveTexture(GL_TEXTURE0);
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_videoTextureCache,
pixelBuffer,
NULL,
GL_TEXTURE_2D,
GL_RGBA,
width,
height,
GL_BGRA,
GL_UNSIGNED_BYTE,
0,
&_lumaTexture);
if (err)
{
cout << "Error at CVOpenGLESTextureCacheCreateTextureFromImage" << endl;
}
glBindTexture(CVOpenGLESTextureGetTarget(_lumaTexture), CVOpenGLESTextureGetName(_lumaTexture));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
I’m excluding initialization and cleanup of the texture cache since this doesn’t matter for my texture orientation problem.
Any suggestions on how to get the correct orientation for my texture?
Solving this issues was actually pretty easy by choosing your texture coordinates wisely. I rotated, flipped and cropped the camera texture by mapping it with the coordinates below and rendered the orthogonal scene to a new texture which I then use in my scene.
Coordinates I used:
Here’s how I render the plane to a new texture:
Some sample code:
Attach code: