天天看點

Modern OpenGL ES: ndk程式設計——畫一個三角形之NativeWindow

OpenGLES 3.0 需要連結到 下面庫 :      1  OpenGLES3.0 庫 libGLESv2.lib 和 EGL 庫 libEGL.lib     我們會在 android-ndk-r10c下的 platforms/android-21/arch-arm/usr/lib下找到這兩個  libEGL.so 和 libGLEv3.so

   2  OpenGLES3.0 應用程式也需要 包含 相關的 ES3.0 和 EGL 頭檔案        #include <EGL/egl.h>        #include <GLES3/gl3.h>      也可以包含 gl2ext.h 頭檔案,已包含一些opengl es的擴充性能

OpenGL ES3.0 寫一個 三角形的demo:     内容:       1 用EGL建立on-screen 渲染surface       2 加載vertex/fragment shaders       3 建立shader 工程 ,編譯shaders,并連結到shader 工程       4 設定viewport       5 重置 color buffer       6 渲染簡單的形狀       7 使顔色buffer的 内容在EGL window surface上可見

Android.mk:    Android 通過mk 檔案來 導入外部c/c++庫,并輸出so共享庫,以供Android platform調用。是以, Android ndk程式設計需要從 Android.mk入手

  一般, 在mk檔案中 以LOCAL開頭的名字都是  ndk編譯系統的 宏名,在編譯時,會識别這些名字:

參考:  http://blog.csdn.net/smfwuxiao/article/details/8530742

1  定義 目前路徑 即 LOCAL_PATH    LOCAL_PATH := $(call my-dir)   這個就是 目前Android工程 的Android.mk 所在的根目錄 2  定義編譯導出的共享庫的名字   LOCAL_MODULE := name

3  定義c/c++宏     LOCAL_CFLAGS += -DANDROID      形如LOCAL_CFLAGS : = -D*想入這種形式 表明 要在全局(即所有的c/c++檔案裡)定義 *的 宏

4  列舉出對應于同一子產品的,要編譯的源檔案(注意不是頭檔案) LOCAL_SRC_FILES := *.c /                                  **.c    ...

5  包含源檔案要用到的 頭檔案的路徑,它是Android 工程目錄jni根目錄的相對路徑 LOCAL_C_INCLUDES : = $(your-path)

6 告訴連結器在加載共享庫的時候必須連結 系統.so共享庫 LOCAL_LDLIBS : = **

7  指定應該連結到目前子產品的靜态庫(可指定多個)。 目前子產品是動态庫時,才有意義 LOCAL_STATIC_LIBRARIES : = **

8  用于指向 一個特殊的Makefile,這個Makefile負責不同的功能   8.1 include $(CLEAR_VARS)表示 清除 LOCAL_XXX的變量,除了 LOCAL_PATH   8.2 include $(BUILD_SHARED_LIBRARY) 表示将LOCAL_XXX等變量中 定義的資訊收集起來, 确定要編譯的檔案,如何編譯。 如果要編譯靜态庫: BUILD_STATIC_LIBRARY

9  引入外部庫  $(call import-module, name); name是ndk/sources根目錄下的某個路徑,一般我們把要導入的庫,都會放在這個路徑下

編寫工程:       目的:     1 鍛煉Android NDK 程式設計能力        純C/C++編寫,由于不需要編寫java,是以我們必須找到activity底層啟動的入口, 這也是在鍛煉Android NDK 程式設計能力    2 學習能移植不同平台的opengl es       在學習OpenGL ES3.0 的知識點的同時,寫一些demo,在寫demo的同時,把一些公用的東西整理出一個工具集,供以後開發使用       實作步驟:     1  在Manifest.xml          參考:  http://www.cnblogs.com/pilang/archive/2011/04/20/2022932.html         

<?xml version="1.0" encoding="utf-8"?>
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.openglesbook.HelloTriangle">
         <application
            android:label="HelloTriangle"
            android:hasCode="false">
            <activity android:name="android.app.NativeActivity"
                  android:label="HelloTriangle"
                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                  android:launchMode="singleTask"
                  android:configChanges="orientation|keyboardHidden">
                 <meta-data android:name="android.app.lib_name"
                  android:value="Hello_Triangle" />
                  <intent-filter>
                       <action android:name="android.intent.action.MAIN" />
                       <category android:name="android.intent.category.LAUNCHER" />
                 </intent-filter>
            </activity>
         </application>
         <uses-feature android:glEsVersion="0x00030000"/>
         <uses-sdk android:minSdkVersion="18"/>
     </manifest>
           

             相關說明:          詳細說明請參看 參考          1.1 因為我們嘗試隻用 c/c++來開發應用程式, 是以将android:hasCode 設定為false,意思是不包含任何的JAVA的代碼(除了内置元件類,比如Activity類)

         1.2 <activity android:name="android.app.NativeActivity"...               NativeActivity是 實作Android 純c/c++程式設計的關鍵,它是我們app啟動的界面, 它裡面有一個 靜态字元串 META_DATA_LIB_NAME,       它定義了 元件需要從meta-data 中加載的共享so庫。 正如             <meta-data android:name="android.app.lib_name" android:value="Hello_Triangle"/>中指的, Hello_Triangle就是NativeActivity要加載的so檔案。 

        1.3 我們下面就編寫輸出Hello_Triangle.so的 c/c++檔案

   2   入口函數及執行順序       關于 純C++的 Android NDK開發 可以參考:  http://blog.csdn.net/gengshenghong/article/details/8656862      2.1 native_app_glue        native_app_glue 是Android 運作的一個子產品, 它位于 ndk根目錄下 Sources/android/目錄下,  

        mk檔案 定義了 将 native_app_glue作為靜态庫的語句:

         LOCAL_PATH:= $(call my-dir)          include $(CLEAR_VARS)

         LOCAL_MODULE:= android_native_app_glue

         LOCAL_SRC_FILES:= android_native_app_glue.c

         LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)

         LOCAL_EXPORT_LDLIBS := -llog

         include $(BUILD_STATIC_LIBRARY)

        LOCAL_EXPORT_C_INCLUDES 是将 目前路徑下的頭檔案,導到 我們工程的 mk根目錄下, 它與LOCAL_C_INCLUDES功能是一樣的都會 将 頭檔案 弄到 根目錄下

         android_native_glue.c 有一個程式入口函數:             

static void* android_app_entry(void *param)
         {
               struct android_app *android_app = (struct android_app*)param;
               ......
               android_main(android_app);
              .....
         }
           

        可以看到android_app_entry 調用了 android_main,android_main 接收 android_app結構體參數

      2.2  struct android_app           它定義在 android_native_app_glue.h 頭檔案裡            是以,我們如果需要使用android_app的資訊,必須包含此頭檔案

           我們需要關心的資訊有:            struct android_app{                 void *userData;  // 指向它内部狀态的對象                    ......                 ANativeActivity *activity;  // app運作的activity                 ....                 ANativeWindow *window; // app可以畫上去的視窗                              }

      2.3 android_main 函數          它是我們自己建立的一個 main函數,在這個函數裡面,我們可以完成 建立視窗,并運作opengl程式的功能。它就相當于Java層的GLSurfaceView。

                 3 純C/C++ 建立Android 視窗   參考:  http://jingyan.baidu.com/article/a501d80cf394dfec630f5e85.html?qq-pf-to=pcqq.c2c      這篇文章比較給力,我就不羅嗦了。

建立完視窗後,後面會在這個視窗上 用OpenGLl來繪圖。                                            

繼續閱讀