OpenGL|OpenGL ES 案例07(GLSL使用索引绘图 + 纹理颜色混合)
本文案例代码有OC及Swift版本,详情见文末链接,讲解以OC版本为主本案例是在OpenGL ES 案例05:GLSL使用索引绘图案例的基础上
新增纹理与颜色的混合填充
功能整体效果图如下:
这个案例的思路很简单,主要就是OpenGL ES 案例04:GLSL加载图片与OpenGL ES 案例05:GLSL使用索引绘图案例中功能结合的一个综合案例,下面主要针对新增的功能作一个说明
如图所示,在案例05的基础上,作了以下修改
注:图中标准的
(!!!)
即表示需要修改或者新增代码的位置文章图片
主要需要修改和新增两个部分
- 自定义着色器
- renderLayer函数
文章图片
顶点着色器
- 新增
attribute
修饰的纹理坐标 - 新增
varying
修饰的桥接纹理坐标 - main函数中,将纹理坐标赋值给桥接纹理坐标
文章图片
片元着色器
- 新增与顶点中一致的桥接纹理坐标
- 新增
uniform
修饰的纹理采样器 - main函数中,计算每个像素的纹素并与顶点颜色混合,将最终的颜色值赋值给
gl_FragColor
文章图片
片元着色器中,颜色混合方式有两种
- 直接使用GLSL的内建函数
mix(x, y, alpha)
,返回一个vec4
类型的颜色值,内部的计算为x(1-alpha) +y*alpha
vec4 weakMask = texture2D(colorMap, varyTextCoord);
vec4 mask = varyColor;
//mix(x,y,a) return x(1-a) +y*a
gl_FragColor = mix(mask, weakMask, 0.3);
- 直接套用颜色混合计算公式
关于颜色的混合公式,在六、OpenGL 渲染技巧:深度测试、多边形偏移、 混合里,略有提及
vec4 weakMask = texture2D(colorMap, varyTextCoord);
vec4 mask = varyColor;
float alpha = 0.3;
vec4 tempColor = mask * (1.0 - alpha) + weakMask * alpha;
gl_FragColor = tempColor;
renderLayer函数
文章图片
render函数的主要功能是渲染,由于新增了纹理颜色混合,主要修改的是设置顶点数据部分,需要增加纹理相关数据、加载等
修改顶点数组
增加顶点的纹理坐标
//前3个元素,是顶点数据;中间3个元素,是顶点颜色值,最后2个是纹理坐标
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f,1.0f, 0.0f, 1.0f,0.0f, 1.0f,//左上
0.5f, 0.5f, 0.0f,1.0f, 0.0f, 1.0f,1.0f, 1.0f,//右上
-0.5f, -0.5f, 0.0f,1.0f, 1.0f, 1.0f,0.0f, 0.0f,//左下0.5f, -0.5f, 0.0f,1.0f, 1.0f, 1.0f,1.0f, 0.0f,//右下
0.0f, 0.0f, 1.0f,0.0f, 1.0f, 0.0f,0.5f, 0.5f,//顶点
};
新增纹理相关操作
- 处理纹理数据
将纹理坐标传入到顶点着色器 - 新增setupTexture函数,用于加载纹理
- 设置纹理采样器
用于采集纹理对应像素点的颜色,并传入片元着色器中,与顶点颜色进行混合
新增纹理相关代码如下
//---------处理纹理数据
GLuint textCoord = glGetAttribLocation(self.myPrograme, "textCoordinate");
glEnableVertexAttribArray(textCoord);
glVertexAttribPointer(textCoord, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, (float*)NULL+6);
//------加载纹理
[self setupTexture:@"mouse"];
//------设置纹理采样器
glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0);
setupTexture函数
主要是将png/jpg图片解压成位图,然后进行绑定、加载
- (GLuint)setupTexture: (NSString *)fileName{
//将UIImage转换为CGImageRef
CGImageRef image = [UIImage imageNamed:fileName].CGImage;
if (!image) {
NSLog(@"failed to load image %@", fileName);
exit(1);
}//获取图片的宽高
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
//获取图片的字节数
GLubyte *imageData = https://www.it610.com/article/(GLubyte *)calloc(width*height*4, sizeof(GLubyte));
//创建context & 使用默认方式绘制图片,即纹理的加载就是重新绘制图片
CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, width*4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
CGRect rect = CGRectMake(0, 0, width, height);
CGContextDrawImage(context, rect, image);
CGContextRelease(context);
//绑定纹理到默认的标识符0,0默认是激活状态
glBindTexture(GL_TEXTURE_2D, 0);
//设置纹理参数(过滤方式、环绕模式)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
float fw = width, fh = height;
//加载纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
return 0;
}
完整的代码见github - 11_02_GLSL三角形变换+纹理与颜色混合_OC、11_02_GLSL三角形变换+纹理与颜色混合_Swift
推荐阅读
- 翼光家长沙龙复盘
- 小程序有哪些低成本获客手段——案例解析
- 【文魁大脑实用记忆第五期】贤派张丽琼第8次案例一地理记忆有汽泡图
- W15L21-L22-电商企业案例分析
- 2.关于OpenGL|2.关于OpenGL 坐标系以及渲染流程
- 案例11(|案例11: “我们” 小成功关注个人,大成功关注大多数人)
- 从正面管教看家庭案例
- 集合框架(集合嵌套存储和遍历元素的案例代码实现)
- 目标管理模型的应用案例
- OpenGL|OpenGL ES之LUT(滤镜基准图)