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 编程指南 第二版(姚军 译).北京:机械工业出版社


[toc]

一、OpenGL ES 3.0 介绍


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

OpenGL ES 3.0主要新功能有:

  • 1、渲染管线多重增强,实现先进视觉效果的加速,包括遮挡查询(Occlusion Query)、变缓反馈(Transform Feedback)、实例渲染(Instanced Rendering)、四个或更多渲染目标支持。
  • 2、高质量ETC2/EAC纹理压缩格式成为一项标准功能,不同平台上不再需要需要不同的纹理集。
  • 3、新版GLSL ES 3.0着色语言,全面支持整数和32位浮点操作。
  • 4、纹理功能大幅增强,支持浮点纹理、3D纹理、深度纹理、顶点纹理、NPOT纹理、R/RG单双通道纹理、不可变纹理、2D阵列纹理、无二次幂限制纹理、阴影对比、调配(swizzle)、LOD与mip level clamps、无缝立方体贴图、采样对象、纹理MSAA抗锯齿渲染器。
  • 5、一系列广泛的精确尺寸纹理和渲染缓冲格式,便携移动应用更简单。

二、使用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文件,打开文件我们会看见如下内容(注释已精简)。

# 这里指定了CMake的最低版本为3.4.1
cmake_minimum_required(VERSION 3.4.1)

# 这里用来添加一个库
add_library( # 这里设置so库的名称为native-lib
             native-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文件。

2.3 MainActivity说明

我们来看自动生成的MainActivity:

public class MainActivity extends AppCompatActivity {

    // 这里加载的库名必须在CMakeList.txt中使用add_library指定
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected 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++这句话。

2.4 修改程序

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

2.4.1 修改MainActivity

public class MainActivity extends AppCompatActivity {
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected 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文件中实现这个本地方法

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

mySource.cpp

//mySource.cpp
#include 
#include 

static char * static_str=NULL;//使用全局变量缓存传入的字符串

extern "C"
void
Java_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"
jstring
Java_com_github_cccxm_gles_MainActivity_getString(JNIEnv *env,jobject /* this */) {
    return env->NewStringUTF(static_str);//回传缓存的字符串
}

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

add_library( native-lib

             SHARED

             src/main/cpp/native-lib.cpp
             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文件示例:

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"

3.2 创建一个KotlinActivity

删除原来的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中不需要分号表示语句结束

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

你可能感兴趣的:(NDK开发OpenGL ES 3.0(一)——OpenGL-ES 3.0介绍以及NDK环境搭建)