日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NDK OpenGL ES 3.0 开发(十七):相机基础滤镜

發布時間:2024/1/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NDK OpenGL ES 3.0 开发(十七):相机基础滤镜 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

該原創文章首發于微信公眾號:字節流動

相機基礎濾鏡

上文中我們通過 ImageReader 獲取到 Camera2 預覽的 YUV 數據,然后利用 OpenGLES 渲染實現相機預覽,這一節將利用 GLSL (OpenGL 著色器語言)基于不同的著色器實現多種基礎濾鏡。

GLSL 一些使用頻率比較高的內建函數

內建函數函數說明
float distance (genType p0, genType p1)計算向量 p0 ,p1 之間的距離
float length (genType x)返回向量 x 的長度
genType floor (genType x)返回小于等于 x 的最大整數值
genType ceil (genType x)返回大于等于 x 的最小整數值
genType mod (genType x, float y)返回 x – y * floor (x / y) ,即求模計算 %
float dot (genType x, genType y)向量 x ,y 之間的點積
vec3 cross (vec3 x, vec3 y)向量 x ,y 之間的叉積
genType normalize (genType x)標準化向量,返回一個方向和 x 相同但長度為 1 的向量

動態網格


動態網格濾鏡主要是將紋理劃分為多個網格,然后根據一個偏移量動態改變網格線的寬度。mod 和 floor 為 GLSL 的內建函數,分別表示取模和取整。需要注意的是,計算之前需要將紋理坐標系轉換為圖片坐標系,保證網格沒有被拉伸。

//dynimic mesh 動態網格著色器 #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);} }

分屏


分屏濾鏡的原理是在多個指定區域內對整個紋理進行下采樣(縮小),從而實現整個圖像在多個區域內多次顯示。

//分屏(四分屏) #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); }

縮放的圓


縮放的圓效果實現主要依賴偏移量來動態改變圓半徑的大小,在半徑區域內對紋理采樣顯示圖像,在半徑區域外返回一個固定顏色(如白色)。distance 也是 GLSL 的內建函數,用于計算兩點之間的距離。另外需要注意是,在計算之前首先要將紋理坐標系轉換為圖片坐標系,否則繪制的將會是一個橢圓形圖像(圖像寬高不同的情況下),想一想為什么會這樣?

//scale circle 縮放的圓 #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);} }

在計算之前首先要將紋理坐標系轉換為圖片坐標系,其原因在于紋理縱橫坐標的取值范圍均為 [0, 1] ,從數值上看紋理的縱橫方向長度相同,但是在 OpenGL 采樣時,圖像的寬高比往往不是 1 ,這就導致了數值相同的縱橫坐標,對應不同的采樣權重,出現了預期繪制圓形而實際上卻繪制出橢圓的情況。

聯系與交流

技術交流/獲取源碼可以添加我的微信:Byte-Flow

總結

以上是生活随笔為你收集整理的NDK OpenGL ES 3.0 开发(十七):相机基础滤镜的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。