在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)后,纹理在模拟器上正确渲染,但在真实设备上无法渲染。有什么建议吗?
答案 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];