OpenGL ES渲染到UIImage,图像是黑色的

时间:2012-07-06 13:09:18

标签: ios image opengl-es processing

在OpenGL ES的帮助下,我在图像处理方面遇到了一些问题。 我创建了一个纹理,加载着色器,并将它们附加到程序中,当我想渲染我的时 纹理到UIImage,图像是全黑的:(

纹理初始化:

glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &_name);
glBindTexture(self.format, _name);
glTexParameteri(self.format, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(self.format, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(self.format, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(self.format, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(self.format, 0);

纹理加载代码:

self.pixelSize = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale);

    BOOL shouldScale = NO;

    if (self.limitedSize.width < self.pixelSize.width ||
        self.limitedSize.height < self.pixelSize.height) {
        self.pixelSize = self.limitedSize;
    }

    if (shouldScale) {
        CGFloat normalizedWidth = ceil(log2(self.pixelSize.width));
        CGFloat normalizedHeight = ceil(log2(self.pixelSize.height));

        self.pixelSize = CGSizeMake(pow(2.0, normalizedWidth), powf(2.0, normalizedHeight));
        self.data = (GLubyte *)calloc(1, self.bytes);

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
        CGContextRef context = CGBitmapContextCreate(self.data, normalizedWidth, normalizedHeight, 8, normalizedWidth * 4, colorSpace, bitmapInfo);
        CGContextDrawImage(context, CGRectMake(0, 0, normalizedWidth, normalizedHeight), image.CGImage);
        CGContextRelease(context);
        CGColorSpaceRelease(colorSpace);
    }
    else {
        CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
        self.data = (GLubyte *)CFDataGetBytePtr(dataRef);
        CFRelease(dataRef);
    }

    glBindTexture(self.format, self.name);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexImage2D(self.format, 0, GL_RGBA, self.pixelSize.width, self.pixelSize.height, 0, GL_BGRA, self.type, self.data);
    glGenerateMipmap(GL_TEXTURE_2D);

帧缓冲:

glActiveTexture(GL_TEXTURE1);
glGenFramebuffers(1, &_buffer);
glBindFramebuffer(GL_FRAMEBUFFER, _buffer); // self.format is GL_TEXTURE_2D
glBindTexture(self.texture.format, self.texture.name);
glTexImage2D(self.texture.format, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, self.texture.format, self.texture.name, 0);

GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
    NSLog(@"GLBuffer: Failed to make framebuffer object");
}

glBindTexture(self.texture.format, 0);

渲染:

[self.buffer bind];
[self.program use];

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glActiveTexture(GL_TEXTURE2);
[self.texture bind];

glUniform1i([self.texture uniformForKey:@"inputImageTexture"], 2);
glUniform1f([self.texture uniformForKey:@"red"], 1.0);
glUniform1f([self.texture uniformForKey:@"green"], 0.0);
glUniform1f([self.texture uniformForKey:@"blue"], 0.0);

glVertexAttribPointer([self.texture attributeForKey:@"position"], 2, GL_FLOAT, 0, 0, [self.texture vertices]);
glEnableVertexAttribArray([self.texture attributeForKey:@"position"]);

glVertexAttribPointer([self.texture attributeForKey:@"inputTextureCoordinate"], 2, GL_FLOAT, 0, 0, [self.texture coordinates]);
glEnableVertexAttribArray([self.texture attributeForKey:@"inputTextureCoordinate"]);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

[self.buffer unbind];
[self.texture unbind];

纹理到图像:

  [self.buffer bind];
   GLubyte *rawPixels = (GLubyte *)malloc([self.texture bytes]);

glReadPixels(0, 0, [self.texture width], [self.texture height], GL_RGBA, GL_UNSIGNED_BYTE, rawPixels);
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rawPixels, [self.texture bytes], NULL);

NSUInteger bytesPerRow = [self.texture pixelWidth] * 4;
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGImageRef cgImage = CGImageCreate([self.texture pixelWidth], 
                                   [self.texture pixelHeight], 
                                   8,
                                   32, 
                                   bytesPerRow, 
                                   colorSpace, 
                                   bitmapInfo, 
                                   dataProvider,
                                   NULL, 
                                   NO, 
                                   kCGRenderingIntentDefault);


UIImage *image = [UIImage imageWithCGImage:cgImage];

CGImageRelease(cgImage);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);

从我的渲染方法中删除glClear(GL_COLOR_BUFFER_BIT)后,纹理在模拟器上正确渲染,但在真实设备上无法渲染。有什么建议吗?

1 个答案:

答案 0 :(得分:3)

将纹理转换为UIImage

`#pragma mark - Convert GL image to UIImage`
-(UIImage *) glToUIImage
{

    imageWidth = 702;
    imageHeight = 962;

    NSInteger myDataLength = imageWidth * imageHeight * 4;


    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

    // gl renders "upside down" so swap top to bottom into new array.
    // there's gotta be a better way, but this works.
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    for(int y = 0; y < imageHeight; y++)
    {
        for(int x = 0; x < imageWidth * 4; x++)
        {
            buffer2[((imageHeight - 1) - y) * imageWidth * 4 + x] = buffer[y * 4 * imageWidth + x];
        }
    }

    // make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);

    // prep the ingredients
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * imageWidth;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    // make the cgimage
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    // then make the uiimage from that
    UIImage *myImage = [UIImage imageWithCGImage:imageRef];
    return myImage;
}

通过调用此方法来获取您的图像 -

UIImage *yourImage = [self glToUIImage];

来源= http://www.bit-101.com/blog/?p=1861