Android OpenGL ES-Frame Buffer Object

來源:互聯網
上載者:User

Frame Buffer 對象的概念可以參見前面文章Android OpenGL ES 開發教程(23):FrameBuffer。

簡單的和2D映像類比,Frame Buffer 如果 對應到二維圖形環境中,就是一個2D的記憶體數組空間,預設情況為螢幕的顯存,也可以建立Offscreen 記憶體空間,此時Frame Buffer 可以是一個二維數組,數組每個元素代表一個像素顏色。

對於三維圖形來說,除了需要代表顏色的二維數組(Color Buffer),還需要深度二維數組(Depth Buffer) 或遮罩數組(Stencil Buffer),因此在OpenGL 中的Frame Buffer為上述Color Buffer,Depth Buffer,Stencil Buffer 的集合。如果手機具有GPU,其預設的Frame Buffer也是3D螢幕顯示地區。

通過Opengl ES擴充支援,應用程式也可以建立記憶體中的Frame Buffer對象(不用於螢幕顯示)。通過這種應用程式建立的FrameBuffer對象,OpenGL應用可以將映像顯示輸出重新定向到這個非螢幕顯示用FrameBuffer對象中,類似於二維圖形繪製中常用的Offscreen 技術。

和預設的螢幕顯示FrameBuffer一樣,由應用程式建立的FrameBuffer對象也是由Color Buffer, Depth Buffer和Stencil Buffer(可選)的集合組成。這些Buffer在FrameBuffer對象中可以稱為FrameBuffer-attachable 映像,FrameBuffer定義了一些存取點(Attachment Point)可以用於串連(Attach)這些Buffer數組。

OpenGL ES定義了兩種FrameBuffer-attachable 映像,Texture 和 renderbuffer ,簡單的可以將Texture 理解為Color buffer 或是2D映像,render buffer 對應於depth buffer。

表示了Texture , Renderbuffer 對象和 Frame Buffer 對象之間的關係:

但把Texture 和 Render Buffer 連結到FrameBuffer這些存取點(ATTACHMENT)之後,之後所有OpenGL繪圖指令的輸出結果就寫入到這些記憶體Buffer中,而非預設螢幕顯示。

不同的Android裝置支援的OpenGL ES擴充可能有所不同,因此如果需要使用應用建立FrameBuffer對象前需要檢查手機是否支援Framebuffer擴充,本例使用

private boolean checkIfContextSupportsExtension(GL10 gl, String extension) { String extensions = " " + gl.glGetString(GL10.GL_EXTENSIONS) + " "; // The extensions string is padded with spaces between extensions, but not // necessarily at the beginning or end.
For simplicity, add spaces at the // beginning and end of the extensions string and the extension string. // This means we can avoid special-case checks for the first or last // extension, as well as avoid special-case checks when an extension name // is the
same as the first part of another extension name. return extensions.indexOf(" " + extension + " ") >= 0; }

使用FrameBuffer的基本步驟如下:

1. 使用glGenFramebuffersOES建立FrameBuffer對象

int[] framebuffers = new int[1]; gl11ep.glGenFramebuffersOES(1, framebuffers, 0); framebuffer = framebuffers[0];

2. 建立好FrameBuffer後,必須綁定FrameBuffer到OpenGL中,

gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, framebuffer);

第一個參數類型必須為GL_FRAMEBUFFER_OES,第二個參數為FrameBuffer的ID。如果Id為0,表示綁定到預設的螢幕FrameBuffer。

綁定之後,後續的OpenGL繪製結果就從定向到FrameBuffer中,而不是顯示到螢幕上。

3, 使用glGenRenderbuffersOES建立RenderBuffer

int depthbuffer; int[] renderbuffers = new int[1]; gl11ep.glGenRenderbuffersOES(1, renderbuffers, 0); depthbuffer = renderbuffers[0];

4. 和FrameBuffer類似,建立RenderBuffer對象,也需要綁定到OpengL庫中

gl11ep.glBindRenderbufferOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, depthbuffer);

5. 給renderBuffer 分配記憶體。

建立的renderBuffer 本身不含有記憶體空間,因此必須給它分配記憶體空間,這是通過glRenderbufferStorageOES來實現的。

gl11ep.glRenderbufferStorageOES(GL11ExtensionPack.GL_RENDERBUFFER_OES, GL11ExtensionPack.GL_DEPTH_COMPONENT16, width, height);

第二個參數為建立的RenderBuffer的內部格式類型。

6. 建立Texture對象,可以參見Android ApiDemos樣本解析(200):Graphics->OpenGL ES->Textured Triangle。

7. 在建立好FrameBuffer,Texture和renderBuffer對象之後,需要把Texture,RenderBuffer對象和FrameBuffer中對應的Attachment Point連結起來。

連結Texture對象

gl11ep.glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, targetTextureId, 0);

連結renderBuffer 對象

l11ep.glFramebufferRenderbufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_DEPTH_ATTACHMENT_OES, GL11ExtensionPack.GL_RENDERBUFFER_OES, depthbuffer);

來看一下本例的onDrawFrame方法

private static final boolean DEBUG_RENDER_OFFSCREEN_ONSCREEN = false; public void onDrawFrame(GL10 gl) { checkGLError(gl); if (mContextSupportsFrameBufferObject) { GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl; if (DEBUG_RENDER_OFFSCREEN_ONSCREEN) { drawOffscreenImage(gl,
mSurfaceWidth, mSurfaceHeight); } else { gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFramebuffer); drawOffscreenImage(gl, mFramebufferWidth, mFramebufferHeight); gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0); drawOnscreen(gl,
mSurfaceWidth, mSurfaceHeight); } } else { // Current context doesn't support frame buffer objects. // Indicate this by drawing a red background. gl.glClearColor(1,0,0,0); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); } }

本例在建立的FrameBuffer中繪製立方體,其繪圖指令和例子Android ApiDemos樣本解析(203):Graphics->OpenGL ES->GLSurfaceView一樣。但其顯示結果存放在mFramebuffer中(可以通過將DEBUG_RENDER_OFFSCREEN_ONSCREEN設為True看到FrameBuffer的內容)。然後將mFramebuffer顯示的記憶體作為Triangle的材質繪製三角形。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.