生活随笔
收集整理的這篇文章主要介紹了
NDK OpenGL ES 3.0 开发(十七):相机基础滤镜
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
該原創(chuàng)文章首發(fā)于微信公眾號(hào):字節(jié)流動(dòng)
相機(jī)基礎(chǔ)濾鏡
上文中我們通過 ImageReader 獲取到 Camera2 預(yù)覽的 YUV 數(shù)據(jù),然后利用 OpenGLES 渲染實(shí)現(xiàn)相機(jī)預(yù)覽,這一節(jié)將利用 GLSL (OpenGL 著色器語言)基于不同的著色器實(shí)現(xiàn)多種基礎(chǔ)濾鏡。
GLSL 一些使用頻率比較高的內(nèi)建函數(shù)
內(nèi)建函數(shù)函數(shù)說明
| float distance (genType p0, genType p1) | 計(jì)算向量 p0 ,p1 之間的距離 |
| float length (genType x) | 返回向量 x 的長度 |
| genType floor (genType x) | 返回小于等于 x 的最大整數(shù)值 |
| genType ceil (genType x) | 返回大于等于 x 的最小整數(shù)值 |
| genType mod (genType x, float y) | 返回 x – y * floor (x / y) ,即求模計(jì)算 % |
| float dot (genType x, genType y) | 向量 x ,y 之間的點(diǎn)積 |
| vec3 cross (vec3 x, vec3 y) | 向量 x ,y 之間的叉積 |
| genType normalize (genType x) | 標(biāo)準(zhǔn)化向量,返回一個(gè)方向和 x 相同但長度為 1 的向量 |
動(dòng)態(tài)網(wǎng)格
動(dòng)態(tài)網(wǎng)格濾鏡主要是將紋理劃分為多個(gè)網(wǎng)格,然后根據(jù)一個(gè)偏移量動(dòng)態(tài)改變網(wǎng)格線的寬度。mod 和 floor 為 GLSL 的內(nèi)建函數(shù),分別表示取模和取整。需要注意的是,計(jì)算之前需要將紋理坐標(biāo)系轉(zhuǎn)換為圖片坐標(biāo)系,保證網(wǎng)格沒有被拉伸。
#version 100
precision highp
float;
varying vec2 v_texcoord
;
uniform lowp sampler2D s_textureY
;
uniform lowp sampler2D s_textureU
;
uniform lowp sampler2D s_textureV
;
uniform
float u_offset
;
uniform vec2 texSize
;
vec4
YuvToRgb(vec2 uv
) {float y
, u
, v
, r
, g
, b
;y
= texture2D(s_textureY
, uv
).r
;u
= texture2D(s_textureU
, uv
).r
;v
= texture2D(s_textureV
, uv
).r
;u
= u
- 0.5;v
= v
- 0.5;r
= y
+ 1.403 * v
;g
= y
- 0.344 * u
- 0.714 * v
;b
= y
+ 1.770 * u
;return vec4(r
, g
, b
, 1.0);
}
void main()
{vec2 imgTexCoord
= v_texcoord
* texSize
;float sideLength
= texSize
.y
/ 6.0;float maxOffset
= 0.15 * sideLength
;float x
= mod(imgTexCoord
.x
, floor(sideLength
));float y
= mod(imgTexCoord
.y
, floor(sideLength
));float offset
= u_offset
* maxOffset
;if(offset
<= x
&& x
<= sideLength
- offset
&& offset
<= y
&& y
<= sideLength
- offset
){gl_FragColor
= YuvToRgb(v_texcoord
);}else{gl_FragColor
= vec4(1.0, 1.0, 1.0, 1.0);}
}
分屏
分屏濾鏡的原理是在多個(gè)指定區(qū)域內(nèi)對(duì)整個(gè)紋理進(jìn)行下采樣(縮小),從而實(shí)現(xiàn)整個(gè)圖像在多個(gè)區(qū)域內(nèi)多次顯示。
#version 100
precision highp
float;
varying vec2 v_texcoord
;
uniform lowp sampler2D s_textureY
;
uniform lowp sampler2D s_textureU
;
uniform lowp sampler2D s_textureV
;
vec4
YuvToRgb(vec2 uv
) {float y
, u
, v
, r
, g
, b
;y
= texture2D(s_textureY
, uv
).r
;u
= texture2D(s_textureU
, uv
).r
;v
= texture2D(s_textureV
, uv
).r
;u
= u
- 0.5;v
= v
- 0.5;r
= y
+ 1.403 * v
;g
= y
- 0.344 * u
- 0.714 * v
;b
= y
+ 1.770 * u
;return vec4(r
, g
, b
, 1.0);
}
void main()
{vec2 newTexCoord
= v_texcoord
;if(newTexCoord
.x
< 0.5){newTexCoord
.x
= newTexCoord
.x
* 2.0;}else{newTexCoord
.x
= (newTexCoord
.x
- 0.5) * 2.0;}if(newTexCoord
.y
< 0.5){newTexCoord
.y
= newTexCoord
.y
* 2.0;}else{newTexCoord
.y
= (newTexCoord
.y
- 0.5) * 2.0;}gl_FragColor
= YuvToRgb(newTexCoord
);
}
縮放的圓
縮放的圓效果實(shí)現(xiàn)主要依賴偏移量來動(dòng)態(tài)改變圓半徑的大小,在半徑區(qū)域內(nèi)對(duì)紋理采樣顯示圖像,在半徑區(qū)域外返回一個(gè)固定顏色(如白色)。distance 也是 GLSL 的內(nèi)建函數(shù),用于計(jì)算兩點(diǎn)之間的距離。另外需要注意是,在計(jì)算之前首先要將紋理坐標(biāo)系轉(zhuǎn)換為圖片坐標(biāo)系,否則繪制的將會(huì)是一個(gè)橢圓形圖像(圖像寬高不同的情況下),想一想為什么會(huì)這樣?
#version 100
precision highp
float;
varying vec2 v_texcoord
;
uniform lowp sampler2D s_textureY
;
uniform lowp sampler2D s_textureU
;
uniform lowp sampler2D s_textureV
;
uniform
float u_offset
;
uniform vec2 texSize
;
vec4
YuvToRgb(vec2 uv
) {float y
, u
, v
, r
, g
, b
;y
= texture2D(s_textureY
, uv
).r
;u
= texture2D(s_textureU
, uv
).r
;v
= texture2D(s_textureV
, uv
).r
;u
= u
- 0.5;v
= v
- 0.5;r
= y
+ 1.403 * v
;g
= y
- 0.344 * u
- 0.714 * v
;b
= y
+ 1.770 * u
;return vec4(r
, g
, b
, 1.0);
}
void main()
{vec2 imgTex
= v_texcoord
* texSize
;float r
= (u_offset
+ 0.208 ) * texSize
.x
;if(distance(imgTex
, vec2(texSize
.x
/ 2.0, texSize
.y
/ 2.0)) < r
){gl_FragColor
= YuvToRgb(v_texcoord
);}else{gl_FragColor
= vec4(1.0, 1.0, 1.0, 1.0);}
}
在計(jì)算之前首先要將紋理坐標(biāo)系轉(zhuǎn)換為圖片坐標(biāo)系,其原因在于紋理縱橫坐標(biāo)的取值范圍均為 [0, 1] ,從數(shù)值上看紋理的縱橫方向長度相同,但是在 OpenGL 采樣時(shí),圖像的寬高比往往不是 1 ,這就導(dǎo)致了數(shù)值相同的縱橫坐標(biāo),對(duì)應(yīng)不同的采樣權(quán)重,出現(xiàn)了預(yù)期繪制圓形而實(shí)際上卻繪制出橢圓的情況。
聯(lián)系與交流
技術(shù)交流/獲取源碼可以添加我的微信:Byte-Flow
總結(jié)
以上是生活随笔為你收集整理的NDK OpenGL ES 3.0 开发(十七):相机基础滤镜的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。