<h5>一、先上效果图</h5>
<h5>二、混合 的 主要代码</h5>
- (void)setupTextureInfo{
CGImageRef imageRef0 = [[UIImage imageNamed:@"leaves.gif"] CGImage];
self.textureInfo0 = [GLKTextureLoader textureWithCGImage:imageRef0 options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],GLKTextureLoaderOriginBottomLeft, nil] error:nil];
CGImageRef imageRef1 = [[UIImage imageNamed:@"beetle.png"] CGImage];
self.textureInfo1 = [GLKTextureLoader textureWithCGImage:imageRef1 options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],GLKTextureLoaderOriginBottomLeft, nil] error:nil];
self.baseEffect = [[GLKBaseEffect alloc] init];
glEnable(GL_BLEND); //开启混合
//表示把渲染的图像融合到目标区域。也就是说源的每一个像素的alpha都等于自己的alpha,
//目标的每一个像素的alpha等于1减去该位置源像素的alpha。 因此不论叠加多少次,亮度是不变的。
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
self.baseEffect.texture2d0.name = self.textureInfo0.name;
self.baseEffect.texture2d0.target = self.textureInfo0.target;
[self.baseEffect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 6);
self.baseEffect.texture2d0.name = self.textureInfo1.name;
self.baseEffect.texture2d0.target = self.textureInfo1.target;
[self.baseEffect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 6);
}
<h6>代码说明</h6>
- 通过glEnable (GL_BLEND) 函数来开启混合,
- 通过glBlendFunc (GLenum sfactor, GLenum dfactor)设置混合函数,告诉OpenGL它该如何混合。sfactor参数是源因子,dfactor参数是目标因子。
- 源和目标跟绘制的顺序有关,先绘制的是目标,随后绘制的是源。假设先红色,再在红色上绘制绿色,此时红色先进,假设我们希望在红色方块上绘制绿色方块。红色方块会成为目标颜色(因为它会先进入颜色缓冲),绿色就是源颜色。
- glBlendFunc可使用的混合参数如下:
混合参数 | 描述 |
---|---|
GL_ZERO | 使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算 |
GL_ONE | 使用1.0作为因子,实际上相当于完全的使用了这种颜色参与混合运算 |
GL_SRC_ALPHA | 表示使用源颜色的alpha值来作为因子 |
GL_DST_ALPHA | 表示使用目标颜色的alpha值来作为因子 |
GL_ONE_MINUS_SRC_ALPHA | 表示用1.0减去源颜色的alpha值来作为因子 |
<h5>三、多重纹理</h5>
- 我们发现,在每次更新显示的时候,调用2次glDrawArrays,混合函数需要从像素颜色渲染缓存读取颜色数据以便和片元颜色混合,然后结果被写回帧缓存。
- 当带有透明度的多个纹理层叠时,每个纹理的像素颜色渲染缓存会被再次读取、混合、重写。这种通过多次读写像素颜色渲染缓存来创建一个最终的渲染像素的过程叫“多通道渲染”。因为内存访问限制了性能,多通道渲染是次优的。
- 多重纹理可以避免多通道渲染导致的内存访问限制性能情况。
- 现代GPU都能够同时从至少两个纹理缓存中取样纹素。而GLKit的GLKBaseEffect同时支持两种纹理。
- 多重纹理引入了另一个组合配置选项。iOS中的GLKit的GLKEffectPropertyTexture类操作了3种常见的多重纹理模式,如下:
多重纹理混合模式 | 描述 |
---|---|
GLKTextureEnvModeReplace | 给第二个纹理设置该模式,只显示第二个纹理 |
GLKTextureEnvModeModulate | 默认使用,几乎总是产生最好的结果。它会让所有的为灯光和其他效果计算出来的颜色与从一个纹理取样的颜色相混合。 |
GLKTextureEnvModeDecal | 开启多重纹理,启用一个和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)类似的方程式来混合两个纹理 |
- 使用多重纹理模式,不需要再开启混合了(glEnable(GL_BLEND))
- 多重纹理支持为每个纹理使用不同的纹理坐标。本例中两个纹理使用相同的纹理坐标。
<h5>四、多重纹理 之 主要代码</h5>
- (void)setupMultipleTexture{
CGImageRef imageRef0 = [[UIImage imageNamed:@"leaves.gif"] CGImage];
self.textureInfo0 = [GLKTextureLoader textureWithCGImage:imageRef0 options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],GLKTextureLoaderOriginBottomLeft, nil] error:nil];
CGImageRef imageRef1 = [[UIImage imageNamed:@"beetle.png"] CGImage];
self.textureInfo1 = [GLKTextureLoader textureWithCGImage:imageRef1 options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],GLKTextureLoaderOriginBottomLeft, nil] error:nil];
self.baseEffect = [[GLKBaseEffect alloc] init];
self.baseEffect.texture2d0.name = self.textureInfo0.name;
self.baseEffect.texture2d0.target = self.textureInfo0.target;
self.baseEffect.texture2d1.name = self.textureInfo1.name;
self.baseEffect.texture2d1.target = self.textureInfo1.target;
self.baseEffect.texture2d1.envMode = GLKTextureEnvModeDecal;
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
[self.baseEffect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 6);
}
代码直通车:QSOpenGLES002_BlendTexture
篇外:纹理后续部分:关于自定义纹理和纹理压缩的内容,先填个坑,继续下一主题(光线)的学习。