[关闭]
@cxm-2016 2017-04-05T14:26:21.000000Z 字数 5594 阅读 7781

NDK开发OpenGL ES 3.0(一)——OpenGL-ES 3.0介绍以及NDK环境搭建

OpenGL-ES

版本:1
作者:陈小默
版权声明:禁止商用,禁止转载

该文章仅被发布于作业部落(原)简书


参考书目:
[1]Donald Hearn,M.Pauline Barker.计算机图形学 第四版(蔡士杰 译).北京:电子工业出版社
[2]Dave Shreiner,Graham Sellers.OpenGL编程指南 第八版(王锐 译).北京:机械工业出版社
[3]Dan Ginsburg,Budirjanto Purnomo.OpenGL ES 3.0 编程指南 第二版(姚军 译).北京:机械工业出版社


一、OpenGL ES 3.0 介绍


OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。

OpenGL ES 3.0主要新功能有:

二、使用Android Studio 2.0及以上版本搭建NDK开发环境


Android Studio在其2.0及以上版本继承了流行的C++编译器CMake,于是我们很方便的就能够搭建出NDK开发环境。

2.1 创建NDK工程

在Android Studio 2.0 及以上版本创建NDK的工程只需要勾选Include C++ Support即可。
图2.1-1
剩下的一路next就行。

2.2 CMakeList.txt文件说明

在工程创建完成之后,我们将目录视图切换到Project,我们发现app目录下多了一个CMakeList.txt文件,打开文件我们会看见如下内容(注释已精简)。

  1. # 这里指定了CMake的最低版本为3.4.1
  2. cmake_minimum_required(VERSION 3.4.1)
  3. # 这里用来添加一个库
  4. add_library( # 这里设置so库的名称为native-lib
  5. native-lib
  6. # 这里设置该库为共享
  7. SHARED
  8. # 这里是源文件的路径,可以有多个,最终这个源文件将被编译并打包进native-lib库。
  9. src/main/cpp/native-lib.cpp )
  10. # 这里用来查找一个库,并设置到路径变量中去
  11. find_library( # 设置路径变量
  12. log-lib
  13. # 你希望CMake编译器加载的NDK函数库
  14. log )
  15. # 将一个库关联到目标函数库中
  16. target_link_libraries( # 目标函数库
  17. native-lib
  18. # 想要在目标函数库中使用的函数库,其中${路径变量}
  19. ${log-lib} )

更详细的CMakeList.txt可以参照这里CMakeList.txt说明

工程创建完成之后,我们在src/main/cpp文件夹下可以看到一个native-lib.cpp源文件(我们也可以改名成其他),由于其被指定到了add_library操作中,所以其最终会被编译并链接称为native-lib.so文件。

2.3 MainActivity说明

我们来看自动生成的MainActivity:

  1. public class MainActivity extends AppCompatActivity {
  2. // 这里加载的库名必须在CMakeList.txt中使用add_library指定
  3. static {
  4. System.loadLibrary("native-lib");
  5. }
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_main);
  10. TextView tv = (TextView) findViewById(R.id.sample_text);
  11. tv.setText(stringFromJNI());
  12. }
  13. //该本地方法需要在某一个源文件中被实现,并且System.loadLibrary加载的库必须编译了了此源文件
  14. public native String stringFromJNI();
  15. }

我们可以直接运行这个程序,并且在屏幕上打印Hello from C++这句话。

2.4 修改程序

如果你对上面自动生成的代码还是不好理解的话,我们可以手动创建一个CPP文件,并配置。
这里演示一个方法传入字符串,并且在另一个方法接收的示例:

2.4.1 修改MainActivity

  1. public class MainActivity extends AppCompatActivity {
  2. static {
  3. System.loadLibrary("native-lib");
  4. }
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. TextView tv = (TextView) findViewById(R.id.sample_text);
  10. setString("在这里传入新的字符串");
  11. tv.setText(getString());
  12. }
  13. public native String getString();
  14. public native void setString(String str);
  15. }

加入我们写到这一步,AS就会报错说找不到方法,接下来我们需要在cpp文件中实现这个本地方法

2.4.2 在cpp目录下创建一个源文件

mySource.cpp

  1. //mySource.cpp
  2. #include <jni.h>
  3. #include <string>
  4. static char * static_str=NULL;//使用全局变量缓存传入的字符串
  5. extern "C"
  6. void
  7. Java_com_github_cccxm_gles_MainActivity_setString(JNIEnv *env, jobject instance, jstring str_) {
  8. const char *str = env->GetStringUTFChars(str_, 0);//获取传入的字符串
  9. jsize len = env->GetStringLength(str_);//计算字符串的长度
  10. if(static_str!=NULL)free(static_str);//释放之前保存的字符串
  11. static_str = (char*)malloc(sizeof(char)*len+1);//重新从内存中分配内存给字符串
  12. for(int i=0;static_str[i]=str[i];i++);//复制传入的字符串
  13. env->ReleaseStringUTFChars(str_, str);//释放原始的字符串
  14. }
  15. extern "C"
  16. jstring
  17. Java_com_github_cccxm_gles_MainActivity_getString(JNIEnv *env,jobject /* this */) {
  18. return env->NewStringUTF(static_str);//回传缓存的字符串
  19. }

2.4.3 修改CMakeList.txt文件引入新增的源文件

  1. add_library( native-lib
  2. SHARED
  3. src/main/cpp/native-lib.cpp
  4. src/main/cpp/mySource.cpp)

然后我们运行就可以看到结果了。

三、使用Android Studio搭建Kotlin开发环境


本系列教程除了需要定义native方法的地方使用Java语言,其他地方全部使用Kotlin语言。Android开发不会Kotlin?你out啦!这里我们配置Kotlin环境,对于与Java语法不同的地方会有解释说明。目前kotlin语言的版本是1.0.4

3.1 修改配置文件

首先我们需要修改整个应用的build.gradle文件,并在其中声明一个全局变量ext.kotlin_version = '1.0.4',然后增加一个kotlin的插件classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version",这里我们会使用到kotlin语言的扩展功能,所以还需要添加其扩展库classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
以下是应用的build.gradle文件示例:

  1. buildscript {
  2. ext.kotlin_version = '1.0.4'
  3. repositories {
  4. jcenter()
  5. }
  6. dependencies {
  7. classpath 'com.android.tools.build:gradle:2.2.2'
  8. classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  9. classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
  10. // NOTE: Do not place your application dependencies here; they belong
  11. // in the individual module build.gradle files
  12. }
  13. }

接下来修改app的build.gradle文件,我们在文件头部添加启用插件的语句

  1. apply plugin: 'kotlin-android'
  2. apply plugin: 'kotlin-android-extensions'

接下来在dependencies项中添加类库compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

  1. dependencies {
  2. compile fileTree(dir: 'libs', include: ['*.jar'])
  3. androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
  4. exclude group: 'com.android.support', module: 'support-annotations'
  5. })
  6. compile 'com.android.support:appcompat-v7:24.2.1'
  7. testCompile 'junit:junit:4.12'
  8. compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
  9. }

注意:这里使用$kotlin_version来引用全局变量,其优点显而易见,每次版本更新的时候只需要修改一处即可。但是在目前2.2.0版本的AS中这样写可能会导致后续一些操作出错。这里建议手写版本号compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.4"

3.2 创建一个KotlinActivity

删除原来的MainActivity和资源文件activity_main.xml,然后在包目录上单击右键/New/Kotlin Activity,这里就跟平常创建一个Activity是一样的过程。这里Activity Name输入MainActivity,然后勾选Launcher Activity
最后产生的Activity是这个样子的

  1. class MainActivity : AppCompatActivity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. setContentView(R.layout.activity_main)
  5. }
  6. }

Kotlin小贴士:

  • kotlin中不需要分号表示语句结束

下一篇:NDK开发OpenGL ES 3.0(二)——初见GLES,第一个三角形

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注