android opengl分屏,OpenGL ES 分屏滤镜

想要绘制滤镜首先我们需要清楚如何绘制纹理,如果不了解的可以参考 OpenGL ES 纹理绘制。

这篇文章中绘制的图片是倒立的,我们需要将图片反转过来。方法很多,这里就简单介绍一种常用的方法,反转坐标系:

CGContextRef contextRef = CGBitmapContextCreate(imageData, width, height, 8, width * 4, colorRGBSpaceRef, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGRect rect = CGRectMake(0, 0, width, height);

CGContextTranslateCTM(contextRef, rect.origin.x, rect.origin.y);

CGContextTranslateCTM(contextRef, 0, rect.size.height);

CGContextScaleCTM(contextRef, 1.0, -1.0);

CGContextTranslateCTM(contextRef, -rect.origin.x, -rect.origin.y);

0、先将图片contextRef先移动到它的位置坐标rect.origin.x、rect.origin.y

1、将图片contextRef沿Y轴方向移动图片的高度的距离height。

2、沿Y轴缩放-1.0,这时图片已经翻转过来了,只是位置不对。

3、将图片contextRef恢复到原来的位置坐标rect.origin.x、rect.origin.y

下面我们开始讲解下滤镜的处理。

一、分屏滤镜

我们这里做了一分屏、二分屏、三分屏、四分屏、六分屏、九分屏的效果,当然一分屏其实就是正常的绘制。

这里分屏效果的代码全部都是在片元着色程序.fsh中修改的,只需要处理纹理坐标即可。

一分屏(正常绘制).fsh代码:

precision highp float;

varying vec2 textureCoords;

uniform sampler2D texture;

void main()

{

vec4 mask = texture2D(texture, textureCoords);

gl_FragColor = vec4(mask.rgb, 1.0);

}

正常效果:

b432bc85982e

二分屏.fsh代码:

precision highp float;

varying vec2 textureCoords;

uniform sampler2D texture;

void main()

{

vec2 uv = textureCoords.xy;

if (uv.y <= 0.5 && uv.y >= 0.0) {

uv.y += 0.25;

} else {

uv.y -= 0.25;

}

gl_FragColor = texture2D(texture, uv);

}

这里将纹理坐标在Y方向上分成了两个区域:[0.0, 0.5] 和 [0.5, 1.0]。

这里我们要求尽可能取图片中间位置的纹理。所以为了将屏幕铺满,就需要取在Y方向上[0.25, 0.75]之间的位置。

所以,在[0.0, 0.5] 区域时,Y方向上需要加上0.25。在[0.5, 1.0] 区域时,Y方向上需要减去0.25。

二分屏效果:

b432bc85982e

三分屏.fsh代码:

precision highp float;

varying vec2 textureCoords;

uniform sampler2D texture;

void main()

{

vec2 uv = textureCoords.xy;

float detal = 1.0/3.0;

if (uv.y <= detal && uv.y >= 0.0) {

uv.y += detal;

} else if (uv.y > detal * 2.0) {

uv.y -= detal;

}

gl_FragColor = texture2D(texture, uv);

}

三分屏将纹理坐标在Y方向上分成了三个区域:[0.0, 1.0/3.0]、 [1.0/3.0, 2.0/3.0]、[2.0/3.0, 1.0]。

这里同样要求尽可能取图片中间位置的纹理。所以为了将屏幕铺满,就需要取在Y方向上[1.0/3.0, 2.0/3.0]之间的位置。

所以,在[0.0, 1.0/3.0] 区域时,Y方向上需要加上1.0/3.0。在[1.0/3.0, 2.0/3.0]正好对应上中间的纹理,所以不用修改。在[2.0/3.0, 1.0] 区域时,Y方向上需要减去1.0/3.0。

三分屏效果:

b432bc85982e

四分屏.fsh代码:

precision highp float;

varying vec2 textureCoords;

uniform sampler2D texture;

void main()

{

vec2 uv = textureCoords.xy;

float detal = 0.5;

if (uv.x <= detal && uv.x >= 0.0) {

uv.x *= 2.0;

} else if (uv.x > detal) {

uv.x = (uv.x - detal) * 2.0;

}

if (uv.y <= detal && uv.y >= 0.0) {

uv.y *= 2.0;

} else if (uv.y > detal) {

uv.y = (uv.y - detal) * 2.0;

}

gl_FragColor = texture2D(texture, uv);

}

四分屏需要将纹理坐标分成四个区域:

Y方向[0.0, 0.5] 和 [0.5, 1.0]。

X方向[0.0, 0.5] 和 [0.5, 1.0]。

两两结合构成四个区域。

这里要求每个区域都展示完整的图片。

所以无论X、Y,范围在[0.0, 0.5]时坐标都需要乘以2.0

范围在[0.5, 1.0] 时,坐标都需要减去先0.5再乘以2.0

四分屏效果:

b432bc85982e

六分屏.fsh代码:

precision highp float;

varying vec2 textureCoords;

uniform sampler2D texture;

void main()

{

vec2 uv = textureCoords.xy;

float detal = 1.0/3.0;

if (uv.x <= detal && uv.x >= 0.0) {

uv.x += detal;

} else if (uv.x >= detal * 2.0) {

uv.x -= detal;

}

if (uv.y <= 0.5 && uv.y >= 0.0) {

uv.y += 0.25;

} else {

uv.y -= 0.25;

}

gl_FragColor = texture2D(texture, uv);

}

六分屏将纹理坐标分成六个区域:

X方向[0.0, 1.0/3.0] 、 [1.0/3.0, 2.0/3.0]、 [2.0/3.0, 1.0]。

Y方向[0.0, 0.5] 和 [0.5, 1.0]。

两两结合构成六个区域。

这里同样要求尽可能取图片中间位置的纹理。所以为了将屏幕铺满,就需要取在X方向上[1.0/3.0, 2.0/3.0]之间的位置。在Y方向上取[0.25, 0.75]之间的位置。

所以

X方向上:在[0.0, 1.0/3.0] 区域时,X方向上需要加上1.0/3.0。在[1.0/3.0, 2.0/3.0]正好对应上中间的纹理,所以不用修改。在[2.0/3.0, 1.0] 区域时,X方向上需要减去1.0/3.0。

Y方向上:在[0.0, 0.5] 区域时,Y方向上需要加上0.25。在[0.5, 1.0] 区域时,Y方向上需要减去0.25。

六分屏效果:

b432bc85982e

九分屏.fsh代码:

precision highp float;

varying vec2 textureCoords;

uniform sampler2D texture;

void main()

{

vec2 uv = textureCoords.xy;

float detal = 1.0/3.0;

if (uv.x <= detal && uv.x >= 0.0) {

uv.x *= 3.0;

} else if (uv.x > detal && uv.x < detal * 2.0) {

uv.x = (uv.x - detal) * 3.0;

} else {

uv.x = (uv.x - detal * 2.0) * 3.0;

}

if (uv.y <= detal && uv.y >= 0.0) {

uv.y *= 3.0;

} else if (uv.y > detal && uv.y < detal * 2.0) {

uv.y = (uv.y - detal) * 3.0;

} else {

uv.y = (uv.y - detal * 2.0) * 3.0;

}

gl_FragColor = texture2D(texture, uv);

}

九分屏需要将纹理坐标分成九个区域:

Y方向[0.0, 1.0/3.0] 、 [1.0/3.0, 2.0/3.0]、 [2.0/3.0, 1.0]。

X方向[0.0, 1.0/3.0] 、 [1.0/3.0, 2.0/3.0]、 [2.0/3.0, 1.0]。

两两结合构成九个区域。

这里要求每个区域都展示完整的图片。

所以无论X、Y:

范围在[0.0, 1.0/3.0]时坐标需要乘以3.0。

范围在[1.0/3.0, 2.0/3.0]时,坐标需要先减去1.0/3.0再乘以3.0。

范围在[2.0/3.0, 1.0]时,坐标需要先减去2.0/3.0再乘以3.0。

九分屏效果:

b432bc85982e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值