使用OpenGL实现滤镜转换的一种思路

这儿定义的滤镜是一种表,输入源的每像素颜色,也就是RGB共256*256*256那么多种颜色,每种都能在滤镜表中找到一个替换色,从而实现画面观感的改变。

这里是一张滤镜表(64*64*64):

在OpenGL中,纹理颜色的定位规则和通常的数组操作不同。纹理无论宽高比例如何,有多长,有多宽,都是长为1,宽为1的一个对象,要定位纹理某个位置的颜色,需要使用比例的方式。

所以,在这里,RGB三个通道中,

R控制可以去到纵向的第几面,这儿有64面,即整个纵向可以分为64份,第一分为0,最后一份为63,即定位公式为Y1 = (R/255) * (1/63)

G可以控制R到达的面的第几行,每面有64行Y2 = (G/255) * (1/63/63)

最终Y = Y1+Y2 (先定位面,再定位行)

B通道大小决定选择滤镜表x轴的哪个位置,即(B / 255)* 63,如果滤镜表是更细腻的256*256*256一一对应的话,即直接是(B/255)*255即可。

 (最后定位某行的第几个位置的颜色)

 

 

按照以上规则,shader编写如下。故意使得只有左半边纹理应用滤镜规则,方便观察效果:

#version 300 es
precision highp float;
uniform sampler2D sTexture;
uniform sampler2D lutTexture;
in highp vec2 vTextureCoord;
out vec4 fragColor;
void main()
{
	if(vTextureCoord[0] < 0.5f) {//输入纹理,左半边使用滤镜规则替换像素
  	    vec4 srcColor = texture(sTexture, vec2(vTextureCoord[0], vTextureCoord[1]));
  	    float z = (floor(srcColor[0] * 64.0f) - 1.0f) * 0.015625f; //Z轴控制可以去到 64面 * 百分之几,控制可以去到的面,每面单位为1/64 = 0.015625
  	    float y = (floor(srcColor[1] * 64.0f) - 1.0f) * 0.015625f * 0.015625f; //Y轴控制可以去到其中一面的百分之几  1/64=0.015625
  	    float x = floor(srcColor[2] * 64.0f) * 0.015625f;
  	    if(z < 0.0f) z = 0.0f;
		if(y < 0.0f) y = 0.0f;
  	    float offsetY = (z + y);
  	    vec4 fragColorLut = texture(lutTexture, vec2(x, offsetY));
  	    fragColor = fragColorLut;
	} else {//右半边使用原图
  	    fragColor = texture(sTexture, vec2(vTextureCoord[0], vTextureCoord[1]));
	}
}

其中sTexture是原图,lutTexture是滤镜映射表。

 

最终效果:

 

当然作为手机预览来说,这样的精度可以说是足够了,但是如果要出精细的图,则需要更复杂的规则,例如256是64的4倍,每4个单位映射为1个单位,所以必须要计算出其是滤镜两个颜色之间的4个阶梯颜色,再进行替换。出图版本的滤镜shader下次再贴原理和代码,先下班,有点晚了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值