美文网首页Android OpenGLAndroid知识Android技术知识
NDK开发OpenGL ES 3.0(一)——OpenGL-ES

NDK开发OpenGL ES 3.0(一)——OpenGL-ES

作者: 798fe2ac8685 | 来源:发表于2016-10-25 12:11 被阅读1877次

    标签(空格分隔): 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图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 <jni.h>
    #include <string>
    
    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

        本文链接:https://www.haomeiwen.com/subject/zueruttx.html