androidopengl視頻
⑴ 求android opengl教程
你放QQ吧 這里不能發鏈接
⑵ 如何使用Android中的OpenGL ES媒體效果
Android的媒體效果框架允許開發者可以很容易的應用多種令人印象深刻的視覺效果到照片或視頻之上。作為這個媒體效果的框架,它使用GPU來處
理圖片處理的過程,它僅僅接收OpenGL的紋理(texture)作為輸入。在本次教程中,你將會學習到如何使用OpenGL
ES2.0將圖片資源轉化為紋理,以及如何使用框架為圖片應用不同的處理效果。
准備
為了開始本次的教程,你必須具備:
1.一款支持Android開發的IDE,如果你沒有的話,可以在Android Developer website下載最新版本的Android studio。
2.一款運行Android4.0之上Android手機,並且GPU支持OpenGL ES2.0
3.對OpenGL的基本知識了解
設置OpenGL ES環境
創建GLSurfaceView
為了顯示OpenGL的圖形,你需要使用GLSurfaceView類,就像其他任何的View子類意義,你可以將它添加到你的Activity或Fragment之上,通過在布局xml文件中定義或者在代碼中創建實例。
在本次的教程中,我們使用GLSurfaceView作為唯一的View在我們的Activity中,因此,為了簡便,我們在代碼中創建
GLSurfaceView的實例並將其傳入setContentView中,這樣它將會填充你的整個手機屏幕。Activity中的onCreate方
法如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView view = new GLSurfaceView(this);
setContentView(view);
}
因為媒體效果的框架僅僅支持OpenGL ES2.0及以上的版本,所以在setEGLContextClientVersion 方法中傳入2;
view.setEGLContextClientVersion(2);
為了確保GLSurfaceView僅僅在必要的時候進行渲染,我們在setRenderMode 方法中進行設置:
view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
創建Renderer
Renderer負責渲染GLSurfaceView中的內容。
創建類實現介面GLSurfaceView.Renderer,在這里我們打算將這個類命名為EffectsRenderer,添加構造函數並覆寫介面中的抽象方法,如下:
public class EffectsRenderer implements GLSurfaceView.Renderer {
public EffectsRenderer(Context context){
super();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
@Override
public void onDrawFrame(GL10 gl) {
}
}
回到Activity中調用setRenderer方法,讓GLSurfaceView使用我們創建的Renderer:
view.setRenderer(new EffectsRenderer(this));
編寫Manifest文件
如果你想要發布你的App到谷歌商店,在AndroidManifest.xml文件中添加如下語句:
這會確保你的app只能被安裝在支持OpenGL ES2.0的設備之上。現在OpenGL環境准備完畢。
創建一個OpenGL平面
定義頂點
GLSurfaceView是不能直接顯示一張照片的,照片首先應該被轉化為紋理,應用在OpenGL square之上。在本次教程中,我將創建一個2D平面,並且具有4個頂點。為了簡單,我將使用一個長方形,現在,創建一個新的類Square,用它來代表形狀。
public class Square {
}
默認的OpenGL系統的坐標系中的原點是在中心,因此4個角的坐標可以表示為:
左下角: (-1, -1) 右下角:(1, -1) 右上角:(1, 1) 左上角:(-1, 1)
我們使用OpenGL繪制的所有的物體都應該是由三角形決定的,為了畫一個方形,我們需要兩個具有一條公共邊的三角形,那意味著這些三角形的坐標應該是:
triangle 1: (-1, -1), (1, -1), 和 (-1, 1) triangle 2: (1, -1), (-1, 1), 和 (1, 1)
創建一個float數組來代表這些頂點:
private float vertices[] = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f,
};
為了在square上定位紋理,需要確定紋理的頂點坐標,創建另一個數組來表示紋理頂點的坐標:private float textureVertices[] = {
0f,1f,
1f,1f,
0f,0f,
1f,0f
};
⑶ Android音視頻(六) 使用OpenGL ES 3.0預覽Camera
剛學習了OpenGL的紋理相關知識,終於可以接著寫Android音視頻系列了。
本篇博客會介紹使用OpenGL ES 3.0相關知識預覽Camera,並且提供Camera和Camera2兩個版本實現。
頂點著色器
片段著色器
紋理的類型需要使用 samplerExternalOES ,而不是之前渲染圖片的 sampler2D。
我們知道Android相機輸出的原始數據一般都為YUV數據,而在OpenGL中使用的絕大部分紋理ID都是RGBA的格式,所以原始數據都是無法直接用OpenGL ES來渲染的。所以我們添加了一個擴展 #extension GL_OES_EGL_image_external_essl3 : require ,其中定義了一個紋理的擴展類型 GL_TEXTURE_EXTERNAL_OES 。後面綁定紋理時需要綁定到 GL_TEXTURE_EXTERNAL_OES 上,而不是類型GL_TEXTURE_2D上。
其實前面部分和載入圖片沒有什麼區別,最後兩行,對應上面流程中的1、2步。創建紋理,綁定外部紋理,然後根據紋理ID創建SurfaceTexture作為相機預覽輸出。
使用Camera2在OpenGL方面其實是一樣的,並沒有什麼改動。所以只需要看一下Camera2的調用就好。
源碼地址
⑷ 短視頻編輯:可實時交互的播放器
如何開發一個類似剪影或抖音的視頻剪輯工具?
其開發任務如上圖,一個短視頻生產app的首要任務在於實現一個高度可實時交互的播放器,在播放預覽時支持多種編輯能力。
最初我們調研了多種方案,乍一看Android原生播放器肯定不夠用,估計要在眾多c++的開源播放器中尋找參考方案,最好自己實現一個播放器,高度靈活高度可控。然而我們發現exo這個男團播放器的厲害之處,雖然這個播放器如此常用,但是我們不知道其潛力值爆表,可以拓展得如此強大。
事實上直到現在,我們仍然在自研視頻剪輯工具中使用exoplayer做編輯預覽。為什麼選擇exoplayer,基於以下幾點原因(一句話,性價比高):
使用基於exoplayer播放器進行二次開發,快速高效實現視頻剪輯功能。視頻剪輯播放器用於視頻編輯過程中的實時預覽播放,支持有功能有:
針對上述視頻剪輯所需要支持的功能,逐一對照explayer的api文檔,尋找拓展實現的方法。
其中,視頻旋轉、文字貼紙、美顏濾鏡、素材轉場需要調用setVideoSurface控制視頻呈現層,自定義GLSurfaceView,使用opengl實現對視頻的旋轉、美顏濾鏡、添加貼紙。exoplayer播放輸出的surface與自定義GLSurfaceView的渲染紋理相綁定。
視頻裁剪播放使用ClippingMediaSource設置裁剪素材,按api文檔傳入起始時間和結束時間。
多個視頻拼接播放,使用ConcatenatingMediaSource可以用來無縫地合並播放多個素材,為了能對單個素材進行編輯,isAtomic設為true。
變速使用setPlaybackParameters設置速度參數
這三個功能使用exoplayer已提供的api就可以實現,相對容易。在執行編輯操作後即時更新播放器素材和參數即可。在我們的產品中,有一個撤銷操作的交互,所以需要保留一份數據拷貝,如果用戶撤銷操作則更新為原來的數據。
exoplayer本身不支持圖片格式的素材播放。注入一個自定義渲染器來實現圖片(格式為jpg、png、gif等)
其中ImageRender繼承BaseRenderer,實現了圖片的自定義渲染。render主要工作是將每幀數據解碼流渲染為屏幕圖像。對於圖片來說,我們定義ImageMediaSourceImage、SampleStreamImpl和ImageMediaPeriod,分別繼承於BaseMediaSource、SampleStream和MediaPeriod,從原素材解析並傳送每幀圖片數據。圖片不需要真正的解碼,實現SampleStream的readData方法讀取圖片uri為解碼buffer。
實現圖片播放的核心在於實現render介面:
在這個方法內,我們創建opengl環境,將bitmap繪制到屏幕上
添加的文字或貼紙支持移動、旋轉、縮放和設置時間軸。對於多個文字貼紙,我們最終包裝為一個與渲染屏幕同尺寸的bitmap,在這個bitmap的畫布上繪制一系列帶坐標大小、起止時間的小bitmap(即stickerItem.getBitmap)。
將這張貼紙畫布bitmap與原視頻幀像素混合就實現了所有文字貼紙的繪制。用opengl繪制貼紙,就是對屏幕上像素做一個水印濾鏡的運算。採用GLSL內建的mix函數做兩個紋理的混合,以下是水印濾鏡所用的片元著色器。
和文字貼紙一樣,要實現實時的美顏濾鏡效果,必須使用幀緩沖fbo。幀緩沖的每一存儲單元對應著屏幕每一個像素。而美顏濾鏡涉及較復雜演算法,由部門內的人工智慧組提供sdk接入,在繪制過程中調用sdk方法如下,就是使用fbo進行一次圖像紋理轉換。傳入參數為屏幕方向、攝像頭方向和渲染尺寸。
目前產品實現了左右移、上下移、拉近拉遠、順時針逆時針旋轉等幾種轉場效果。轉場的實現方法是:對於兩個在其中添加了轉場的素材,在上一個素材的最後1000ms繪制轉場濾鏡,轉場濾鏡即將兩張圖片的像素以一定的規律進行渲染,轉場演算法由opengl使用glsl著色器實現。轉場基類的片元著色器如下,移動轉場(左右向移動和上下移動)、縮放轉場(拉近拉遠)、旋轉轉場對getFromColor與getToColor執行的行為不同。
以移動轉場的轉場glsl著色器為例
轉場的具體實現參考了GPUImageFilter庫,和美顏濾鏡以及文字貼紙不同的是,轉場濾鏡需要在渲染前預先設置將下個素材的首幀圖。
在預覽編輯過程中,由於音樂並不需要真正合成於視頻中,因此可以使用另一個播放器單獨播放音頻,我們採用android更原始的MediaPlayer單獨播放音樂,單獨支持音樂的裁剪播放和seek。
抽幀預覽即每隔固定時間取視頻的一幀圖片構成時間軸,我們使用ffmpegMediaMetadataRetriever庫進行抽幀 ,使用方法為
該庫內部使用ffmpeg進行解碼取幀,介面易用但是其軟體解碼方式效率過低,相對較慢。因為exoplayer播放器是默認使用硬體解碼的,可以採用另一個exoplayer播放器快速播放一次素材,然後每隔一段時間獲取屏幕圖像,但此種方法開銷過大,兩個exoplayer播放器不利於管理。
最後,我們發現常用的圖片載入庫glide也能進行視頻抽幀,使用更為簡單方便,其內部採用mediaMetadataRetriever進行抽幀。
1.調整素材,拼接、裁剪、變速
https://vod.cc.163.com/file/5f896ef25655da63cc2d3237.mp4
2.轉場、文字貼紙、美顏濾鏡
https://vod.cc.163.com/file/5f896edad70f81a0e3c77dbe.mp4
⑸ 如何使用Android中的OpenGL ES媒體效果
為了握笑開始本次的教程,你必須具備:
1.一款支持Android開發的IDE,如果你沒有的話,可以在Android Developer website下載最新段昌含版本的Android studio。
2.一款運行Android4.0之上Android手機,並且GPU支持OpenGL ES2.0
3.對OpenGL的基本知識了解
設置OpenGL ES環境
創建GLSurfaceView
為了顯示OpenGL的圖形,你需要使用GLSurfaceView類,就像其他任何的View子類意義迅殲,你可以將它添加到你的Activity或Fragment之上,通過在布局xml文件中定義或者在代碼中創建實例。
在本次的教程中,我們使用GLSurfaceView作為唯一的View在我們的Activity中,因此,為了簡便,我們在代碼中創建
GLSurfaceView的實例並將其傳入setContentView中,這樣它將會填充你的整個手機屏幕。Activity中的onCreate方
法如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView view = new GLSurfaceView(this);
setContentView(view);
}123456123456
⑹ 如何使用Android中的OpenGL ES媒體效果
設置OpenGL ES環境
創建GLSurfaceView
為了顯示OpenGL的圖形,需要使用GLSurfaceView類,就像其他任何的View子類意義,可以將它添加到自己的Activity或Fragment之上,通過在布局xml文件中定義或者在代碼中創建實例。
在這里,咱們使用GLSurfaceView作為唯一的View在咋們的Activity中,因此,為了簡便,咱在代碼中創建GLSurfaceView的實例並將其傳入setContentView中,這樣它將會填充自己的整弊慧個手機屏幕。Activity中的onCreate方法如下:
<code class="hljs" java="">protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GLSurfaceView view = new GLSurfaceView(this); setContentView(view);}</code>
因為媒體效果的框架僅僅支持OpenGL ES2.0及以上的版本,所以在setEGLContextClientVersion 方法中傳入2;
<code avrasm="" class="hljs">view.setEGLContextClientVersion(2);</code>
為了確保GLSurfaceView僅僅在必要的時候耐卜備進行渲染,咱們在setRenderMode 方法中進行設置:
<code avrasm="" class="hljs">view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);</code>
創建Renderer
Renderer負責渲染GLSurfaceView中的內容。
創建類實現介面GLSurfaceView.Renderer,在這里咱打算將這個類命名為EffectsRenderer,添加昌毀構造函數並覆寫介面中的抽象方法,如下:
<code class="hljs" java="">public class EffectsRenderer implements GLSurfaceView.Renderer { public EffectsRenderer(Context context){ super(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { } @Override public void onDrawFrame(GL10 gl) { }}</code>
⑺ 求Android下openGL開發的視頻教程。
慢慢找吧,body
⑻ Android -- 音視頻基礎知識
幀,是視頻的一個基本概念,表示一張畫面,如上面的翻頁動畫書中的一頁,就是一幀。一個視頻就是由許許多多幀組成的。
幀率,即單位時間內幀的數量,單位為:幀/秒 或fps(frames per second)。一秒內包含多少張圖片,圖片越多,畫面越順滑,過渡越自然。 幀率的一般以下幾個典型值:
24/25 fps:1秒 24/25 幀,一般的電影幀率。
30/60 fps:1秒 30/60 幀,游戲的幀率,30幀可以接受,60幀會感覺更加流暢逼真。
85 fps以上人眼基本無法察覺出來了,所以更高的幀率在視頻里沒有太大意義。
這里我們只講常用到的兩種色彩空間。
RGB的顏色模式應該是我們最熟悉的一種,在現在的電子設備中應用廣泛。通過R G B三種基礎色,可以混合出所有的顏色。
這里著重講一下YUV,這種色彩空間並不是我們熟悉的。這是一種亮度與色度分離的色彩格式。
早期的電視都是黑白的,即只有亮度值,即Y。有了彩色電視以後,加入了UV兩種色度,形成現在的YUV,也叫YCbCr。
Y:亮度,就是灰度值。除了表示亮度信號外,還含有較多的綠色通道量。
U:藍色通道與亮度的差值。
V:紅色通道與亮度的差值。
音頻數據的承載方式最常用的是 脈沖編碼調制 ,即 PCM 。
在自然界中,聲音是連續不斷的,是一種模擬信號,那怎樣才能把聲音保存下來呢?那就是把聲音數字化,即轉換為數字信號。
我們知道聲音是一種波,有自己的振幅和頻率,那麼要保存聲音,就要保存聲音在各個時間點上的振幅。
而數字信號並不能連續保存所有時間點的振幅,事實上,並不需要保存連續的信號,就可以還原到人耳可接受的聲音。
根據奈奎斯特采樣定理:為了不失真地恢復模擬信號,采樣頻率應該不小於模擬信號頻譜中最高頻率的2倍。
根據以上分析,PCM的採集步驟分為以下步驟:
采樣率,即采樣的頻率。
上面提到,采樣率要大於原聲波頻率的2倍,人耳能聽到的最高頻率為20kHz,所以為了滿足人耳的聽覺要求,采樣率至少為40kHz,通常為44.1kHz,更高的通常為48kHz。
采樣位數,涉及到上面提到的振幅量化。波形振幅在模擬信號上也是連續的樣本值,而在數字信號中,信號一般是不連續的,所以模擬信號量化以後,只能取一個近似的整數值,為了記錄這些振幅值,采樣器會採用一個固定的位數來記錄這些振幅值,通常有8位、16位、32位。
位數越多,記錄的值越准確,還原度越高。
最後就是編碼了。由於數字信號是由0,1組成的,因此,需要將幅度值轉換為一系列0和1進行存儲,也就是編碼,最後得到的數據就是數字信號:一串0和1組成的數據。
整個過程如下:
聲道數,是指支持能不同發聲(注意是不同聲音)的音響的個數。 單聲道:1個聲道
雙聲道:2個聲道
立體聲道:默認為2個聲道
立體聲道(4聲道):4個聲道
碼率,是指一個數據流中每秒鍾能通過的信息量,單位bps(bit per second)
碼率 = 采樣率 * 采樣位數 * 聲道數
這里的編碼和上面音頻中提到的編碼不是同個概念,而是指壓縮編碼。
我們知道,在計算機的世界中,一切都是0和1組成的,音頻和視頻數據也不例外。由於音視頻的數據量龐大,如果按照裸流數據存儲的話,那將需要耗費非常大的存儲空間,也不利於傳送。而音視頻中,其實包含了大量0和1的重復數據,因此可以通過一定的演算法來壓縮這些0和1的數據。
特別在視頻中,由於畫面是逐漸過渡的,因此整個視頻中,包含了大量畫面/像素的重復,這正好提供了非常大的壓縮空間。
因此,編碼可以大大減小音視頻數據的大小,讓音視頻更容易存儲和傳送。
視頻編碼格式有很多,比如H26x系列和MPEG系列的編碼,這些編碼格式都是為了適應時代發展而出現的。
其中,H26x(1/2/3/4/5)系列由ITU(International Telecommunication Union)國際電傳視訊聯盟主導
MPEG(1/2/3/4)系列由MPEG(Moving Picture Experts Group, ISO旗下的組織)主導。
當然,他們也有聯合制定的編碼標准,那就是現在主流的編碼格式H264,當然還有下一代更先進的壓縮編碼標准H265。
H264是目前最主流的視頻編碼標准,所以我們後續的文章中主要以該編碼格式為基準。
H264由ITU和MPEG共同定製,屬於MPEG-4第十部分內容。
我們已經知道,視頻是由一幀一幀畫面構成的,但是在視頻的數據中,並不是真正按照一幀一幀原始數據保存下來的(如果這樣,壓縮編碼就沒有意義了)。
H264會根據一段時間內,畫面的變化情況,選取一幀畫面作為完整編碼,下一幀只記錄與上一幀完整數據的差別,是一個動態壓縮的過程。
在H264中,三種類型的幀數據分別為
I幀:幀內編碼幀。就是一個完整幀。
P幀:前向預測編碼幀。是一個非完整幀,通過參考前面的I幀或P幀生成。
B幀:雙向預測內插編碼幀。參考前後圖像幀編碼生成。B幀依賴其前最近的一個I幀或P幀及其後最近的一個P幀。
全稱:Group of picture。指一組變化不大的視頻幀。
GOP的第一幀成為關鍵幀:IDR
IDR都是I幀,可以防止一幀解碼出錯,導致後面所有幀解碼出錯的問題。當解碼器在解碼到IDR的時候,會將之前的參考幀清空,重新開始一個新的序列,這樣,即便前面一幀解碼出現重大錯誤,也不會蔓延到後面的數據中。
DTS全稱:Decoding Time Stamp。標示讀入內存中數據流在什麼時候開始送入解碼器中進行解碼。也就是解碼順序的時間戳。
PTS全稱:Presentation Time Stamp。用於標示解碼後的視頻幀什麼時候被顯示出來。
前面我們介紹了RGB和YUV兩種圖像色彩空間。H264採用的是YUV。
YUV存儲方式分為兩大類:planar 和 packed。
planar如下:
packed如下:
上面說過,由於人眼對色度敏感度低,所以可以通過省略一些色度信息,即亮度共用一些色度信息,進而節省存儲空間。因此,planar又區分了以下幾種格式:YUV444、 YUV422、YUV420。
YUV 4:4:4采樣,每一個Y對應一組UV分量。
YUV 4:2:2采樣,每兩個Y共用一組UV分量。
YUV 4:2:0采樣,每四個Y共用一組UV分量。
其中,最常用的就是YUV420。
YUV420屬於planar存儲方式,但是又分兩種類型:
YUV420P:三平面存儲。數據組成為YYYYYYYYUUVV(如I420)或YYYYYYYYVVUU(如YV12)。
YUV420SP:兩平面存儲。分為兩種類型YYYYYYYYUVUV(如NV12)或YYYYYYYYVUVU(如NV21)
原始的PCM音頻數據也是非常大的數據量,因此也需要對其進行壓縮編碼。
和視頻編碼一樣,音頻也有許多的編碼格式,如:WAV、MP3、WMA、APE、FLAC等等,音樂發燒友應該對這些格式非常熟悉,特別是後兩種無損壓縮格式。
但是,我們今天的主角不是他們,而是另外一個叫AAC的壓縮格式。
AAC是新一代的音頻有損壓縮技術,一種高壓縮比的音頻壓縮演算法。在MP4視頻中的音頻數據,大多數時候都是採用AAC壓縮格式。
AAC格式主要分為兩種:ADIF、ADTS。
ADIF:Audio Data Interchange Format。音頻數據交換格式。這種格式的特徵是可以確定的找到這個音頻數據的開始,不需進行在音頻數據流中間開始的解碼,即它的解碼必須在明確定義的開始處進行。這種格式常用在磁碟文件中。
ADTS:Audio Data Transport Stream。音頻數據傳輸流。這種格式的特徵是它是一個有同步字的比特流,解碼可以在這個流中任何位置開始。它的特徵類似於mp3數據流格式。
ADIF數據格式:
ADTS 一幀 數據格式(中間部分,左右省略號為前後數據幀):
AAC內部結構也不再贅述,可以參考AAC 文件解析及解碼流程
細心的讀者可能已經發現,前面我們介紹的各種音視頻的編碼格式,沒有一種是我們平時使用到的視頻格式,比如:mp4、rmvb、avi、mkv、mov...
沒錯,這些我們熟悉的視頻格式,其實是包裹了音視頻編碼數據的容器,用來把以特定編碼標准編碼的視頻流和音頻流混在一起,成為一個文件。
例如:mp4支持H264、H265等視頻編碼和AAC、MP3等音頻編碼。
我們在一些播放器中會看到,有硬解碼和軟解碼兩種播放形式給我們選擇,但是我們大部分時候並不能感覺出他們的區別,對於普通用戶來說,只要能播放就行了。
那麼他們內部究竟有什麼區別呢?
在手機或者PC上,都會有CPU、GPU或者解碼器等硬體。通常,我們的計算都是在CPU上進行的,也就是我們軟體的執行晶元,而GPU主要負責畫面的顯示(是一種硬體加速)。
所謂軟解碼,就是指利用CPU的計算能力來解碼,通常如果CPU的能力不是很強的時候,一則解碼速度會比較慢,二則手機可能出現發熱現象。但是,由於使用統一的演算法,兼容性會很好。
硬解碼,指的是利用手機上專門的解碼晶元來加速解碼。通常硬解碼的解碼速度會快很多,但是由於硬解碼由各個廠家實現,質量參差不齊,非常容易出現兼容性問題。
MediaCodec 是Android 4.1(api 16)版本引入的編解碼介面,是所有想在Android上開發音視頻的開發人員繞不開的坑。
由於Android碎片化嚴重,雖然經過多年的發展,Android硬解已經有了很大改觀,但實際上各個廠家實現不同, 還是會有一些意想不到的坑。
相對於FFmpeg,Android原生硬解碼還是相對容易入門一些,所以接下來,我將會從MediaCodec入手,講解如何實現視頻的編解碼,以及引入OpenGL實現對視頻的編輯,最後才引入FFmpeg來實現軟解,算是一個比較常規的音視頻開發入門流程吧。
⑼ Android音視頻之使用OpenGL ES繪制圖片
關於 OpenGL ES 的介紹,請先看上篇: Android 音視頻之使用 OpenGL ES 繪制三角形 。
使用 OpenGL ES 繪制簡單的幾何形狀還不夠,OpenGL 更多地是用來顯示而紋理圖像,比如本地圖片、相機畫面。簡單說,紋理(texture)就是一個圖像或照片,它們可以被載入進 OpenGL 中。
OpenGL 中的紋理可以擾判用來表示圖像、照片等,每個二維的紋理都由許多小緩缺改的紋理元素組成,它們是小塊的數據,類似片段和像素。要使用紋理,最常用的方式是直接從一個圖像文件載入數據。
紋理不會被直接繪制,它們要被綁定到紋理單元,然後把這些紋理單元傳遞給著色器。紋理映射的基本思想就是:首先為圖元中的每個頂點指定恰當的紋理坐標,然後通過紋理坐標在紋理圖中可以確定選中的紋理區域,最後將選中紋理區域中的內容根據紋理坐標映射到指定的圖元上。
紋理的坐標系和頂點著色器的坐標系是不一樣的。紋理坐標用浮點數來表示,范圍 [0, 1],左上角坐標為 (0.0, 0.0),右上角坐標為 (1.0, 0.0)。注意:要將紋理坐標對應到正確的頂點上,才能使紋理正確扮銀地顯示。
定義頂點和紋理坐標,兩者的順序必須一一對應。
定義著色器。
載入圖片到 OpenGL 中。
計算變換矩陣,採用 CenterInside 或者 CenterCrop 的方式顯示。
顯示圖片。
源碼在 GitHub 上。
參考資料:
⑽ 如何使用Android中的OpenGL ES媒體效果
准備
一款支持Android開發的IDE;
一款運行Android4.0之上Android手機,並且GPU支持OpenGL
ES2.0
;
對OpenGL的基本知識了解;
步驟
設置OpenGL
ES環境
為了顯示OpenGL的圖形,需要使用GLSurfaceView類,就像其他任何的View子類意義,可以將它添加到Activity或Fragment之上,通過在布局xml文件中定義或者在代碼中創建實例,Activity中的onCreate方法如下:
因為媒體效果的框架僅僅支持OpenGL
ES2.0及以上的版本,所以在setEGLContextClientVersion
方法中傳入2;
了確保GLSurfaceView僅僅在必要的時候進行渲染,在setRenderMode
方法中進行設置:
創建Renderer
創建類實現介面GLSurfaceView.Renderer,將這個類命名為EffectsRenderer,添加構造函數並覆寫介面中的抽象方法,如下:
回到Activity中調用setRenderer方法,讓GLSurfaceView使用我們創建的Renderer:
編寫Manifest文件
在AndroidManifest.xml文件中添加如下語句:
創建一個OpenGL平面
創建一個2D平面,並且具有4個頂點。
默認的OpenGL系統的坐標系中的原點是在中心,因此4個角的坐標可以表示為:
創建一個float數組來代表這些頂點,在square上定位紋理,需要確定紋理的頂點坐標,創建另一個數組來表示紋理頂點的坐標:
這些坐標數組應該被轉變為緩沖字元(byte
buffer)在OpenGL可以使用之前,所以需要定義: