@cxm-2016
2017-04-05T06:26:21.000000Z
字数 5594
阅读 8365
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 (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。
OpenGL ES 3.0主要新功能有:
Android Studio在其2.0及以上版本继承了流行的C++编译器CMake,于是我们很方便的就能够搭建出NDK开发环境。
在Android Studio 2.0 及以上版本创建NDK的工程只需要勾选Include C++ Support即可。
剩下的一路next就行。
在工程创建完成之后,我们将目录视图切换到Project,我们发现app目录下多了一个CMakeList.txt文件,打开文件我们会看见如下内容(注释已精简)。
# 这里指定了CMake的最低版本为3.4.1cmake_minimum_required(VERSION 3.4.1)# 这里用来添加一个库add_library( # 这里设置so库的名称为native-libnative-lib# 这里设置该库为共享SHARED# 这里是源文件的路径,可以有多个,最终这个源文件将被编译并打包进native-lib库。src/main/cpp/native-lib.cpp )# 这里用来查找一个库,并设置到路径变量中去find_library( # 设置路径变量log-lib# 你希望CMake编译器加载的NDK函数库log )# 将一个库关联到目标函数库中target_link_libraries( # 目标函数库native-lib# 想要在目标函数库中使用的函数库,其中${路径变量}${log-lib} )
更详细的CMakeList.txt可以参照这里CMakeList.txt说明。
工程创建完成之后,我们在src/main/cpp文件夹下可以看到一个native-lib.cpp源文件(我们也可以改名成其他),由于其被指定到了add_library操作中,所以其最终会被编译并链接称为native-lib.so文件。
我们来看自动生成的MainActivity:
public class MainActivity extends AppCompatActivity {// 这里加载的库名必须在CMakeList.txt中使用add_library指定static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = (TextView) findViewById(R.id.sample_text);tv.setText(stringFromJNI());}//该本地方法需要在某一个源文件中被实现,并且System.loadLibrary加载的库必须编译了了此源文件public native String stringFromJNI();}
我们可以直接运行这个程序,并且在屏幕上打印Hello from C++这句话。
如果你对上面自动生成的代码还是不好理解的话,我们可以手动创建一个CPP文件,并配置。
这里演示一个方法传入字符串,并且在另一个方法接收的示例:
public class MainActivity extends AppCompatActivity {static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = (TextView) findViewById(R.id.sample_text);setString("在这里传入新的字符串");tv.setText(getString());}public native String getString();public native void setString(String str);}
加入我们写到这一步,AS就会报错说找不到方法,接下来我们需要在cpp文件中实现这个本地方法
mySource.cpp
//mySource.cpp#include <jni.h>#include <string>static char * static_str=NULL;//使用全局变量缓存传入的字符串extern "C"voidJava_com_github_cccxm_gles_MainActivity_setString(JNIEnv *env, jobject instance, jstring str_) {const char *str = env->GetStringUTFChars(str_, 0);//获取传入的字符串jsize len = env->GetStringLength(str_);//计算字符串的长度if(static_str!=NULL)free(static_str);//释放之前保存的字符串static_str = (char*)malloc(sizeof(char)*len+1);//重新从内存中分配内存给字符串for(int i=0;static_str[i]=str[i];i++);//复制传入的字符串env->ReleaseStringUTFChars(str_, str);//释放原始的字符串}extern "C"jstringJava_com_github_cccxm_gles_MainActivity_getString(JNIEnv *env,jobject /* this */) {return env->NewStringUTF(static_str);//回传缓存的字符串}
add_library( native-libSHAREDsrc/main/cpp/native-lib.cppsrc/main/cpp/mySource.cpp)
然后我们运行就可以看到结果了。
本系列教程除了需要定义native方法的地方使用Java语言,其他地方全部使用Kotlin语言。Android开发不会Kotlin?你out啦!这里我们配置Kotlin环境,对于与Java语法不同的地方会有解释说明。目前kotlin语言的版本是1.0.4
首先我们需要修改整个应用的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文件示例:
buildscript {ext.kotlin_version = '1.0.4'repositories {jcenter()}dependencies {classpath 'com.android.tools.build:gradle:2.2.2'classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"// NOTE: Do not place your application dependencies here; they belong// in the individual module build.gradle files}}
接下来修改app的build.gradle文件,我们在文件头部添加启用插件的语句
apply plugin: 'kotlin-android'apply plugin: 'kotlin-android-extensions'
接下来在dependencies项中添加类库compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {exclude group: 'com.android.support', module: 'support-annotations'})compile 'com.android.support:appcompat-v7:24.2.1'testCompile 'junit:junit:4.12'compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"}
注意:这里使用$kotlin_version来引用全局变量,其优点显而易见,每次版本更新的时候只需要修改一处即可。但是在目前2.2.0版本的AS中这样写可能会导致后续一些操作出错。这里建议手写版本号
compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.4"
删除原来的MainActivity和资源文件activity_main.xml,然后在包目录上单击右键/New/Kotlin Activity,这里就跟平常创建一个Activity是一样的过程。这里Activity Name输入MainActivity,然后勾选Launcher Activity
最后产生的Activity是这个样子的
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)}}
Kotlin小贴士:
- kotlin中不需要分号表示语句结束