原文链接:http://blog.hdlx.tk/index.php/2019/08/16/ios%e5%b0%86uiimage%e8%bd%ac%e4%b8%baopengl-texture/
一、swift
创建一个extension类 UIImage+Texture.switf
import UIKit
import OpenGLES
extension UIImage {
func createGLTexture() -> GLuint {
let cgImageRef = self.cgImage
let width = cgImageRef!.width
let height = cgImageRef!.height
let rect = CGRect(x: 0, y: 0, width: width, height: height)
let imageData = malloc(width * height * 4)
let context = CGContext(data: imageData, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: cgImageRef!.colorSpace!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue)
context?.clear(rect)
context?.draw(cgImageRef!, in: rect)
glEnable(GLenum(GL_TEXTURE_2D))
/**
* GL_TEXTURE_2D表示操作2D纹理
* 创建纹理对象,
* 绑定纹理对象,
*/
var textureID : GLuint = 0
glGenTextures(1, &textureID)
glBindTexture(GLenum(GL_TEXTURE_2D), textureID)
/**
* 纹理过滤函数
* 图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),
* 这时就可用glTexParmeteri()函数来确定如何把纹理象素映射成像素.
* 如何把图像从纹理图像空间映射到帧缓冲图像空间(即如何把纹理像素映射成像素)
*/
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_CLAMP_TO_EDGE); // S方向上的贴图模式
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_CLAMP_TO_EDGE); // T方向上的贴图模式
// 线性过滤:使用距离当前渲染像素中心最近的4个纹理像素加权平均值
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR);
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR);
/**
* 将图像数据传递给到GL_TEXTURE_2D中, 因其于textureID纹理对象已经绑定,所以即传递给了textureID纹理对象中。
* glTexImage2d会将图像数据从CPU内存通过PCIE上传到GPU内存。
* 不使用PBO时它是一个阻塞CPU的函数,数据量大会卡。
*/
glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(width), GLsizei(height), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), imageData);
// 结束后要做清理
glBindTexture(GLenum(GL_TEXTURE_2D), 0); //解绑
free(imageData);
return textureID
}
}
二、objective-c
创建分类UIImage+Texture
@implementation UIImage(Texture)
/**
* 加载image, 使用CoreGraphics将位图以RGBA格式存放. 将UIImage图像数据转化成OpenGL ES接受的数据.
* 然后在GPU中将图像纹理传递给GL_TEXTURE_2D。
* @return 返回的是纹理对象,该纹理对象暂时未跟GL_TEXTURE_2D绑定(要调用bind)。
* 即GL_TEXTURE_2D中的图像数据都可从纹理对象中取出。
*/
– (GLuint)createOGLTexture {
CGImageRef cgImageRef = [self CGImage];
GLuint width = (GLuint)CGImageGetWidth(cgImageRef);
GLuint height = (GLuint)CGImageGetHeight(cgImageRef);
CGRect rect = CGRectMake(0, 0, width, height);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc(width * height * 4);
CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0f, –1.0f);
CGColorSpaceRelease(colorSpace);
CGContextClearRect(context, rect);
CGContextDrawImage(context, rect, cgImageRef);
glEnable(GL_TEXTURE_2D);
/**
* GL_TEXTURE_2D表示操作2D纹理
* 创建纹理对象,
* 绑定纹理对象,
*/
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
/**
* 纹理过滤函数
* 图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),
* 这时就可用glTexParmeteri()函数来确定如何把纹理象素映射成像素.
* 如何把图像从纹理图像空间映射到帧缓冲图像空间(即如何把纹理像素映射成像素)
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // S方向上的贴图模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // T方向上的贴图模式
// 线性过滤:使用距离当前渲染像素中心最近的4个纹理像素加权平均值
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/**
* 将图像数据传递给到GL_TEXTURE_2D中, 因其于textureID纹理对象已经绑定,所以即传递给了textureID纹理对象中。
* glTexImage2d会将图像数据从CPU内存通过PCIE上传到GPU内存。
* 不使用PBO时它是一个阻塞CPU的函数,数据量大会卡。
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
NSLog(@”glTexImage2D error : %d” , glGetError());
// 结束后要做清理
glBindTexture(GL_TEXTURE_2D, 0); //解绑
CGContextRelease(context);
free(imageData);
return textureID;
}
@end