最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android OpenGL ES 實現(xiàn)抖音傳送帶特效(原理解析)

 更新時間:2022年07月21日 09:48:11   作者:字節(jié)流動  
這篇文章主要介紹了Android OpenGL ES 實現(xiàn)抖音傳送帶特效,抖音傳送帶特效推出已經(jīng)很長一段時間了,前面也實現(xiàn)了下,最近把它整理出來了,如果你有仔細(xì)觀測傳送帶特效,就會發(fā)現(xiàn)它的實現(xiàn)原理其實很簡單,需要的朋友可以參考下

抖音 APP 真是個好東西,不過也容易上癮,老實說你的抖音是不是反復(fù)卸載又反復(fù)安裝了,后來我也發(fā)現(xiàn)我的幾個 leader 都不刷抖音,這令我挺吃驚的。

我刷抖音主要是為了看新聞,聽一些大 V 講歷史,研究抖音的一些算法特效,最重要的是抖音提供了一個年輕人的視角去觀察世界。另外,自己感興趣的內(nèi)容看多了,反而訓(xùn)練抖音推送更多類似的優(yōu)質(zhì)內(nèi)容,大家可以反向利用抖音的這一特點。

至于我的 leader 老是強調(diào)刷抖音不好,對此我并不完全認(rèn)同。

抖音傳送帶特效原理

抖音傳送帶特效推出已經(jīng)很長一段時間了,前面也實現(xiàn)了下,最近把它整理出來了,如果你有仔細(xì)觀測傳送帶特效,就會發(fā)現(xiàn)它的實現(xiàn)原理其實很簡單。

通過仔細(xì)觀察抖音的傳送帶特效,你可以發(fā)現(xiàn)左側(cè)是不停地更新預(yù)覽畫面,右側(cè)看起來就是一小格一小格的豎條狀圖像區(qū)域不斷地向右移動,一直移動到右側(cè)邊界位置。

預(yù)覽的時候每次拷貝一小塊預(yù)覽區(qū)域的圖像送到傳送帶,這就形成了源源不斷地向右傳送的效果。

原理圖進(jìn)行了簡化處理, 實際上右側(cè)的豎條圖像更多,效果會更流暢,每來一幀預(yù)覽圖像,首先拷貝更新左側(cè)預(yù)覽畫面,然后從最右側(cè)的豎條圖像區(qū)域開始拷貝圖像(想一想為什么?)。

例如將區(qū)域 2 的像素拷貝到區(qū)域 3 ,然后將區(qū)域 1 的像素拷貝到區(qū)域 2,以此類推,最后將來源區(qū)域的像素拷貝到區(qū)域 0 。

這樣就形成了不斷傳送的效果,最后將拷貝好的圖像更新到紋理,利用 OpenGL 渲染到屏幕上。

抖音傳送帶特效實現(xiàn)

上節(jié)原理分析時,將圖像區(qū)域從左側(cè)到右側(cè)拷貝并不高效,可能會導(dǎo)致一些性能問題,好在 Android 相機出圖都是橫向的(旋轉(zhuǎn)了 90 或 270 度),這樣圖像區(qū)域上下拷貝效率高了很多,最后渲染的時候再將圖像旋轉(zhuǎn)回來。

Android 相機出圖是 YUV 格式的,這里為了拷貝處理方便,先使用 OpenCV 將 YUV 圖像轉(zhuǎn)換為 RGBA 格式,當(dāng)然為了追求性能直接使用 YUV 格式的圖像問題也不大。

cv::Mat mati420 = cv::Mat(pImage->height * 3 / 2, pImage->width, CV_8UC1, pImage->ppPlane[0]);
cv::Mat matRgba = cv::Mat(m_SrcImage.height, m_SrcImage.width, CV_8UC4, m_SrcImage.ppPlane[0]);
cv::cvtColor(mati420, matRgba, CV_YUV2RGBA_I420);

用到的著色器程序就是簡單的貼圖:

#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_texCoord;
uniform mat4 u_MVPMatrix;
out vec2 v_texCoord;
void main()
{
gl_Position = u_MVPMatrix * a_position;
v_texCoord = a_texCoord;
}

#version 300 es
precision mediump float;
in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D u_texture;

void main()
{
    outColor = texture(u_texture, v_texCoord);
}

傳送帶的核心就是圖像拷貝操作:

memcpy(m_RenderImage.ppPlane[0], m_SrcImage.ppPlane[0], m_RenderImage.width * m_RenderImage.height * 4 / 2); //左側(cè)預(yù)覽區(qū)域像素拷貝

int bannerHeight = m_RenderImage.height / 2 / m_bannerNum;//一個 banner 的高(小豎條)
int bannerPixelsBufSize = m_RenderImage.width * bannerHeight * 4;//一個 banner 占用的圖像內(nèi)存

uint8 *pBuf = m_RenderImage.ppPlane[0] + m_RenderImage.width * m_RenderImage.height * 4 / 2; //傳送帶分界線

//從最右側(cè)的豎條圖像區(qū)域開始拷貝圖像
for (int i = m_bannerNum - 1; i >= 1; --i) {
    memcpy(pBuf + i*bannerPixelsBufSize, pBuf + (i - 1)*bannerPixelsBufSize, bannerPixelsBufSize);
}

//將來源區(qū)域的像素拷貝到豎條圖像區(qū)域 0
memcpy(pBuf, pBuf - bannerPixelsBufSize, bannerPixelsBufSize);

渲染操作:

glUseProgram (m_ProgramObj);

glBindVertexArray(m_VaoId);

glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);

//圖像拷貝,傳送帶拷貝
memcpy(m_RenderImage.ppPlane[0], m_SrcImage.ppPlane[0], m_RenderImage.width * m_RenderImage.height * 4 / 2);
int bannerHeight = m_RenderImage.height / 2 / m_bannerNum;
int bannerPixelsBufSize = m_RenderImage.width * bannerHeight * 4;

uint8 *pBuf = m_RenderImage.ppPlane[0] + m_RenderImage.width * m_RenderImage.height * 4 / 2; //傳送帶分界線

for (int i = m_bannerNum - 1; i >= 1; --i) {
    memcpy(pBuf + i*bannerPixelsBufSize, pBuf + (i - 1)*bannerPixelsBufSize, bannerPixelsBufSize);
}
memcpy(pBuf, pBuf - bannerPixelsBufSize, bannerPixelsBufSize);

//更新紋理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_TextureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImage.width, m_RenderImage.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_RenderImage.ppPlane[0]);
glBindTexture(GL_TEXTURE_2D, GL_NONE);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_TextureId);
GLUtils::setInt(m_ProgramObj, "u_texture", 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);
glBindVertexArray(GL_NONE);

詳細(xì)實現(xiàn)代碼見項目:github.com/githubhaoha…

到此這篇關(guān)于Android OpenGL ES 實現(xiàn)抖音傳送帶特效的文章就介紹到這了,更多相關(guān)Android 抖音傳送帶特效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android自定義HorizontalScrollView實現(xiàn)qq側(cè)滑菜單

    Android自定義HorizontalScrollView實現(xiàn)qq側(cè)滑菜單

    本文主要介紹了android自定義HorizontalScrollView實現(xiàn)qq側(cè)滑菜單的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-04-04
  • Android實現(xiàn)地理定位功能

    Android實現(xiàn)地理定位功能

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)地理定位功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android自定義格式顯示Button的布局思路

    Android自定義格式顯示Button的布局思路

    下文的效果都是xml布局文件實現(xiàn)的,一張圖片都未曾使用,順便貼出幾個布局文件留個大家參考下,感性的朋友可不要錯過了哈
    2013-04-04
  • 詳解Android自定義控件屬性TypedArray以及attrs

    詳解Android自定義控件屬性TypedArray以及attrs

    這篇文章主要為大家介紹了android自定義控件屬性TypedArray以及attrs,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Android shape和selector 結(jié)合使用實例代碼

    Android shape和selector 結(jié)合使用實例代碼

    本篇文章主要介紹了Android shape和selector 的使用,這里提供了shape 和selector 的詳細(xì)介紹,并附有代碼實例,有興趣的朋友可以參考下
    2016-07-07
  • 教你制作Android中炫酷的ViewPagerIndicator(不僅仿MIUI)

    教你制作Android中炫酷的ViewPagerIndicator(不僅仿MIUI)

    ViewPagerIndicator作為一款分頁指標(biāo)小部件兼容ViewPager,封裝上做得非常不錯,目前已為眾多知名應(yīng)用所使用。今天給你大家分享一個炫酷的效果,有需要的可以參考學(xué)習(xí)。
    2016-08-08
  • Android實現(xiàn)TCP客戶端接收數(shù)據(jù)的方法

    Android實現(xiàn)TCP客戶端接收數(shù)據(jù)的方法

    這篇文章主要介紹了Android實現(xiàn)TCP客戶端接收數(shù)據(jù)的方法,較為詳細(xì)的分析了Android基于TCP實現(xiàn)客戶端接收數(shù)據(jù)的相關(guān)技巧與注意事項,需要的朋友可以參考下
    2016-04-04
  • Android實現(xiàn)自定義飄雪效果

    Android實現(xiàn)自定義飄雪效果

    隨著冬季的腳步越來越遠(yuǎn),南方的我今年就看了一場雪,下一場雪遙遙無期,那我們來實現(xiàn)一個自定義的 View,它能模擬雪花飄落的景象,所以本文給大家介紹了基于Android實現(xiàn)自定義飄雪效果,感興趣的朋友可以參考下
    2024-01-01
  • Android界面刷新的方法分享

    Android界面刷新的方法分享

    Android界面刷新的方法分享,需要的朋友可以參考一下
    2013-05-05
  • Android實現(xiàn)拼圖游戲

    Android實現(xiàn)拼圖游戲

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)拼圖小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論

巫溪县| 莱西市| 郎溪县| 同仁县| 商河县| 密山市| 天气| 永德县| 滦南县| 尖扎县| 桂阳县| 桐庐县| 平定县| 眉山市| 灌南县| 小金县| 锦州市| 镇雄县| 长岛县| 临夏县| 瑞安市| 理塘县| 馆陶县| 开平市| 西乌| 平山县| 明溪县| 广宁县| 中宁县| 伊春市| 洛阳市| 奇台县| 屯昌县| 石河子市| 济源市| 聂荣县| 时尚| 大洼县| 建宁县| 周口市| 永兴县|