├── .gitignore ├── .idea ├── codeStyleSettings.xml ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── Application ├── .gitignore ├── CMakeLists.txt ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── basemap.tga │ ├── fragment_linear_fog.glsl │ ├── fragment_mipmap.glsl │ ├── fragment_multitexture.glsl │ ├── fragment_texture.glsl │ ├── fragment_texture_cube.glsl │ ├── glslIntroduce.glsl │ ├── lightmap.tga │ ├── smoke.tga │ ├── triangleFragment.glsl │ ├── triangleVertex.glsl │ ├── vertex_linear_fog.glsl │ ├── vertex_mipmap.glsl │ ├── vertex_multitexture.glsl │ ├── vertex_texture.glsl │ └── vertex_texture_cube.glsl │ ├── cpp │ ├── gles │ │ ├── EGLLinearFog.cpp │ │ ├── EGLMipMap2D.cpp │ │ ├── EGLMultiTexture.cpp │ │ ├── EGLParticleSystem.cpp │ │ ├── EGLTexture2D.cpp │ │ ├── EGLTextureCube.cpp │ │ ├── EGLTextureWrap.cpp │ │ ├── EGLTriangle.cpp │ │ ├── VertexBufferSample.cpp │ │ └── VertexSample.cpp │ ├── glue │ │ ├── android_native_app_glue.cpp │ │ └── android_native_app_glue.h │ └── util │ │ ├── AndroidUtil.cpp │ │ ├── EGLUtil.cpp │ │ └── EGLUtil.h │ └── res │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 226 | 228 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Application/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Application/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | native-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | 21 | #glue source 谷歌开发的NativeActivity的胶水层,复制到这里是为了方便Android Studio使用 22 | src/main/cpp/glue/android_native_app_glue.cpp 23 | src/main/cpp/glue/android_native_app_glue.h 24 | 25 | # util source 26 | src/main/cpp/util/EGLUtil.h 27 | src/main/cpp/util/EGLUtil.cpp 28 | src/main/cpp/util/AndroidUtil.cpp 29 | 30 | # OpenGLES source 31 | # src/main/cpp/gles/EGLTriangle.cpp 32 | # src/main/cpp/gles/EGLMipMap2D.cpp 33 | # src/main/cpp/gles/EGLTextureWrap.cpp 34 | # src/main/cpp/gles/EGLTexture2D.cpp 35 | # src/main/cpp/gles/EGLTextureCube.cpp 36 | # src/main/cpp/gles/EGLMultiTexture.cpp 37 | # src/main/cpp/gles/EGLLinearFog.cpp 38 | src/main/cpp/gles/EGLParticleSystem.cpp 39 | ) 40 | 41 | # Searches for a specified prebuilt library and stores the path as a 42 | # variable. Because CMake includes system libraries in the search path by 43 | # default, you only need to specify the name of the public NDK library 44 | # you want to add. CMake verifies that the library exists before 45 | # completing its build. 46 | 47 | find_library( # Sets the name of the path variable. 48 | log-lib 49 | 50 | # Specifies the name of the NDK library that 51 | # you want CMake to locate. 52 | log ) 53 | 54 | # Specifies libraries CMake should link to your target library. You 55 | # can link multiple libraries, such as libraries you define in this 56 | # build script, prebuilt third-party libraries, or system libraries. 57 | 58 | target_link_libraries( # Specifies the target library. 59 | native-lib 60 | -llog -landroid -lEGL -lGLESv3 61 | # Links the target library to the log library 62 | # included in the NDK. 63 | ${log-lib} ) -------------------------------------------------------------------------------- /Application/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.cgfay.cain.glesnativesample" 8 | minSdkVersion 18 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | externalNativeBuild { 14 | cmake { 15 | cppFlags "-std=c++11" 16 | } 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | externalNativeBuild { 26 | cmake { 27 | path "CMakeLists.txt" 28 | } 29 | } 30 | } 31 | 32 | dependencies { 33 | compile fileTree(dir: 'libs', include: ['*.jar']) 34 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 35 | exclude group: 'com.android.support', module: 'support-annotations' 36 | }) 37 | compile 'com.android.support:appcompat-v7:25.3.1' 38 | testCompile 'junit:junit:4.12' 39 | } 40 | -------------------------------------------------------------------------------- /Application/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Volumes/MacHD/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /Application/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Application/src/main/assets/basemap.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/assets/basemap.tga -------------------------------------------------------------------------------- /Application/src/main/assets/fragment_linear_fog.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | 4 | uniform vec4 u_fogColor; 5 | uniform float u_fogMaxDist; 6 | uniform float u_fogMinDist; 7 | uniform sampler2D s_baseMap; 8 | 9 | in vec2 v_texCoord; 10 | in float v_eyeDist; 11 | 12 | layout(location = 0) out vec4 outColor; 13 | 14 | float computeLinearFogFactor() { 15 | float factor; 16 | // 线性雾化计算公式 17 | factor = (u_fogMaxDist - v_eyeDist) / (u_fogMinDist - u_fogMinDist); 18 | return factor; 19 | } 20 | 21 | void main() { 22 | float fogFactor = computeLinearFogFactor(); 23 | vec4 baseColor = texture(s_baseMap, v_texCoord); 24 | // 根据得到的线性雾化因子,计算实际输出的雾化效果 25 | outColor = baseColor * vec4(fogFactor) + u_fogColor * (1.0 - fogFactor); 26 | } 27 | -------------------------------------------------------------------------------- /Application/src/main/assets/fragment_mipmap.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | precision mediump float; 4 | in vec2 v_texCoord; 5 | layout(location = 0) out vec4 outColor; 6 | uniform sampler2D s_texture; 7 | void main() { 8 | outColor = texture(s_texture, v_texCoord); 9 | } -------------------------------------------------------------------------------- /Application/src/main/assets/fragment_multitexture.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | in vec2 v_texCoord; 4 | layout(location = 0) out vec4 outColor; 5 | uniform sampler2D s_baseMap; 6 | uniform sampler2D s_lightMap; 7 | void main() { 8 | vec4 baseColor; 9 | vec4 lightColor; 10 | 11 | baseColor = texture(s_baseMap, v_texCoord); 12 | lightColor = texture(s_lightMap, v_texCoord); 13 | outColor = baseColor * (lightColor + 0.25); 14 | } 15 | -------------------------------------------------------------------------------- /Application/src/main/assets/fragment_texture.glsl: -------------------------------------------------------------------------------- 1 | // fragment shader 2 | #version 300 es 3 | precision mediump float; 4 | in vec2 v_texCoord; 5 | layout(location = 0) out vec4 outColor; 6 | // 声明一个类型为sampler2D的统一变量 7 | // 采样器是用于从纹理贴图中读取的特殊统一变量 8 | uniform sampler2D s_texture; 9 | void main() { 10 | outColor = texture(s_texture, v_texCoord); 11 | } -------------------------------------------------------------------------------- /Application/src/main/assets/fragment_texture_cube.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | precision mediump float; 3 | in vec3 v_normal; 4 | layout(location = 0) out vec4 outColor; 5 | uniform samplerCube s_texture; 6 | void main() { 7 | outColor = texture(s_texture, v_normal); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /Application/src/main/assets/glslIntroduce.glsl: -------------------------------------------------------------------------------- 1 | // 声明版本 2 | #version 300 es 3 | 4 | // OpenGLES着色器语言 5 | 6 | // 默认精度 7 | precision highp float; 8 | precision mediump int; 9 | 10 | // 精度限定符 11 | highp vec4 position; 12 | varying lowp vec4 color; 13 | mediump float specularExp; 14 | 15 | // 统一变量Uniform 16 | // 统一变量是类型限定符,统一变量存储应用程序通过OpenGLES API传入着色器的只读值 17 | // 本质上一个着色器的任何参数在所有顶点或片元中都应该以统一变量的形式传入 18 | // 在编译时已知的变量应该是常量,不是统一变量。 19 | // 统一变量的命名空间在顶点着色器和片元着色器中是共享的,类似C语言中的static 20 | // 如果在顶点着色器和片元着色器中都声明一个统一变量,那么两个声明必须匹配 21 | // 使用API加载统一变量时,值在顶点和片元着色器中都可用 22 | uniform mat4 ViewProjMatrix; 23 | uniform mat4 viewMatrix; 24 | uniform vec3 lightPosition; 25 | // 统一变量块,实际上是一个缓冲区对象。 26 | // 缓冲区数据可以在多个程序中共享,但只需要设置一次。 27 | layout(std140) uniform TransformBlock 28 | { 29 | mat4 matViewProj; 30 | // 单独的统一变量块以及其内部的单独统一变量也可以指定布局限定符 31 | layout(row_major) mat3 matNormal; 32 | mat3 matTexGen; 33 | }; 34 | 35 | // 布局限定符,用于指定支持统一变量块的统一缓冲对象在内存中的布局方式 36 | // shared - 指定多个着色器活着多个程序中统一变量块的内存布局相同 37 | // packed - 指定编译器可以优化统一变量块的内存布局。使用时必须查询偏移位置,且统一变量块无法在顶点/片元着色器或程序间共享。 38 | // std140 - 基于OpenGLES3.0规范的"标准统一变量块布局"中定义的一组标准规则 39 | // row_major - 矩阵在内存中以行优先顺序布局 40 | // column_major - 矩阵在内存中以列优先顺序布局(默认) 41 | layout(shared, column_major) uniform; 42 | 43 | // 顶点输入变量/属性变量 44 | // 用于指定顶点着色器每个顶点的输入 45 | uniform mat4 u_matViewProjection; 46 | layout(location = 0) in vec4 a_postion; 47 | layout(location = 1) in vec3 a_color; 48 | // 在顶点说着色器中,v_color被声明为输出变量,那么要在片元着色器中使用,则需要在片元着色器的声明名字相同的in变量 49 | // smooth - 插值限定符,没有插值限定符时,默认插值行为是平滑着色,也就是顶点着色器输出变量在图元中进行先行插值 50 | // flat - 平面着色。在平面着色中,图元的值没有进行插值,而是将其中一个顶点视为驱动顶点,该顶点的值被用于图元的所有片元 51 | smooth out vec3 v_color; 52 | 53 | 54 | // 不变性声明 55 | // 两个着色器之间等价计算不能保证产生完全相同的结果,可能产生精度丢失的情况, 56 | // 因此需要不变性保证多次计算输出的结果是一致的 57 | invariant gl_Position; 58 | invariant texCoord; 59 | // 也可以用 #pragma 指定所有变量都不变 60 | // #pragma STDGL invariant (all) 61 | 62 | // 结构体 63 | struct fogStruct 64 | { 65 | vec4 color; 66 | float start; 67 | float end; 68 | } fogVar; 69 | 70 | void main() { 71 | // 变量 72 | vec3 myVec3 = vec3(0.0, 1.0, 2.0); 73 | vec3 temp; 74 | temp = myVec3.xyz; // temp = {0.0, 1.0, 2.0} 75 | temp = myVec3.xxx; // temp = {0.0, 0.0, 0.0} 76 | temp = myVec3.zyx; // temp = {2.0, 1.0, 0.0} 77 | // 常量 78 | const float zero = 0.0; 79 | const float pi = 3.14159; 80 | const vec4 red = vec4(1.0, 0.0, 0.0, 1.0); 81 | 82 | // 结构体初始化,必须一一对应 83 | fogVar = fogStruct(vec4(0.0, 1.0, 0.0, 0.0), 0.5, 2.0); 84 | // 获取结构体变量 85 | vec4 color = fogVar.color; 86 | float start = fogVar.start; 87 | float end = fogVar.end; 88 | 89 | // 数组 90 | float floatArray[4]; 91 | vec4 vecArray[2]; 92 | float a[4] = float[] (1.0, 2.0, 3.0, 4.0); 93 | float b[4] = float[4] (1.0, 2.0, 3.0, 4.0); 94 | vec2 c[2] = vec2[2](vec2(1.0), vec2(1.0)); 95 | 96 | // 运算符,大部分表现和C中的一样,乘法可以用在浮点、向量和矩阵之间进行运算 97 | // 除了 == 和 != 外,比较运算符智能用于标量值,要比较向量可以使用内建函数 98 | float myFloat; 99 | vec4 myVec4; 100 | mat4 myMat4; 101 | myVec4 = myVec4 * myFloat; 102 | myVec4 = myVec4 * myVec4; 103 | myVec4 = myMat4 * myVec4; 104 | myMat4 = myMat4 * myMat4; 105 | myMat4 = myMat4 * myFloat; 106 | 107 | // 控制流程语句,跟C语言一样 108 | if (color.a < 0.25) { 109 | color *= color.a; 110 | } else { 111 | color = myVec4(0.0); 112 | } 113 | 114 | // 使用统一变量块的例子: 115 | // 使用了声明的a_postion 和 TransformBlock缓冲区中的matViewProj 116 | // gl_Position = matViewProj * a_position; 117 | 118 | // 着色器的输入变量a_position 和 a_color 数据由应用程序加载。 119 | // 本质上应用程序将为每个顶点创建一个顶点数组创建了一个顶点数组,包含了位置和颜色 120 | gl_Position = u_matViewProjection * a_postion; 121 | v_color = a_color; 122 | 123 | 124 | } 125 | 126 | 127 | // 函数声明 128 | // 限定符 129 | // in - 这个限定符号指定参数按值传递,函数不能修改 130 | // inout - 这个限定符规定变量按照引用传入函数,函数中修改了该值,该变量是会跟着改变的 131 | // out - 表示该变量的值不被传入函数,但是在函数返回时被修改 132 | vec4 myFunc(inout float myFloat, 133 | out vec4 myVec4, 134 | mat4 myMat4); 135 | 136 | // 定义一个计算基本漫反射光线的函数: 137 | vec4 diffuse(vec3 normal, vec3 light, vec4 backColor) { 138 | // dot 是内建函数,计算向量的点积, pow函数则是计算幂次 139 | return baseColor * dot(normal, light); 140 | } 141 | -------------------------------------------------------------------------------- /Application/src/main/assets/lightmap.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/assets/lightmap.tga -------------------------------------------------------------------------------- /Application/src/main/assets/smoke.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/assets/smoke.tga -------------------------------------------------------------------------------- /Application/src/main/assets/triangleFragment.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | precision mediump float; 4 | 5 | // 跟顶点着色器中的out vec3 v_color; 声明的变量一致 6 | in vec3 v_color; 7 | layout(location = 0) out vec4 fragColor; 8 | 9 | void main(){ 10 | fragColor = vec4(v_color, 1.0); 11 | } -------------------------------------------------------------------------------- /Application/src/main/assets/triangleVertex.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | uniform mat4 u_matViewProjection; 4 | 5 | layout(location = 0) in vec4 a_position; 6 | layout(location = 1) in vec3 a_color; 7 | out vec3 v_color; 8 | 9 | void main() { 10 | gl_Position = u_matViewProjection * a_position; 11 | v_color = a_color; 12 | } -------------------------------------------------------------------------------- /Application/src/main/assets/vertex_linear_fog.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | uniform mat4 u_matViewProjection; 4 | uniform mat4 u_matView; 5 | uniform vec4 u_eyePos; 6 | 7 | layout(location = 0) in vec4 a_vertex; 8 | layout(location = 1) in vec2 a_texCoord0; 9 | 10 | out vec2 v_texCoord; 11 | out float v_eyeDist; 12 | 13 | void main() { 14 | // 将vertex顶点转到view区域 15 | vec4 vViewPos = u_matView * a_vertex; 16 | // 计算眼睛距离 17 | v_eyeDist = sqrt((vViewPos.x - u_eyePos.x) * (vViewPos.x - u_eyePos.x) 18 | + (vViewPos.y - u_eyePos.y) * (vViewPos.y - u_eyePos.y) 19 | + (vViewPos.z - u_eyePos.z) * (vViewPos.z - u_eyePos.z)); 20 | gl_Position = u_matViewProjection * a_vertex; 21 | v_texCoord = a_texCoord0.xy; 22 | } 23 | -------------------------------------------------------------------------------- /Application/src/main/assets/vertex_mipmap.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | uniform float u_offset; 4 | layout(location = 0) in vec4 a_position; 5 | layout(location = 1) in vec2 a_texCoord; 6 | out vec2 v_texCoord; 7 | void main() { 8 | gl_Position = a_position; 9 | gl_Position.x += u_offset; 10 | v_texCoord = a_texCoord; 11 | } -------------------------------------------------------------------------------- /Application/src/main/assets/vertex_multitexture.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | layout(location = 0) in vec4 a_position; 3 | layout(location = 1) in vec2 a_texCoord; 4 | out vec2 v_texCoord; 5 | void main() { 6 | gl_Position = a_position; 7 | v_texCoord = a_texCoord; 8 | } 9 | -------------------------------------------------------------------------------- /Application/src/main/assets/vertex_texture.glsl: -------------------------------------------------------------------------------- 1 | 2 | // vertex shader 3 | #version 300 es 4 | layout(location = 0) in vec4 a_postion; 5 | layout(location = 1) in vec2 a_texCoord; 6 | out vec2 v_texCoord; 7 | void main() { 8 | gl_Position = a_postion; 9 | v_texCoord = a_texCoord; 10 | } -------------------------------------------------------------------------------- /Application/src/main/assets/vertex_texture_cube.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | layout(location = 0) in vec4 a_position; 4 | layout(location = 1) in vec3 a_normal; 5 | out vec3 v_normal; 6 | void main() { 7 | gl_Position = a_position; 8 | v_normal = a_normal; 9 | } 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLLinearFog.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/7/2. 3 | // 4 | #include "../util/EGLUtil.h" 5 | 6 | typedef struct { 7 | GLuint programObject; 8 | 9 | GLint uMVPLoc; 10 | GLint uMVLoc; 11 | GLint uEyePosLoc; 12 | 13 | GLint uFogColorLoc; 14 | GLint uFogMaxDistLoc; 15 | GLint uFogMinDistLoc; 16 | GLint baseMapLoc; 17 | GLuint baseMapTexId; 18 | 19 | 20 | } UserData; 21 | 22 | // u_matViewProjection 的value值 23 | GLfloat mvpMatrix[] = { 24 | 1.0f, 1.0f, 0.0f, 0.0f, 25 | 0.0f, 1.0f, 0.0f, 0.0f, 26 | 1.0f, 0.0f, 1.0f, 0.0f, 27 | 1.0f, 1.0f, 1.0f, 1.0f 28 | }; 29 | // u_matView 的value值 30 | GLfloat mvMatrix[] = { 31 | 1.0f, 0.0f, 1.0f, 0.0f, 32 | 0.0f, 1.0f, 0.0f, 0.0f, 33 | 1.0f, 0.0f, 1.0f, 0.0f, 34 | 1.0f, 0.0f, 1.0f, 1.0f 35 | }; 36 | 37 | // u_eyePos 的value值 38 | GLfloat epVector[]= { 39 | 0.5f, 0.5f, 0.5f, 1.0f 40 | }; 41 | 42 | // u_fogColor 的value值 43 | GLfloat fColorVector[] = { 44 | 0.4f, 0.4f, 0.8f, 1.0f, 45 | 0.2f, 0.2f, 0.2f, 1.0f, 46 | 0.1f, 0.1f, 0.1f, 1.0f 47 | }; 48 | 49 | // 50 | 51 | // 顶点和texture 52 | GLfloat vertices[] = { 53 | -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 54 | -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 55 | 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 56 | 0.5f, 0.5f, 0.0f, 1.0f, 0.0f 57 | }; 58 | // 索引 59 | GLushort indices[] = {0, 1, 2, 0, 2, 3}; 60 | 61 | 62 | 63 | /** 64 | * 加载Texture 65 | * @param ioContext 66 | * @param fileName 67 | * @return 68 | */ 69 | GLuint loadTexture(void *ioContext, char *fileName) { 70 | 71 | int width, height; 72 | char *buffer = loadTGA(ioContext, fileName, &width, &height); 73 | GLuint textureId; 74 | 75 | if (buffer == NULL) { 76 | ALOGE("Error loading (%s) image.\n", fileName); 77 | return 0; 78 | } 79 | 80 | glGenTextures(1, &textureId); 81 | glBindTexture(GL_TEXTURE_2D, textureId); 82 | 83 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); 84 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 85 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 86 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 87 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 88 | 89 | free(buffer); 90 | 91 | return textureId; 92 | } 93 | 94 | /** 95 | * 初始化 96 | * @param esContext 97 | * @return 98 | */ 99 | int init(ESContext *esContext) { 100 | UserData *userData = (UserData *) esContext->userData; 101 | 102 | char *vertexStr = readAssetFile("vertex_linear_fog.glsl", 103 | esContext->activity->assetManager); 104 | char *fragmentStr = readAssetFile("fragment_linear_fog.glsl", 105 | esContext->activity->assetManager); 106 | 107 | userData->programObject = loadProgram(vertexStr, fragmentStr); 108 | 109 | // vertex中的uniform 110 | userData->uMVPLoc = glGetUniformLocation(userData->programObject, "u_matViewProjection"); 111 | userData->uMVLoc = glGetUniformLocation(userData->programObject, "u_matView"); 112 | userData->uEyePosLoc = glGetUniformLocation(userData->programObject, "u_eyePos"); 113 | 114 | // fragment中的uniform 115 | userData->uFogColorLoc = glGetUniformLocation(userData->programObject, "u_fogColor"); 116 | userData->uFogMaxDistLoc = glGetUniformLocation(userData->programObject, "u_fogMaxDist"); 117 | userData->uFogMinDistLoc = glGetUniformLocation(userData->programObject, "u_fogMinDist"); 118 | userData->baseMapLoc = glGetUniformLocation(userData->programObject, "s_baseMap"); 119 | 120 | // 加载texture 121 | userData->baseMapTexId = loadTexture(esContext->activity->assetManager, "lightmap.tga"); 122 | if (userData->baseMapTexId == 0) { 123 | return FALSE; 124 | } 125 | 126 | // 初始化vertex 的uniform 127 | glUniformMatrix4fv(userData->uMVPLoc, 1, GL_FALSE, mvpMatrix); 128 | glUniformMatrix4fv(userData->uMVLoc, 1, GL_FALSE, mvMatrix); 129 | glUniform4fv(userData->uEyePosLoc, 1, epVector); 130 | 131 | // 初始化fragment的uniform 132 | glUniform4fv(userData->uFogColorLoc, 3, fColorVector); 133 | glUniform1f(userData->uFogMaxDistLoc, 5.0f); 134 | glUniform1f(userData->uFogMinDistLoc, 1.0f); 135 | 136 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 137 | return TRUE; 138 | } 139 | 140 | void onDraw(ESContext *esContext) { 141 | UserData *userData = (UserData *) esContext->userData; 142 | 143 | glViewport(0, 0, esContext->width, esContext->height); 144 | glClear(GL_COLOR_BUFFER_BIT); 145 | glUseProgram(userData->programObject); 146 | 147 | glVertexAttribPointer(0, 3, GL_FLOAT, 148 | GL_FALSE, 5 * sizeof(GLfloat), vertices); 149 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vertices[3]); 150 | glEnableVertexAttribArray(0); 151 | glEnableVertexAttribArray(1); 152 | 153 | glActiveTexture(GL_TEXTURE0); 154 | glBindTexture(GL_TEXTURE_2D, userData->baseMapTexId); 155 | glUniform1i(userData->baseMapLoc, 0); 156 | 157 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 158 | } 159 | 160 | void shutDown(ESContext *esContext) { 161 | UserData *userData = (UserData *) esContext->userData; 162 | glDeleteTextures(1, &userData->baseMapTexId); 163 | glDeleteProgram(userData->programObject); 164 | } 165 | 166 | int onCreate(ESContext *esContext) { 167 | esContext->userData = malloc(sizeof(UserData)); 168 | createWindow(esContext, "LinearFog", 320, 240, ES_WINDOW_RGB); 169 | if (!init(esContext)) { 170 | ALOGE("Cannot init!"); 171 | return GL_FALSE; 172 | } 173 | registerDrawFunc(esContext, onDraw); 174 | registerShutdownFunc(esContext, shutDown); 175 | return GL_TRUE; 176 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLMipMap2D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/6/4. 3 | // 4 | 5 | #include "../util/EGLUtil.h" 6 | 7 | typedef struct { 8 | GLuint program; 9 | GLint samplerLoc; 10 | GLint offsetLoc; 11 | GLuint textureId; 12 | } UserData; 13 | 14 | 15 | GLboolean mipMap2D(GLubyte *src, GLubyte **dst, 16 | int srcWidth, int srcHeight, 17 | int *dstWidth, int *dstHeight) { 18 | int x, y; 19 | int texelSize = 3; 20 | *dstWidth = srcWidth / 2; 21 | if (*dstWidth <= 0) { 22 | *dstWidth = 1; 23 | } 24 | 25 | *dstHeight = srcHeight / 2; 26 | 27 | if (*dstHeight <= 0) { 28 | *dstHeight = 1; 29 | } 30 | 31 | *dst = (GLubyte *)malloc(sizeof(GLubyte) * (*dstWidth) * (*dstHeight)); 32 | 33 | if (*dst == nullptr) { 34 | return GL_FALSE; 35 | } 36 | 37 | for (y = 0; y < *dstHeight; ++y) { 38 | for (x = 0; x < *dstWidth; ++x) { 39 | int srcIndex[4]; 40 | float r = 0.0f, g = 0.0f, b = 0.0f; 41 | int sample; 42 | srcIndex[0] = (y * 2 * srcWidth + (x * 2)) * texelSize; 43 | srcIndex[1] = (y * 2 * srcWidth + (x * 2 + 1)) * texelSize; 44 | srcIndex[2] = ((y * 2 + 1) * srcWidth + x * 2) * texelSize; 45 | srcIndex[2] = ((y * 2 + 1) * srcWidth + x * 2 + 1) * texelSize; 46 | 47 | for (sample = 0; sample < 4; sample++) { 48 | r += src[srcIndex[sample]]; 49 | g += src[srcIndex[sample] + 1]; 50 | b += src[srcIndex[sample] + 2]; 51 | } 52 | 53 | r /= 4.0; 54 | g /= 4.0; 55 | b /= 4.0; 56 | 57 | (*dst)[(y * (*dstWidth) + x) * texelSize] = (GLubyte) r; 58 | (*dst)[(y * (*dstWidth) + x) * texelSize + 1] = (GLubyte) g; 59 | (*dst)[(y * (*dstWidth) + x) * texelSize + 2] = (GLubyte) b; 60 | } 61 | } 62 | 63 | return GL_TRUE; 64 | } 65 | 66 | GLubyte *checkImage(int width, int height, int checkSize) { 67 | 68 | GLubyte *pixels = (GLubyte *)malloc((size_t) (width * height * 3)); 69 | if (pixels == nullptr) { 70 | return nullptr; 71 | } 72 | for (int y = 0; y < height; ++y) { 73 | for (int x = 0; x < width; ++x) { 74 | GLubyte rColor = 0; 75 | GLubyte bColor = 0; 76 | 77 | if ((x / checkSize) % 2 == 0) { 78 | rColor = 255 * ((y / checkSize) % 2); 79 | bColor = 255 * (1 - (y /checkSize) %2); 80 | } else { 81 | bColor = 255 * ((y / checkSize) % 2); 82 | rColor = 255 * (1 - (y / checkSize) % 2); 83 | } 84 | 85 | pixels[(y * width + x) * 3] = rColor; 86 | pixels[(y * width + x) * 3 + 1] = 0; 87 | pixels[(y * width + x) * 3 + 2] = bColor; 88 | } 89 | } 90 | 91 | return pixels; 92 | } 93 | 94 | GLuint createMipMappedTexture2D() { 95 | GLuint textureId; 96 | int width = 256; 97 | int height = 256; 98 | int level; 99 | GLubyte *pixels; 100 | GLubyte *prevImage; 101 | GLubyte *newImage; 102 | 103 | pixels = checkImage(width, height, 8); 104 | 105 | if (pixels == nullptr) { 106 | return 0; 107 | } 108 | 109 | glGenTextures(1, &textureId); 110 | 111 | glBindTexture(GL_TEXTURE_2D, textureId); 112 | 113 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 114 | 115 | level = 1; 116 | prevImage = &pixels[0]; 117 | 118 | while (width > 1 && height > 1) { 119 | int newWidth, newHeight; 120 | mipMap2D(prevImage, &newImage, width, height, &newWidth, &newHeight); 121 | 122 | glTexImage2D(GL_TEXTURE_2D, level, GL_RGB, 123 | newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, newImage); 124 | 125 | free(prevImage); 126 | 127 | prevImage = newImage; 128 | 129 | level++; 130 | 131 | width = newWidth; 132 | height = newHeight; 133 | } 134 | 135 | free(newImage); 136 | 137 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 138 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 139 | 140 | return textureId; 141 | } 142 | 143 | 144 | int EGLInit(ESContext *esContext) { 145 | 146 | UserData *userData = (UserData *) esContext->userData; 147 | 148 | ANativeActivity* activity = esContext->activity; 149 | // 从asset文件夹加载shader 150 | char* vertex = readAssetFile("vertex_mipmap.glsl", activity->assetManager); 151 | char* fragment = readAssetFile("fragment_mipmap.glsl", activity->assetManager); 152 | // 加载program 153 | userData->program = loadProgram(vertex, fragment); 154 | if (userData->program == 0) { 155 | return FALSE; 156 | } 157 | 158 | // 获取sampler 的location 159 | userData->samplerLoc = glGetUniformLocation(userData->program, "s_texture"); 160 | // 获取 offset 的location 161 | userData->offsetLoc = glGetUniformLocation(userData->program, "u_offset"); 162 | 163 | // 加载texture 164 | userData->textureId = createMipMappedTexture2D(); 165 | 166 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 167 | 168 | return TRUE; 169 | } 170 | 171 | 172 | void onDraw(ESContext *esContext) { 173 | UserData *userData = (UserData *)esContext->userData; 174 | GLfloat vertices[] = { 175 | -0.5f, 0.5f, 0.0f, 1.5f, 176 | 0.0f, 0.0f, 177 | -0.5f, -0.5f, 0.0f, 0.75f, 178 | 0.0f, 1.0f, 179 | 0.5f, -0.5f, 0.0f, 0.75f, 180 | 1.0f, 1.0f, 181 | 0.5f, 0.5f, 0.0f, 1.5f, 182 | 1.0f, 0.0f 183 | }; 184 | 185 | GLushort indices[] = {0, 1, 2, 0, 2, 3}; 186 | 187 | glViewport(0, 0, esContext->width, esContext->height); 188 | 189 | glClear(GL_COLOR_BUFFER_BIT); 190 | 191 | glUseProgram(userData->program); 192 | 193 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), vertices); 194 | 195 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), &vertices[4]); 196 | 197 | glEnableVertexAttribArray(0); 198 | glEnableVertexAttribArray(1); 199 | 200 | glUniform1i(userData->samplerLoc, 0); 201 | 202 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 203 | glUniform1f(userData->offsetLoc, -0.6f); 204 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 205 | 206 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 207 | glUniform1f(userData->offsetLoc, 0.6f); 208 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 209 | 210 | } 211 | 212 | 213 | /** 214 | * 关闭窗口 215 | * @param esContext 216 | */ 217 | void windowShutdown(ESContext *esContext) { 218 | UserData *userData = (UserData *) esContext->userData; 219 | // 删除texture 220 | glDeleteTextures(1, &userData->textureId); 221 | // 删除program 222 | glDeleteProgram(userData->program); 223 | } 224 | 225 | 226 | 227 | /** 228 | * OpenGLES应用程序入口 229 | * @param esContext 230 | * @return 231 | */ 232 | int onCreate(ESContext *esContext) { 233 | esContext->userData = malloc(sizeof(UserData)); 234 | createWindow(esContext, "Hello MipMap2D", 320, 240, ES_WINDOW_RGB); 235 | if (!EGLInit(esContext)) { 236 | return GL_FALSE; 237 | } 238 | // 注册应用程序关闭函数 239 | registerShutdownFunc(esContext, windowShutdown); 240 | // 注册应用程序绘制函数 241 | registerDrawFunc(esContext, onDraw); 242 | 243 | return GL_TRUE; 244 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLMultiTexture.cpp: -------------------------------------------------------------------------------- 1 | #include "../util/EGLUtil.h" 2 | 3 | typedef struct { 4 | GLuint programObject; 5 | 6 | GLint baseMapLoc; 7 | GLint lightMapLoc; 8 | 9 | GLuint baseMapTexId; 10 | GLuint lightMapTexId; 11 | 12 | } UserData; 13 | 14 | 15 | GLuint loadTexture(void *ioContext, char *fileName) { 16 | 17 | int width, height; 18 | char *buffer = loadTGA(ioContext, fileName, &width, &height); 19 | GLuint textureId; 20 | 21 | if (buffer == NULL) { 22 | ALOGE("Error loading (%s) image.\n", fileName); 23 | return 0; 24 | } 25 | 26 | glGenTextures(1, &textureId); 27 | glBindTexture(GL_TEXTURE_2D, textureId); 28 | 29 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); 30 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 31 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 32 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 33 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 34 | 35 | free(buffer); 36 | 37 | return textureId; 38 | } 39 | 40 | 41 | int init(ESContext *esContext) { 42 | UserData *userData = (UserData *) esContext->userData; 43 | 44 | char *vertexStr = readAssetFile("vertex_multitexture.glsl", 45 | esContext->activity->assetManager); 46 | char *fragmentStr = readAssetFile("fragment_multitexture.glsl", 47 | esContext->activity->assetManager); 48 | 49 | userData->programObject = loadProgram(vertexStr, fragmentStr); 50 | 51 | userData->baseMapLoc = glGetUniformLocation(userData->programObject, "s_baseMap"); 52 | userData->lightMapLoc = glGetUniformLocation(userData->programObject, "s_lightMap"); 53 | 54 | userData->baseMapTexId = loadTexture(esContext->activity->assetManager, "basemap.tga"); 55 | userData->lightMapTexId = loadTexture(esContext->activity->assetManager, "lightmap.tga"); 56 | 57 | if (userData->baseMapTexId == 0 || userData->lightMapTexId == 0) { 58 | return FALSE; 59 | } 60 | 61 | glClearColor(1.0f, 1.0f, 1.0f, 0.0f); 62 | return TRUE; 63 | } 64 | 65 | void onDraw(ESContext *esContext) { 66 | UserData *userData = (UserData *) esContext->userData; 67 | // 顶点和texture 68 | GLfloat vertices[] = { 69 | -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 70 | -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 71 | 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 72 | 0.5f, 0.5f, 0.0f, 1.0f, 0.0f 73 | }; 74 | // 索引 75 | GLushort indices[] = {0, 1, 2, 0, 2, 3}; 76 | 77 | glViewport(0, 0, esContext->width, esContext->height); 78 | glClear(GL_COLOR_BUFFER_BIT); 79 | glUseProgram(userData->programObject); 80 | glVertexAttribPointer(0, 3, GL_FLOAT, 81 | GL_FALSE, 5 * sizeof(GLfloat), vertices); 82 | glVertexAttribPointer(1, 2, GL_FLOAT, 83 | GL_FALSE, 5 * sizeof(GLfloat), &vertices[3]); 84 | glEnableVertexAttribArray(0); 85 | glEnableVertexAttribArray(1); 86 | 87 | glActiveTexture(GL_TEXTURE0); 88 | glBindTexture(GL_TEXTURE_2D, userData->baseMapTexId); 89 | glUniform1i(userData->baseMapLoc, 0); 90 | 91 | glActiveTexture(GL_TEXTURE1); 92 | glBindTexture(GL_TEXTURE_2D, userData->lightMapTexId); 93 | glUniform1i(userData->lightMapLoc, 1); 94 | 95 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 96 | } 97 | 98 | void shutDown(ESContext *esContext) { 99 | UserData *userData = (UserData *) esContext->userData; 100 | 101 | glDeleteTextures(1, &userData->baseMapTexId); 102 | glDeleteTextures(1, &userData->lightMapTexId); 103 | 104 | glDeleteProgram(userData->programObject); 105 | } 106 | 107 | int onCreate(ESContext *esContext) { 108 | esContext->userData = malloc(sizeof(UserData)); 109 | createWindow(esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB); 110 | if (!init(esContext)) { 111 | ALOGE("Cannot init!"); 112 | return GL_FALSE; 113 | } 114 | registerDrawFunc(esContext, onDraw); 115 | registerShutdownFunc(esContext, shutDown); 116 | return GL_TRUE; 117 | } 118 | -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLParticleSystem.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/7/8. 3 | // 4 | 5 | #include "../util/EGLUtil.h" 6 | 7 | #define NUM_PARTICLES 1000 8 | #define PARTICLE_SIZE 7 9 | 10 | #define ATTRIBUTE_LIFETIME_LOCATION 0 11 | #define ATTRIBUTE_STARTPOSITION_LOCATION 1 12 | #define ATTRIBUTE_ENDPOSITION_LOCATION 2 13 | 14 | typedef struct 15 | { 16 | GLuint programObject; 17 | 18 | GLint timeLoc; 19 | GLint colorLoc; 20 | GLint centerPositionLoc; 21 | GLint samplerLoc; 22 | 23 | GLuint textureId; 24 | 25 | float particleData[ NUM_PARTICLES * PARTICLE_SIZE ]; 26 | 27 | float time; 28 | 29 | } UserData; 30 | 31 | 32 | GLuint loadTexture(void *ioContext, char *fileName) { 33 | int width, height; 34 | char *buffer = loadTGA(ioContext, fileName, &width, &height); 35 | GLuint texId; 36 | 37 | if (buffer == NULL) { 38 | ALOGE("Error loading (%s) image.\n", fileName); 39 | return 0; 40 | } 41 | 42 | glGenTextures(1, &texId); 43 | glBindTexture(GL_TEXTURE_2D, texId); 44 | 45 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); 46 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 47 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 48 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 49 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 50 | 51 | free(buffer); 52 | 53 | return texId; 54 | } 55 | 56 | 57 | int Init(ESContext *esContext) { 58 | UserData *userData = (UserData *)esContext->userData; 59 | int i; 60 | 61 | char vShaderStr[] = 62 | "#version 300 es \n" 63 | "uniform float u_time; \n" 64 | "uniform vec3 u_centerPosition; \n" 65 | "layout(location = 0) in float a_lifetime; \n" 66 | "layout(location = 1) in vec3 a_startPosition; \n" 67 | "layout(location = 2) in vec3 a_endPosition; \n" 68 | "out float v_lifetime; \n" 69 | "void main() \n" 70 | "{ \n" 71 | " if ( u_time <= a_lifetime ) \n" 72 | " { \n" 73 | " gl_Position.xyz = a_startPosition + \n" 74 | " (u_time * a_endPosition); \n" 75 | " gl_Position.xyz += u_centerPosition; \n" 76 | " gl_Position.w = 1.0; \n" 77 | " } \n" 78 | " else \n" 79 | " { \n" 80 | " gl_Position = vec4( -1000, -1000, 0, 0 ); \n" 81 | " } \n" 82 | " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n" 83 | " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n" 84 | " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n" 85 | "}"; 86 | 87 | char fShaderStr[] = 88 | "#version 300 es \n" 89 | "precision mediump float; \n" 90 | "uniform vec4 u_color; \n" 91 | "in float v_lifetime; \n" 92 | "layout(location = 0) out vec4 fragColor; \n" 93 | "uniform sampler2D s_texture; \n" 94 | "void main() \n" 95 | "{ \n" 96 | " vec4 texColor; \n" 97 | " texColor = texture( s_texture, gl_PointCoord ); \n" 98 | " fragColor = vec4( u_color ) * texColor; \n" 99 | " fragColor.a *= v_lifetime; \n" 100 | "} \n"; 101 | 102 | userData->programObject = loadProgram(vShaderStr, fShaderStr); 103 | 104 | userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" ); 105 | userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" ); 106 | userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" ); 107 | userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); 108 | 109 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 110 | 111 | srand ( 0 ); 112 | // 初始化粒子系统的位置 113 | for (i = 0; i < NUM_PARTICLES; i++) { 114 | float *particleData = &userData->particleData[i * PARTICLE_SIZE]; 115 | 116 | *particleData++ = ((float)(rand() % 10000) / 10000.0f); 117 | 118 | *particleData++ = ((float)(rand() % 10000) / 5000.0f) - 1.0f; 119 | *particleData++ = ((float)(rand() % 10000) / 5000.0f) - 1.0f; 120 | *particleData++ = ((float)(rand() % 10000) / 5000.0f) - 1.0f; 121 | 122 | *particleData++ = ((float)(rand() % 10000) / 40000.0f) - 0.125f; 123 | *particleData++ = ((float)(rand() % 10000) / 40000.0f) - 0.125f; 124 | *particleData++ = ((float)(rand() % 10000) / 40000.0f) - 0.125f; 125 | } 126 | 127 | userData->time = 1.0f; 128 | 129 | userData->textureId = loadTexture(esContext->activity->assetManager, "smoke.tga"); 130 | 131 | if (userData->textureId <= 0) { 132 | return FALSE; 133 | } 134 | return TRUE; 135 | } 136 | 137 | void update(ESContext *esContext, float deltaTime) { 138 | UserData *userData = (UserData *)esContext->userData; 139 | 140 | userData->time += deltaTime; 141 | 142 | glUseProgram ( userData->programObject ); 143 | 144 | // 1秒钟之后,更新粒子系统的位置 145 | if (userData->time >= 1.0f) { 146 | float centerPos[3]; 147 | float color[4]; 148 | 149 | userData->time = 0.0f; 150 | 151 | centerPos[0] = ((float) (rand() % 10000) / 10000.0f) - 0.5f; 152 | centerPos[1] = ((float) (rand() % 10000) / 10000.0f) - 0.5f; 153 | centerPos[2] = ((float) (rand() % 10000) / 10000.0f) - 0.5f; 154 | 155 | glUniform3fv(userData->centerPositionLoc, 1, ¢erPos[0]); 156 | 157 | color[0] = ((float) (rand() % 10000) / 20000.0f) + 0.5f; 158 | color[1] = ((float) (rand() % 10000) / 20000.0f) + 0.5f; 159 | color[2] = ((float) (rand() % 10000) / 20000.0f) + 0.5f; 160 | color[3] = 0.5; 161 | 162 | glUniform4fv(userData->colorLoc, 1, &color[0]); 163 | } 164 | 165 | glUniform1f(userData->timeLoc, userData->time); 166 | } 167 | 168 | void onDraw(ESContext *esContext) { 169 | UserData *userData = (UserData *)esContext->userData; 170 | 171 | glViewport ( 0, 0, esContext->width, esContext->height ); 172 | 173 | glClear(GL_COLOR_BUFFER_BIT); 174 | 175 | glUseProgram(userData->programObject); 176 | 177 | glVertexAttribPointer(ATTRIBUTE_LIFETIME_LOCATION, 1, GL_FLOAT, 178 | GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat), 179 | userData->particleData); 180 | 181 | glVertexAttribPointer(ATTRIBUTE_ENDPOSITION_LOCATION, 3, GL_FLOAT, 182 | GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat), 183 | &userData->particleData[1]); 184 | 185 | glVertexAttribPointer(ATTRIBUTE_STARTPOSITION_LOCATION, 3, GL_FLOAT, 186 | GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat), 187 | &userData->particleData[4]); 188 | 189 | 190 | glEnableVertexAttribArray(ATTRIBUTE_LIFETIME_LOCATION); 191 | glEnableVertexAttribArray(ATTRIBUTE_ENDPOSITION_LOCATION); 192 | glEnableVertexAttribArray(ATTRIBUTE_STARTPOSITION_LOCATION); 193 | 194 | // 混合 195 | glEnable(GL_BLEND); 196 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); 197 | 198 | glActiveTexture(GL_TEXTURE0); 199 | glBindTexture(GL_TEXTURE_2D, userData->textureId); 200 | 201 | glUniform1i(userData->samplerLoc, 0); 202 | 203 | glDrawArrays(GL_POINTS, 0, NUM_PARTICLES); 204 | } 205 | 206 | void windowShutdown(ESContext *esContext) { 207 | UserData *userData = (UserData *)esContext->userData; 208 | glDeleteTextures(1, &userData->textureId); 209 | glDeleteProgram(userData->programObject); 210 | } 211 | 212 | int onCreate(ESContext *esContext) { 213 | esContext->userData = malloc(sizeof(UserData)); 214 | createWindow(esContext, "ParticleSystem", 640, 480, ES_WINDOW_RGB); 215 | if (!Init(esContext)) { 216 | return GL_FALSE; 217 | } 218 | registerDrawFunc(esContext, onDraw); 219 | registerUpdateFunc(esContext, update); 220 | registerShutdownFunc(esContext, windowShutdown); 221 | 222 | return GL_TRUE; 223 | } 224 | -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLTexture2D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/6/4. 3 | // 4 | 5 | #include "../util/EGLUtil.h" 6 | 7 | typedef struct { 8 | GLuint program; 9 | GLint samplerLoc; 10 | GLuint textureId; 11 | } UserData; 12 | 13 | 14 | GLuint createSimplerTexture2D() { 15 | GLuint textureId; 16 | GLubyte pixels[4 * 3] = { 17 | 255, 0, 0, 18 | 0, 255, 0, 19 | 0, 0, 255, 20 | 255, 255, 0, 21 | }; 22 | 23 | // 0、设置解包对齐 24 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 25 | 26 | // 1、创建一个纹理对象 27 | glGenTextures(1, &textureId); 28 | 29 | // 2、绑定纹理对象 30 | glBindTexture(GL_TEXTURE_2D, textureId); 31 | 32 | // 3、加载图像数据 33 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 34 | 35 | // 4、将放大缩小过滤模式设置为GL_NEAREST 36 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 37 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 38 | 39 | return textureId; 40 | } 41 | 42 | 43 | int EGLInit(ESContext *esContext) { 44 | 45 | UserData *userData = (UserData *) esContext->userData; 46 | 47 | ANativeActivity* activity = esContext->activity; 48 | // 从asset文件夹加载shader 49 | char* vertex = readAssetFile("vertex_texture.glsl", activity->assetManager); 50 | char* fragment = readAssetFile("fragment_texture.glsl", activity->assetManager); 51 | // 加载program 52 | userData->program = loadProgram(vertex, fragment); 53 | if (userData->program == 0) { 54 | return FALSE; 55 | } 56 | 57 | // 获取sampler 的location 58 | userData->samplerLoc = glGetUniformLocation(userData->program, "s_texture"); 59 | 60 | // 加载texture 61 | userData->textureId = createSimplerTexture2D(); 62 | 63 | glClearColor(1.0f, 1.0f, 1.0f, 0.0f); 64 | return TRUE; 65 | } 66 | 67 | 68 | void onDraw(ESContext *esContext) { 69 | UserData *userData = (UserData *) esContext->userData; 70 | GLfloat vertices[] = { 71 | -0.5f, 0.5f, 0.0f, // Position 0 72 | 0.0f, 0.0f, // TexCoord 0 73 | -0.5f, -0.5f, 0.0f, // Position 1 74 | 0.0f, 1.0f, // TexCoord 1 75 | 0.5f, -0.5f, 0.0f, // Position 2 76 | 1.0f, 1.0f, // TexCoord 2 77 | 0.5f, 0.5f, 0.0f, // Position 3 78 | 1.0f, 0.0f // TexCoord 3 79 | }; 80 | 81 | GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 82 | 83 | // 设置viewport 84 | glViewport(0, 0, esContext->width, esContext->height); 85 | 86 | // 清空缓冲区 87 | glClear(GL_COLOR_BUFFER_BIT); 88 | 89 | // 使用之前创建的program 90 | glUseProgram(userData->program); 91 | 92 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), vertices); 93 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), &vertices[3]); 94 | 95 | // 使能对应位置的vertex属性值 96 | glEnableVertexAttribArray(0); 97 | glEnableVertexAttribArray(1); 98 | 99 | // 绑定texture 100 | glActiveTexture(GL_TEXTURE0); 101 | glBindTexture(GL_TEXTURE_2D, userData->textureId); 102 | 103 | // 获取统一变量 104 | glUniform1i(userData->samplerLoc, 0); 105 | 106 | // 绘制元素 107 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 108 | } 109 | 110 | /** 111 | * 关闭窗口 112 | * @param esContext 113 | */ 114 | void windowShutdown(ESContext *esContext) { 115 | UserData *userData = (UserData *) esContext->userData; 116 | // 删除texture 117 | glDeleteTextures(1, &userData->textureId); 118 | // 删除program 119 | glDeleteProgram ( userData->program ); 120 | } 121 | 122 | 123 | /** 124 | * OpenGLES应用程序入口 125 | * @param esContext 126 | * @return 127 | */ 128 | int onCreate(ESContext *esContext) { 129 | esContext->userData = malloc(sizeof(UserData)); 130 | createWindow(esContext, "Hello Texture2D", 320, 240, ES_WINDOW_RGB); 131 | if (!EGLInit(esContext)) { 132 | return GL_FALSE; 133 | } 134 | // 注册应用程序关闭函数 135 | registerShutdownFunc(esContext, windowShutdown); 136 | // 注册应用程序绘制函数 137 | registerDrawFunc(esContext, onDraw); 138 | 139 | return GL_TRUE; 140 | } 141 | -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLTextureCube.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/6/4. 3 | // 4 | 5 | #include "../util/EGLUtil.h" 6 | 7 | 8 | typedef struct { 9 | GLuint program; 10 | 11 | GLint samplerLoc; 12 | 13 | GLuint textureId; 14 | 15 | // 顶点数据 16 | int numIndices; 17 | GLfloat *vertices; 18 | GLfloat *normals; 19 | GLuint *indices; 20 | 21 | } UserData; 22 | 23 | 24 | GLuint createSimplerTextureCube() { 25 | 26 | GLuint textureId; 27 | GLubyte cubePixels[6][3] = { 28 | 255, 0, 0, 29 | 0, 255, 0, 30 | 0, 0, 255, 31 | 255, 255, 0, 32 | 255, 0, 255, 33 | 255, 255, 255, 34 | }; 35 | 36 | 37 | glGenTextures(1, &textureId); 38 | 39 | glBindTexture(GL_TEXTURE_CUBE_MAP, textureId); 40 | 41 | 42 | glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0, 43 | GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0]); 44 | glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0, 45 | GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1]); 46 | 47 | glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0, 48 | GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2]); 49 | glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0, 50 | GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3]); 51 | 52 | glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0, 53 | GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4]); 54 | glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0, 55 | GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5]); 56 | 57 | // 放大缩小过滤模式 58 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 59 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 60 | 61 | return textureId; 62 | } 63 | 64 | 65 | 66 | int EGLInit(ESContext *esContext) { 67 | 68 | UserData *userData = (UserData *) esContext->userData; 69 | 70 | ANativeActivity* activity = esContext->activity; 71 | // 从asset文件夹加载shader 72 | char* vertex = readAssetFile("vertex_texture_cube.glsl", activity->assetManager); 73 | char* fragment = readAssetFile("fragment_texture_cube.glsl", activity->assetManager); 74 | // 加载program 75 | userData->program = loadProgram(vertex, fragment); 76 | if (userData->program == 0) { 77 | return FALSE; 78 | } 79 | 80 | // 获取sampler 的location 81 | userData->samplerLoc = glGetUniformLocation(userData->program, "s_texture"); 82 | 83 | // 加载texture 84 | userData->textureId = createSimplerTextureCube(); 85 | 86 | // 加载vertex 数据 87 | userData->numIndices = sphere(20, 0.75f, &userData->vertices, &userData->normals, 88 | nullptr, &userData->indices); 89 | 90 | glClearColor(1.0f, 1.0f, 1.0f, 0.0f); 91 | return TRUE; 92 | } 93 | 94 | 95 | void onDraw(ESContext *esContext) { 96 | 97 | UserData *userData = (UserData *)esContext->userData; 98 | 99 | glViewport(0, 0, esContext->width, esContext->height); 100 | 101 | glClear(GL_COLOR_BUFFER_BIT); 102 | 103 | glCullFace(GL_BACK); 104 | 105 | glEnable(GL_CULL_FACE); 106 | 107 | glUseProgram(userData->program); 108 | 109 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, userData->vertices); 110 | 111 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, userData->normals); 112 | 113 | glEnableVertexAttribArray(0); 114 | 115 | glEnableVertexAttribArray(1); 116 | 117 | glActiveTexture(GL_TEXTURE0); 118 | 119 | glBindTexture(GL_TEXTURE_CUBE_MAP, userData->textureId); 120 | 121 | glUniform1i(userData->samplerLoc, 0); 122 | 123 | glDrawElements(GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_INT, userData->indices); 124 | 125 | } 126 | 127 | 128 | /** 129 | * 关闭窗口 130 | * @param esContext 131 | */ 132 | void windowShutdown(ESContext *esContext) { 133 | UserData *userData = (UserData *) esContext->userData; 134 | // 删除texture 135 | glDeleteTextures(1, &userData->textureId); 136 | // 删除program 137 | glDeleteProgram(userData->program); 138 | 139 | free(userData->vertices); 140 | free(userData->normals); 141 | free(userData->indices); 142 | } 143 | 144 | 145 | 146 | /** 147 | * OpenGLES应用程序入口 148 | * @param esContext 149 | * @return 150 | */ 151 | int onCreate(ESContext *esContext) { 152 | esContext->userData = malloc(sizeof(UserData)); 153 | createWindow(esContext, "Hello TextureCube", 320, 240, ES_WINDOW_RGB); 154 | if (!EGLInit(esContext)) { 155 | return GL_FALSE; 156 | } 157 | // 注册应用程序关闭函数 158 | registerShutdownFunc(esContext, windowShutdown); 159 | // 注册应用程序绘制函数 160 | registerDrawFunc(esContext, onDraw); 161 | 162 | return GL_TRUE; 163 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLTextureWrap.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/6/4. 3 | // 4 | 5 | #include "../util/EGLUtil.h" 6 | 7 | typedef struct { 8 | GLuint program; 9 | GLint samplerLoc; 10 | GLint offsetLoc; 11 | GLuint textureId; 12 | } UserData; 13 | 14 | 15 | GLubyte *checkImage(int width, int height, int checkSize) { 16 | 17 | GLubyte *pixels = (GLubyte *) malloc(width * height * 3); 18 | 19 | if (pixels == NULL) { 20 | return NULL; 21 | } 22 | 23 | for (int y = 0; y < height; y++ ) { 24 | for (int x = 0; x < width; x++ ) { 25 | GLubyte rColor = 0; 26 | GLubyte bColor = 0; 27 | 28 | if ((x / checkSize) % 2 == 0) { 29 | rColor = 255 * ((y / checkSize) % 2); 30 | bColor = 255 * (1 - ((y / checkSize) % 2)); 31 | } else { 32 | bColor = 255 * ((y / checkSize) % 2); 33 | rColor = 255 * (1 - ((y / checkSize ) % 2)); 34 | } 35 | 36 | pixels[(y * width + x) * 3] = rColor; 37 | pixels[(y * width + x) * 3 + 1] = 0; 38 | pixels[(y * width + x) * 3 + 2] = bColor; 39 | } 40 | } 41 | 42 | return pixels; 43 | } 44 | 45 | 46 | GLuint createTexture2D() { 47 | GLuint textureId; 48 | int width = 256, height = 256; 49 | GLubyte *pixels = checkImage(width, height, 64); 50 | 51 | if (pixels == nullptr) { 52 | return 0; 53 | } 54 | 55 | glGenTextures(1, &textureId); 56 | 57 | glBindTexture(GL_TEXTURE_2D, textureId); 58 | 59 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 60 | 61 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 62 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 63 | 64 | return textureId; 65 | } 66 | 67 | 68 | 69 | int EGLInit(ESContext *esContext) { 70 | 71 | UserData *userData = (UserData *) esContext->userData; 72 | 73 | char vertex[] = 74 | "#version 300 es\n" 75 | "uniform float u_offset;\n" 76 | "layout(location = 0) in vec4 a_position;\n" 77 | "layout(location = 1) in vec2 a_texCoord;\n" 78 | "out vec2 v_texCoord;\n" 79 | "void main()\n" 80 | "{" 81 | "gl_Position = a_position;\n" 82 | "gl_Position.x += u_offset;\n" 83 | "v_texCoord = a_texCoord;\n" 84 | "}\n"; 85 | 86 | 87 | char fragment[] = 88 | "#version 300 es\n" 89 | "precision mediump float;\n" 90 | "in vec2 v_texCoord;\n" 91 | "layout(location = 0) out vec4 outColor;\n" 92 | "uniform sampler2D s_texture;\n" 93 | "void main()\n" 94 | "{\n" 95 | "outColor = texture( s_texture, v_texCoord );\n" 96 | "}\n"; 97 | 98 | // 加载program 99 | userData->program = loadProgram(vertex, fragment); 100 | if (userData->program == 0) { 101 | return FALSE; 102 | } 103 | 104 | // 获取sampler 的location 105 | userData->samplerLoc = glGetUniformLocation(userData->program, "s_texture"); 106 | // 获取 offset 的location 107 | userData->offsetLoc = glGetUniformLocation(userData->program, "u_offset"); 108 | 109 | // 加载texture 110 | userData->textureId = createTexture2D(); 111 | 112 | glClearColor(1.0f, 1.0f, 1.0f, 0.0f); 113 | 114 | return TRUE; 115 | } 116 | 117 | 118 | void onDraw(ESContext *esContext) { 119 | UserData *userData = (UserData *)esContext->userData; 120 | GLfloat vertices[] = { 121 | -0.3f, 0.3f, 0.0f, 1.0f, // Position 0 122 | -1.0f, -1.0f, // TexCoord 0 123 | -0.3f, -0.3f, 0.0f, 1.0f, // Position 1 124 | -1.0f, 2.0f, // TexCoord 1 125 | 0.3f, -0.3f, 0.0f, 1.0f, // Position 2 126 | 2.0f, 2.0f, // TexCoord 2 127 | 0.3f, 0.3f, 0.0f, 1.0f, // Position 3 128 | 2.0f, -1.0f // TexCoord 3 129 | }; 130 | 131 | GLushort indices[] = {0, 1, 2, 0, 2, 3}; 132 | 133 | glViewport(0, 0, esContext->width, esContext->height); 134 | 135 | glClear(GL_COLOR_BUFFER_BIT); 136 | 137 | glUseProgram(userData->program); 138 | 139 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), vertices); 140 | 141 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), &vertices[4]); 142 | 143 | glEnableVertexAttribArray(0); 144 | glEnableVertexAttribArray(1); 145 | 146 | glActiveTexture(GL_TEXTURE0); 147 | glBindTexture(GL_TEXTURE_2D, userData->textureId); 148 | 149 | glUniform1i(userData->samplerLoc, 0); 150 | 151 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 152 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 153 | glUniform1f(userData->offsetLoc, -0.7f); 154 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 155 | 156 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 157 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 158 | glUniform1f(userData->offsetLoc, 0.0f); 159 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 160 | 161 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 162 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 163 | glUniform1f(userData->offsetLoc, 0.7f); 164 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); 165 | 166 | } 167 | 168 | 169 | /** 170 | * 关闭窗口 171 | * @param esContext 172 | */ 173 | void windowShutdown(ESContext *esContext) { 174 | UserData *userData = (UserData *) esContext->userData; 175 | // 删除texture 176 | glDeleteTextures(1, &userData->textureId); 177 | // 删除program 178 | glDeleteProgram(userData->program); 179 | } 180 | 181 | 182 | 183 | /** 184 | * OpenGLES应用程序入口 185 | * @param esContext 186 | * @return 187 | */ 188 | int onCreate(ESContext *esContext) { 189 | esContext->userData = malloc(sizeof(UserData)); 190 | createWindow(esContext, "Hello TextureWrap", 640, 640, ES_WINDOW_RGB); 191 | if (!EGLInit(esContext)) { 192 | return GL_FALSE; 193 | } 194 | // 注册应用程序关闭函数 195 | registerShutdownFunc(esContext, windowShutdown); 196 | // 注册应用程序绘制函数 197 | registerDrawFunc(esContext, onDraw); 198 | 199 | return GL_TRUE; 200 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/EGLTriangle.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../util/EGLUtil.h" 3 | 4 | const GLint COORDS_PER_VERTEX = 3; 5 | const GLint vertexStride = COORDS_PER_VERTEX * 4; 6 | 7 | typedef struct { 8 | GLuint program; 9 | 10 | } UserData; 11 | 12 | int EGLInit(ESContext *esContext) { 13 | 14 | UserData *userData = (UserData *) esContext->userData; 15 | 16 | char vertexShader[] = 17 | "#version 300 es\n" 18 | "layout(location = 0) in vec4 a_position;\n" 19 | "layout(location = 1) in vec4 a_color;\n" 20 | "out vec4 v_color;" 21 | "void main()\n" 22 | "{\n" 23 | " gl_Position = a_position;\n" 24 | " v_color = a_color;\n" 25 | "}\n"; 26 | 27 | char fragmentShader[] = 28 | "#version 300 es\n" 29 | "precision mediump float;\n" 30 | "in vec4 v_color;\n" 31 | "out vec4 fragColor;\n" 32 | "void main()\n" 33 | "{\n" 34 | // " fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" 35 | " fragColor = v_color;\n" 36 | "}\n"; 37 | 38 | userData->program = loadProgram(vertexShader, fragmentShader); 39 | 40 | // // 使用assets文件夹下面的着色器程序创建program 41 | // ANativeActivity* activity = esContext->activity; 42 | // char* vertex = readAssetFile("triangleVertex.glsl", activity->assetManager); 43 | // char* fragment = readAssetFile("triangleFragment.glsl", activity->assetManager); 44 | // userData->program = loadProgram(vertex, fragment); 45 | if (userData->program == 0) { 46 | return FALSE; 47 | } 48 | 49 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 50 | return TRUE; 51 | } 52 | 53 | /** 54 | * 绘制方法 55 | * @param esContext 56 | */ 57 | void onDraw(ESContext *esContext) { 58 | UserData *userData = (UserData *)esContext->userData; 59 | 60 | GLfloat vertices[] = { 61 | 0.0f, 0.5f, 0.0f, 62 | -0.5f, -0.5f, 0.0f, 63 | 0.5f, -0.5f, 0.0f 64 | }; 65 | 66 | GLfloat color[] = { 67 | 1.0f, 0.0f, 0.0f, 1.0f 68 | }; 69 | 70 | GLint vertexCount = sizeof(vertices) / (sizeof(vertices[0]) * COORDS_PER_VERTEX); 71 | 72 | glViewport(0, 0, esContext->width, esContext->height); 73 | 74 | glClear(GL_COLOR_BUFFER_BIT); 75 | 76 | glUseProgram(userData->program); 77 | 78 | // 获取a_position位置句柄 79 | GLint positionHandle = glGetAttribLocation(userData->program, "a_position"); 80 | glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GL_FLOAT, GL_FALSE, vertexStride, vertices); 81 | glEnableVertexAttribArray(positionHandle); 82 | 83 | // // 获取颜色句柄 84 | // GLint colorHandle = glGetUniformLocation(userData->program, "a_color"); 85 | // glUniform4fv(colorHandle, 1, color); 86 | 87 | // 使用glVertexAttrib4fv指定,不启用顶点属性数组,第一个参数指的是着色器语言中layout绑定的location的值 88 | glVertexAttrib4fv(1, color); 89 | 90 | glDrawArrays(GL_TRIANGLES, 0, vertexCount); 91 | 92 | glDisableVertexAttribArray(positionHandle); 93 | } 94 | 95 | /** 96 | * 关闭窗口 97 | * @param esContext 98 | */ 99 | void windowShutdown(ESContext *esContext) { 100 | UserData *userData = (UserData *) esContext->userData; 101 | glDeleteProgram ( userData->program ); 102 | } 103 | 104 | /** 105 | * OpenGLES应用程序入口 106 | * @param esContext 107 | * @return 108 | */ 109 | int onCreate(ESContext *esContext) { 110 | esContext->userData = malloc(sizeof(UserData)); 111 | createWindow(esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB); 112 | if (!EGLInit(esContext)) { 113 | return GL_FALSE; 114 | } 115 | // 注册应用程序关闭函数 116 | registerShutdownFunc(esContext, windowShutdown); 117 | // 注册应用程序绘制函数 118 | registerDrawFunc(esContext, onDraw); 119 | 120 | return GL_TRUE; 121 | } 122 | -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/VertexBufferSample.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/5/29. 3 | // 4 | 5 | #include 6 | 7 | typedef int vertex_t; 8 | 9 | /** 10 | * 创建和绑定顶点缓冲区对象 11 | * @param vertexBuffer 12 | * @param indices 13 | * @param numVertices 14 | * @param numIndices 15 | * @param vboIds 16 | */ 17 | void initVertexBufferObjects(vertex_t *vertexBuffer, 18 | GLushort *indices, 19 | GLuint numVertices, 20 | GLuint numIndices, 21 | GLuint *vboIds) { 22 | 23 | // 获取vboIds中两个未用的缓冲区对象名称。然后vboIds返回的未使用的缓冲区对象名称用于创建一个数组缓冲区对象 24 | // 和一个元素数组缓冲区对象。数组缓冲区对象用于保存一个或多个图元的顶点属性数据。 25 | glGenBuffers(2, vboIds); 26 | 27 | glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); 28 | glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertex_t), 29 | vertexBuffer, GL_STATIC_DRAW); 30 | 31 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]); 32 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(GLushort), 33 | indices, GL_STATIC_DRAW); 34 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/gles/VertexSample.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/5/27. 3 | // 4 | 5 | 6 | //四个顶点属性(位置、法线和两个纹理坐标)组成缓冲区布局如下: 7 | // 位置 法线 纹理0 纹理1 8 | // |x | y | z | x | y | z | s | t | s | t | 9 | 10 | // 结构数组 11 | #include 12 | #include 13 | 14 | #define VERTEX_POS_SIZE 3 15 | #define VERTEX_NORMAL_SIZE 3 16 | #define VERTEX_TEXCOORD0_SIZE 2 17 | #define VERTEX_TEXCOORD1_SIZE 2 18 | 19 | #define VERTEX_POS_INDX 0 20 | #define VERTEX_NORMAL_INDX 1 21 | #define VERTEX_TEXCOORD0_INDX 2 22 | #define VERTEX_TEXCOORD1_INDX 3 23 | 24 | #define VERTEX_POS_OFFSET 0 25 | #define VERTEX_NORMAL_OFFSET 3 26 | #define VERTEX_TEXCOORD0_OFFSET 6 27 | #define VERTEX_TEXCOORD1_OFFSET 8 28 | 29 | #define VERTEX_ATTRIB_SIZE (VERTEX_POS_SIZE + VERTEX_NORMAL_SIZE + VERTEX_TEXCOORD0_SIZE + VERTEX_TEXCOORD1_SIZE) 30 | 31 | // 结构数组例子,使用了缓冲区,这种分配方法最高效。因为每个顶点的属性数据可以顺序读取,这是最高效的内存访问模式 32 | void structSample(int numVertices) { 33 | 34 | float *p = (float *) malloc(sizeof(float) * VERTEX_ATTRIB_SIZE * numVertices); 35 | 36 | // 位置属性 37 | glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, VERTEX_ATTRIB_SIZE * 38 | sizeof(float), (p + VERTEX_POS_OFFSET)); 39 | 40 | 41 | // 法线属性 42 | glVertexAttribPointer(VERTEX_NORMAL_INDX, VERTEX_NORMAL_SIZE, GL_FLOAT, GL_FALSE, VERTEX_ATTRIB_SIZE * 43 | sizeof(float), (p + VERTEX_NORMAL_OFFSET)); 44 | 45 | // 纹理0 属性 46 | glVertexAttribPointer(VERTEX_TEXCOORD0_INDX, VERTEX_TEXCOORD0_SIZE, GL_FLOAT, GL_FALSE, VERTEX_ATTRIB_SIZE * 47 | sizeof(float), (p + VERTEX_TEXCOORD0_OFFSET)); 48 | 49 | // 纹理1 属性 50 | glVertexAttribPointer(VERTEX_TEXCOORD1_INDX, VERTEX_TEXCOORD1_SIZE, GL_FLOAT, GL_FALSE, VERTEX_ATTRIB_SIZE * 51 | sizeof(float), (p + VERTEX_TEXCOORD1_OFFSET)); 52 | } 53 | 54 | // 数组结构,位置、法线、纹理坐标都保存在单独的缓冲区中 55 | void arraySample(int numVertices) { 56 | float *position = (float *)malloc(numVertices * VERTEX_POS_SIZE * sizeof(float)); 57 | float *normal = (float *)malloc(numVertices * VERTEX_NORMAL_SIZE * sizeof(float)); 58 | float *texcoord0 = (float *)malloc(numVertices * VERTEX_TEXCOORD0_SIZE * sizeof(float)); 59 | float *texcoord1 = (float *)malloc(numVertices * VERTEX_TEXCOORD1_SIZE * sizeof(float)); 60 | 61 | glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, VERTEX_POS_SIZE * 62 | sizeof(float), position); 63 | glVertexAttribPointer(VERTEX_NORMAL_INDX, VERTEX_NORMAL_SIZE, GL_FLOAT, GL_FALSE, VERTEX_NORMAL_SIZE * 64 | sizeof(float), normal); 65 | glVertexAttribPointer(VERTEX_TEXCOORD0_INDX, VERTEX_TEXCOORD0_SIZE, GL_FLOAT, GL_FALSE, VERTEX_TEXCOORD0_SIZE * 66 | sizeof(float), texcoord0); 67 | glVertexAttribPointer(VERTEX_TEXCOORD1_INDX, VERTEX_TEXCOORD1_SIZE, GL_FLOAT, GL_FALSE, VERTEX_TEXCOORD1_SIZE * 68 | sizeof(float), texcoord1); 69 | } 70 | -------------------------------------------------------------------------------- /Application/src/main/cpp/glue/android_native_app_glue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "android_native_app_glue.h" 27 | #include 28 | 29 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) 30 | #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__)) 31 | 32 | /* For debug builds, always enable the debug traces in this library */ 33 | #ifndef NDEBUG 34 | # define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__)) 35 | #else 36 | # define LOGV(...) ((void)0) 37 | #endif 38 | 39 | static void free_saved_state(struct android_app* android_app) { 40 | pthread_mutex_lock(&android_app->mutex); 41 | if (android_app->savedState != NULL) { 42 | free(android_app->savedState); 43 | android_app->savedState = NULL; 44 | android_app->savedStateSize = 0; 45 | } 46 | pthread_mutex_unlock(&android_app->mutex); 47 | } 48 | 49 | int8_t android_app_read_cmd(struct android_app* android_app) { 50 | int8_t cmd; 51 | if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { 52 | switch (cmd) { 53 | case APP_CMD_SAVE_STATE: 54 | free_saved_state(android_app); 55 | break; 56 | } 57 | return cmd; 58 | } else { 59 | LOGE("No data on command pipe!"); 60 | } 61 | return -1; 62 | } 63 | 64 | static void print_cur_config(struct android_app* android_app) { 65 | char lang[2], country[2]; 66 | AConfiguration_getLanguage(android_app->config, lang); 67 | AConfiguration_getCountry(android_app->config, country); 68 | 69 | LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " 70 | "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " 71 | "modetype=%d modenight=%d", 72 | AConfiguration_getMcc(android_app->config), 73 | AConfiguration_getMnc(android_app->config), 74 | lang[0], lang[1], country[0], country[1], 75 | AConfiguration_getOrientation(android_app->config), 76 | AConfiguration_getTouchscreen(android_app->config), 77 | AConfiguration_getDensity(android_app->config), 78 | AConfiguration_getKeyboard(android_app->config), 79 | AConfiguration_getNavigation(android_app->config), 80 | AConfiguration_getKeysHidden(android_app->config), 81 | AConfiguration_getNavHidden(android_app->config), 82 | AConfiguration_getSdkVersion(android_app->config), 83 | AConfiguration_getScreenSize(android_app->config), 84 | AConfiguration_getScreenLong(android_app->config), 85 | AConfiguration_getUiModeType(android_app->config), 86 | AConfiguration_getUiModeNight(android_app->config)); 87 | } 88 | 89 | void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { 90 | switch (cmd) { 91 | case APP_CMD_INPUT_CHANGED: 92 | LOGV("APP_CMD_INPUT_CHANGED\n"); 93 | pthread_mutex_lock(&android_app->mutex); 94 | if (android_app->inputQueue != NULL) { 95 | AInputQueue_detachLooper(android_app->inputQueue); 96 | } 97 | android_app->inputQueue = android_app->pendingInputQueue; 98 | if (android_app->inputQueue != NULL) { 99 | LOGV("Attaching input queue to looper"); 100 | AInputQueue_attachLooper(android_app->inputQueue, 101 | android_app->looper, LOOPER_ID_INPUT, NULL, 102 | &android_app->inputPollSource); 103 | } 104 | pthread_cond_broadcast(&android_app->cond); 105 | pthread_mutex_unlock(&android_app->mutex); 106 | break; 107 | 108 | case APP_CMD_INIT_WINDOW: 109 | LOGV("APP_CMD_INIT_WINDOW\n"); 110 | pthread_mutex_lock(&android_app->mutex); 111 | android_app->window = android_app->pendingWindow; 112 | pthread_cond_broadcast(&android_app->cond); 113 | pthread_mutex_unlock(&android_app->mutex); 114 | break; 115 | 116 | case APP_CMD_TERM_WINDOW: 117 | LOGV("APP_CMD_TERM_WINDOW\n"); 118 | pthread_cond_broadcast(&android_app->cond); 119 | break; 120 | 121 | case APP_CMD_RESUME: 122 | case APP_CMD_START: 123 | case APP_CMD_PAUSE: 124 | case APP_CMD_STOP: 125 | LOGV("activityState=%d\n", cmd); 126 | pthread_mutex_lock(&android_app->mutex); 127 | android_app->activityState = cmd; 128 | pthread_cond_broadcast(&android_app->cond); 129 | pthread_mutex_unlock(&android_app->mutex); 130 | break; 131 | 132 | case APP_CMD_CONFIG_CHANGED: 133 | LOGV("APP_CMD_CONFIG_CHANGED\n"); 134 | AConfiguration_fromAssetManager(android_app->config, 135 | android_app->activity->assetManager); 136 | print_cur_config(android_app); 137 | break; 138 | 139 | case APP_CMD_DESTROY: 140 | LOGV("APP_CMD_DESTROY\n"); 141 | android_app->destroyRequested = 1; 142 | break; 143 | } 144 | } 145 | 146 | void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { 147 | switch (cmd) { 148 | case APP_CMD_TERM_WINDOW: 149 | LOGV("APP_CMD_TERM_WINDOW\n"); 150 | pthread_mutex_lock(&android_app->mutex); 151 | android_app->window = NULL; 152 | pthread_cond_broadcast(&android_app->cond); 153 | pthread_mutex_unlock(&android_app->mutex); 154 | break; 155 | 156 | case APP_CMD_SAVE_STATE: 157 | LOGV("APP_CMD_SAVE_STATE\n"); 158 | pthread_mutex_lock(&android_app->mutex); 159 | android_app->stateSaved = 1; 160 | pthread_cond_broadcast(&android_app->cond); 161 | pthread_mutex_unlock(&android_app->mutex); 162 | break; 163 | 164 | case APP_CMD_RESUME: 165 | free_saved_state(android_app); 166 | break; 167 | } 168 | } 169 | 170 | void app_dummy() { 171 | 172 | } 173 | 174 | static void android_app_destroy(struct android_app* android_app) { 175 | LOGV("android_app_destroy!"); 176 | free_saved_state(android_app); 177 | pthread_mutex_lock(&android_app->mutex); 178 | if (android_app->inputQueue != NULL) { 179 | AInputQueue_detachLooper(android_app->inputQueue); 180 | } 181 | AConfiguration_delete(android_app->config); 182 | android_app->destroyed = 1; 183 | pthread_cond_broadcast(&android_app->cond); 184 | pthread_mutex_unlock(&android_app->mutex); 185 | // Can't touch android_app object after this. 186 | } 187 | 188 | static void process_input(struct android_app* app, struct android_poll_source* source) { 189 | AInputEvent* event = NULL; 190 | while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { 191 | LOGV("New input event: type=%d\n", AInputEvent_getType(event)); 192 | if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { 193 | continue; 194 | } 195 | int32_t handled = 0; 196 | if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); 197 | AInputQueue_finishEvent(app->inputQueue, event, handled); 198 | } 199 | } 200 | 201 | static void process_cmd(struct android_app* app, struct android_poll_source* source) { 202 | int8_t cmd = android_app_read_cmd(app); 203 | android_app_pre_exec_cmd(app, cmd); 204 | if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); 205 | android_app_post_exec_cmd(app, cmd); 206 | } 207 | 208 | static void* android_app_entry(void* param) { 209 | struct android_app* android_app = (struct android_app*)param; 210 | 211 | android_app->config = AConfiguration_new(); 212 | AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); 213 | 214 | print_cur_config(android_app); 215 | 216 | android_app->cmdPollSource.id = LOOPER_ID_MAIN; 217 | android_app->cmdPollSource.app = android_app; 218 | android_app->cmdPollSource.process = process_cmd; 219 | android_app->inputPollSource.id = LOOPER_ID_INPUT; 220 | android_app->inputPollSource.app = android_app; 221 | android_app->inputPollSource.process = process_input; 222 | 223 | ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 224 | ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, 225 | &android_app->cmdPollSource); 226 | android_app->looper = looper; 227 | 228 | pthread_mutex_lock(&android_app->mutex); 229 | android_app->running = 1; 230 | pthread_cond_broadcast(&android_app->cond); 231 | pthread_mutex_unlock(&android_app->mutex); 232 | 233 | android_main(android_app); 234 | 235 | android_app_destroy(android_app); 236 | return NULL; 237 | } 238 | 239 | // -------------------------------------------------------------------- 240 | // Native activity interaction (called from windowEntry thread) 241 | // -------------------------------------------------------------------- 242 | 243 | static struct android_app* android_app_create(ANativeActivity* activity, 244 | void* savedState, size_t savedStateSize) { 245 | struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); 246 | memset(android_app, 0, sizeof(struct android_app)); 247 | android_app->activity = activity; 248 | 249 | pthread_mutex_init(&android_app->mutex, NULL); 250 | pthread_cond_init(&android_app->cond, NULL); 251 | 252 | if (savedState != NULL) { 253 | android_app->savedState = malloc(savedStateSize); 254 | android_app->savedStateSize = savedStateSize; 255 | memcpy(android_app->savedState, savedState, savedStateSize); 256 | } 257 | 258 | int msgpipe[2]; 259 | if (pipe(msgpipe)) { 260 | LOGE("could not create pipe: %s", strerror(errno)); 261 | return NULL; 262 | } 263 | android_app->msgread = msgpipe[0]; 264 | android_app->msgwrite = msgpipe[1]; 265 | 266 | pthread_attr_t attr; 267 | pthread_attr_init(&attr); 268 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 269 | pthread_create(&android_app->thread, &attr, android_app_entry, android_app); 270 | 271 | // Wait for thread to start. 272 | pthread_mutex_lock(&android_app->mutex); 273 | while (!android_app->running) { 274 | pthread_cond_wait(&android_app->cond, &android_app->mutex); 275 | } 276 | pthread_mutex_unlock(&android_app->mutex); 277 | 278 | return android_app; 279 | } 280 | 281 | static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { 282 | if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { 283 | LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); 284 | } 285 | } 286 | 287 | static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { 288 | pthread_mutex_lock(&android_app->mutex); 289 | android_app->pendingInputQueue = inputQueue; 290 | android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); 291 | while (android_app->inputQueue != android_app->pendingInputQueue) { 292 | pthread_cond_wait(&android_app->cond, &android_app->mutex); 293 | } 294 | pthread_mutex_unlock(&android_app->mutex); 295 | } 296 | 297 | static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { 298 | pthread_mutex_lock(&android_app->mutex); 299 | if (android_app->pendingWindow != NULL) { 300 | android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); 301 | } 302 | android_app->pendingWindow = window; 303 | if (window != NULL) { 304 | android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); 305 | } 306 | while (android_app->window != android_app->pendingWindow) { 307 | pthread_cond_wait(&android_app->cond, &android_app->mutex); 308 | } 309 | pthread_mutex_unlock(&android_app->mutex); 310 | } 311 | 312 | static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { 313 | pthread_mutex_lock(&android_app->mutex); 314 | android_app_write_cmd(android_app, cmd); 315 | while (android_app->activityState != cmd) { 316 | pthread_cond_wait(&android_app->cond, &android_app->mutex); 317 | } 318 | pthread_mutex_unlock(&android_app->mutex); 319 | } 320 | 321 | static void android_app_free(struct android_app* android_app) { 322 | pthread_mutex_lock(&android_app->mutex); 323 | android_app_write_cmd(android_app, APP_CMD_DESTROY); 324 | while (!android_app->destroyed) { 325 | pthread_cond_wait(&android_app->cond, &android_app->mutex); 326 | } 327 | pthread_mutex_unlock(&android_app->mutex); 328 | 329 | close(android_app->msgread); 330 | close(android_app->msgwrite); 331 | pthread_cond_destroy(&android_app->cond); 332 | pthread_mutex_destroy(&android_app->mutex); 333 | free(android_app); 334 | } 335 | 336 | static void onDestroy(ANativeActivity* activity) { 337 | LOGV("Destroy: %p\n", activity); 338 | android_app_free((struct android_app*)activity->instance); 339 | } 340 | 341 | static void onStart(ANativeActivity* activity) { 342 | LOGV("Start: %p\n", activity); 343 | android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); 344 | } 345 | 346 | static void onResume(ANativeActivity* activity) { 347 | LOGV("Resume: %p\n", activity); 348 | android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); 349 | } 350 | 351 | static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { 352 | struct android_app* android_app = (struct android_app*)activity->instance; 353 | void* savedState = NULL; 354 | 355 | LOGV("SaveInstanceState: %p\n", activity); 356 | pthread_mutex_lock(&android_app->mutex); 357 | android_app->stateSaved = 0; 358 | android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); 359 | while (!android_app->stateSaved) { 360 | pthread_cond_wait(&android_app->cond, &android_app->mutex); 361 | } 362 | 363 | if (android_app->savedState != NULL) { 364 | savedState = android_app->savedState; 365 | *outLen = android_app->savedStateSize; 366 | android_app->savedState = NULL; 367 | android_app->savedStateSize = 0; 368 | } 369 | 370 | pthread_mutex_unlock(&android_app->mutex); 371 | 372 | return savedState; 373 | } 374 | 375 | static void onPause(ANativeActivity* activity) { 376 | LOGV("Pause: %p\n", activity); 377 | android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); 378 | } 379 | 380 | static void onStop(ANativeActivity* activity) { 381 | LOGV("Stop: %p\n", activity); 382 | android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); 383 | } 384 | 385 | static void onConfigurationChanged(ANativeActivity* activity) { 386 | struct android_app* android_app = (struct android_app*)activity->instance; 387 | LOGV("ConfigurationChanged: %p\n", activity); 388 | android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); 389 | } 390 | 391 | static void onLowMemory(ANativeActivity* activity) { 392 | struct android_app* android_app = (struct android_app*)activity->instance; 393 | LOGV("LowMemory: %p\n", activity); 394 | android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); 395 | } 396 | 397 | static void onWindowFocusChanged(ANativeActivity* activity, int focused) { 398 | LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); 399 | android_app_write_cmd((struct android_app*)activity->instance, 400 | focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); 401 | } 402 | 403 | static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { 404 | LOGV("NativeWindowCreated: %p -- %p\n", activity, window); 405 | android_app_set_window((struct android_app*)activity->instance, window); 406 | } 407 | 408 | static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { 409 | LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); 410 | android_app_set_window((struct android_app*)activity->instance, NULL); 411 | } 412 | 413 | static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { 414 | LOGV("InputQueueCreated: %p -- %p\n", activity, queue); 415 | android_app_set_input((struct android_app*)activity->instance, queue); 416 | } 417 | 418 | static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { 419 | LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); 420 | android_app_set_input((struct android_app*)activity->instance, NULL); 421 | } 422 | 423 | void ANativeActivity_onCreate(ANativeActivity* activity, 424 | void* savedState, size_t savedStateSize) { 425 | LOGV("Creating: %p\n", activity); 426 | activity->callbacks->onDestroy = onDestroy; 427 | activity->callbacks->onStart = onStart; 428 | activity->callbacks->onResume = onResume; 429 | activity->callbacks->onSaveInstanceState = onSaveInstanceState; 430 | activity->callbacks->onPause = onPause; 431 | activity->callbacks->onStop = onStop; 432 | activity->callbacks->onConfigurationChanged = onConfigurationChanged; 433 | activity->callbacks->onLowMemory = onLowMemory; 434 | activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; 435 | activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; 436 | activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; 437 | activity->callbacks->onInputQueueCreated = onInputQueueCreated; 438 | activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; 439 | 440 | activity->instance = android_app_create(activity, savedState, savedStateSize); 441 | } 442 | -------------------------------------------------------------------------------- /Application/src/main/cpp/glue/android_native_app_glue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef _ANDROID_NATIVE_APP_GLUE_H 19 | #define _ANDROID_NATIVE_APP_GLUE_H 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /** 34 | * The native activity interface provided by 35 | * is based on a set of application-provided callbacks that will be called 36 | * by the Activity's main thread when certain events occur. 37 | * 38 | * This means that each one of this callbacks _should_ _not_ block, or they 39 | * risk having the system force-close the application. This programming 40 | * model is direct, lightweight, but constraining. 41 | * 42 | * The 'android_native_app_glue' static library is used to provide a different 43 | * execution model where the application can implement its own main event 44 | * loop in a different thread instead. Here's how it works: 45 | * 46 | * 1/ The application must provide a function named "android_main()" that 47 | * will be called when the activity is created, in a new thread that is 48 | * distinct from the activity's main thread. 49 | * 50 | * 2/ android_main() receives a pointer to a valid "android_app" structure 51 | * that contains references to other important objects, e.g. the 52 | * ANativeActivity obejct instance the application is running in. 53 | * 54 | * 3/ the "android_app" object holds an ALooper instance that already 55 | * listens to two important things: 56 | * 57 | * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX 58 | * declarations below. 59 | * 60 | * - input events coming from the AInputQueue attached to the activity. 61 | * 62 | * Each of these correspond to an ALooper identifier returned by 63 | * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, 64 | * respectively. 65 | * 66 | * Your application can use the same ALooper to listen to additional 67 | * file-descriptors. They can either be callback based, or with return 68 | * identifiers starting with LOOPER_ID_USER. 69 | * 70 | * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, 71 | * the returned data will point to an android_poll_source structure. You 72 | * can call the process() function on it, and fill in android_app->onAppCmd 73 | * and android_app->onInputEvent to be called for your own processing 74 | * of the event. 75 | * 76 | * Alternatively, you can call the low-level functions to read and process 77 | * the data directly... look at the process_cmd() and process_input() 78 | * implementations in the glue to see how to do this. 79 | * 80 | * See the sample named "native-activity" that comes with the NDK with a 81 | * full usage example. Also look at the JavaDoc of NativeActivity. 82 | */ 83 | 84 | struct android_app; 85 | 86 | /** 87 | * Data associated with an ALooper fd that will be returned as the "outData" 88 | * when that source has data ready. 89 | */ 90 | struct android_poll_source { 91 | // The identifier of this source. May be LOOPER_ID_MAIN or 92 | // LOOPER_ID_INPUT. 93 | int32_t id; 94 | 95 | // The android_app this ident is associated with. 96 | struct android_app* app; 97 | 98 | // Function to call to perform the standard processing of data from 99 | // this source. 100 | void (*process)(struct android_app* app, struct android_poll_source* source); 101 | }; 102 | 103 | /** 104 | * This is the interface for the standard glue code of a threaded 105 | * application. In this model, the application's code is running 106 | * in its own thread separate from the main thread of the process. 107 | * It is not required that this thread be associated with the Java 108 | * VM, although it will need to be in order to make JNI calls any 109 | * Java objects. 110 | */ 111 | struct android_app { 112 | // The application can place a pointer to its own state object 113 | // here if it likes. 114 | void* userData; 115 | 116 | // Fill this in with the function to process windowEntry app commands (APP_CMD_*) 117 | void (*onAppCmd)(struct android_app* app, int32_t cmd); 118 | 119 | // Fill this in with the function to process input events. At this point 120 | // the event has already been pre-dispatched, and it will be finished upon 121 | // return. Return 1 if you have handled the event, 0 for any default 122 | // dispatching. 123 | int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); 124 | 125 | // The ANativeActivity object instance that this app is running in. 126 | ANativeActivity* activity; 127 | 128 | // The current configuration the app is running in. 129 | AConfiguration* config; 130 | 131 | // This is the last instance's saved state, as provided at creation time. 132 | // It is NULL if there was no state. You can use this as you need; the 133 | // memory will remain around until you call android_app_exec_cmd() for 134 | // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. 135 | // These variables should only be changed when processing a APP_CMD_SAVE_STATE, 136 | // at which point they will be initialized to NULL and you can malloc your 137 | // state and place the information here. In that case the memory will be 138 | // freed for you later. 139 | void* savedState; 140 | size_t savedStateSize; 141 | 142 | // The ALooper associated with the app's thread. 143 | ALooper* looper; 144 | 145 | // When non-NULL, this is the input queue from which the app will 146 | // receive user input events. 147 | AInputQueue* inputQueue; 148 | 149 | // When non-NULL, this is the window surface that the app can draw in. 150 | ANativeWindow* window; 151 | 152 | // Current content rectangle of the window; this is the area where the 153 | // window's content should be placed to be seen by the user. 154 | ARect contentRect; 155 | 156 | // Current state of the app's activity. May be either APP_CMD_START, 157 | // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. 158 | int activityState; 159 | 160 | // This is non-zero when the application's NativeActivity is being 161 | // destroyed and waiting for the app thread to complete. 162 | int destroyRequested; 163 | 164 | // ------------------------------------------------- 165 | // Below are "private" implementation of the glue code. 166 | 167 | pthread_mutex_t mutex; 168 | pthread_cond_t cond; 169 | 170 | int msgread; 171 | int msgwrite; 172 | 173 | pthread_t thread; 174 | 175 | struct android_poll_source cmdPollSource; 176 | struct android_poll_source inputPollSource; 177 | 178 | int running; 179 | int stateSaved; 180 | int destroyed; 181 | int redrawNeeded; 182 | AInputQueue* pendingInputQueue; 183 | ANativeWindow* pendingWindow; 184 | ARect pendingContentRect; 185 | }; 186 | 187 | enum { 188 | /** 189 | * Looper data ID of commands coming from the app's main thread, which 190 | * is returned as an identifier from ALooper_pollOnce(). The data for this 191 | * identifier is a pointer to an android_poll_source structure. 192 | * These can be retrieved and processed with android_app_read_cmd() 193 | * and android_app_exec_cmd(). 194 | */ 195 | LOOPER_ID_MAIN = 1, 196 | 197 | /** 198 | * Looper data ID of events coming from the AInputQueue of the 199 | * application's window, which is returned as an identifier from 200 | * ALooper_pollOnce(). The data for this identifier is a pointer to an 201 | * android_poll_source structure. These can be read via the inputQueue 202 | * object of android_app. 203 | */ 204 | LOOPER_ID_INPUT = 2, 205 | 206 | /** 207 | * Start of user-defined ALooper identifiers. 208 | */ 209 | LOOPER_ID_USER = 3, 210 | }; 211 | 212 | enum { 213 | /** 214 | * Command from main thread: the AInputQueue has changed. Upon processing 215 | * this command, android_app->inputQueue will be updated to the new queue 216 | * (or NULL). 217 | */ 218 | APP_CMD_INPUT_CHANGED, 219 | 220 | /** 221 | * Command from main thread: a new ANativeWindow is ready for use. Upon 222 | * receiving this command, android_app->window will contain the new window 223 | * surface. 224 | */ 225 | APP_CMD_INIT_WINDOW, 226 | 227 | /** 228 | * Command from main thread: the existing ANativeWindow needs to be 229 | * terminated. Upon receiving this command, android_app->window still 230 | * contains the existing window; after calling android_app_exec_cmd 231 | * it will be set to NULL. 232 | */ 233 | APP_CMD_TERM_WINDOW, 234 | 235 | /** 236 | * Command from main thread: the current ANativeWindow has been resized. 237 | * Please redraw with its new size. 238 | */ 239 | APP_CMD_WINDOW_RESIZED, 240 | 241 | /** 242 | * Command from main thread: the system needs that the current ANativeWindow 243 | * be redrawn. You should redraw the window before handing this to 244 | * android_app_exec_cmd() in order to avoid transient drawing glitches. 245 | */ 246 | APP_CMD_WINDOW_REDRAW_NEEDED, 247 | 248 | /** 249 | * Command from main thread: the content area of the window has changed, 250 | * such as from the soft input window being shown or hidden. You can 251 | * find the new content rect in android_app::contentRect. 252 | */ 253 | APP_CMD_CONTENT_RECT_CHANGED, 254 | 255 | /** 256 | * Command from main thread: the app's activity window has gained 257 | * input focus. 258 | */ 259 | APP_CMD_GAINED_FOCUS, 260 | 261 | /** 262 | * Command from main thread: the app's activity window has lost 263 | * input focus. 264 | */ 265 | APP_CMD_LOST_FOCUS, 266 | 267 | /** 268 | * Command from main thread: the current device configuration has changed. 269 | */ 270 | APP_CMD_CONFIG_CHANGED, 271 | 272 | /** 273 | * Command from main thread: the system is running low on memory. 274 | * Try to reduce your memory use. 275 | */ 276 | APP_CMD_LOW_MEMORY, 277 | 278 | /** 279 | * Command from main thread: the app's activity has been started. 280 | */ 281 | APP_CMD_START, 282 | 283 | /** 284 | * Command from main thread: the app's activity has been resumed. 285 | */ 286 | APP_CMD_RESUME, 287 | 288 | /** 289 | * Command from main thread: the app should generate a new saved state 290 | * for itself, to restore from later if needed. If you have saved state, 291 | * allocate it with malloc and place it in android_app.savedState with 292 | * the size in android_app.savedStateSize. The will be freed for you 293 | * later. 294 | */ 295 | APP_CMD_SAVE_STATE, 296 | 297 | /** 298 | * Command from main thread: the app's activity has been paused. 299 | */ 300 | APP_CMD_PAUSE, 301 | 302 | /** 303 | * Command from main thread: the app's activity has been stopped. 304 | */ 305 | APP_CMD_STOP, 306 | 307 | /** 308 | * Command from main thread: the app's activity is being destroyed, 309 | * and waiting for the app thread to clean up and exit before proceeding. 310 | */ 311 | APP_CMD_DESTROY, 312 | }; 313 | 314 | /** 315 | * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next 316 | * app command message. 317 | */ 318 | int8_t android_app_read_cmd(struct android_app* android_app); 319 | 320 | /** 321 | * Call with the command returned by android_app_read_cmd() to do the 322 | * initial pre-processing of the given command. You can perform your own 323 | * actions for the command after calling this function. 324 | */ 325 | void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); 326 | 327 | /** 328 | * Call with the command returned by android_app_read_cmd() to do the 329 | * final post-processing of the given command. You must have done your own 330 | * actions for the command before calling this function. 331 | */ 332 | void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); 333 | 334 | /** 335 | * Dummy function you can call to ensure glue code isn't stripped. 336 | */ 337 | void app_dummy(); 338 | 339 | void ANativeActivity_onCreate(ANativeActivity *activity, void * savedState, size_t savedStateSize); 340 | 341 | /** 342 | * This is the function that application code must implement, representing 343 | * the main entry to the app. 344 | */ 345 | extern void android_main(struct android_app* app); 346 | 347 | #ifdef __cplusplus 348 | } 349 | #endif 350 | 351 | #endif /* _ANDROID_NATIVE_APP_GLUE_H */ 352 | -------------------------------------------------------------------------------- /Application/src/main/cpp/util/AndroidUtil.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/5/23. 3 | // 4 | 5 | #include "EGLUtil.h" 6 | #include "../glue/android_native_app_glue.h" 7 | 8 | /** 9 | * 获取当前时间 10 | * @return 11 | */ 12 | static float getCurrentTime() { 13 | struct timespec clockRealTime; 14 | clock_gettime(CLOCK_MONOTONIC, &clockRealTime); 15 | double timeInSeconds = clockRealTime.tv_sec + (double)clockRealTime.tv_nsec / 1e9; 16 | return (float) timeInSeconds; 17 | } 18 | 19 | /** 20 | * 处理命令 21 | * @param androidApp 22 | * @param cmd 23 | */ 24 | static void handleCommand(struct android_app* androidApp, int32_t cmd) { 25 | 26 | ESContext *esContext = (ESContext*)androidApp->userData; 27 | switch (cmd) { 28 | 29 | // 输出改变 30 | case APP_CMD_INPUT_CHANGED: 31 | break; 32 | 33 | // 初始化窗口 34 | case APP_CMD_INIT_WINDOW: 35 | esContext->eglNativeDisplay = EGL_DEFAULT_DISPLAY; 36 | esContext->eglNativeWindow = androidApp->window; 37 | // 如果没有main入口,则推出程序 38 | if (onCreate(esContext) != GL_TRUE) { 39 | exit(0); 40 | } 41 | break; 42 | 43 | // 关闭窗口 44 | case APP_CMD_TERM_WINDOW: 45 | // if (esContext->accelerometerSensor != nullptr) { 46 | // ASensorEventQueue_disableSensor(esContext->sensorEventQueue, 47 | // esContext->accelerometerSensor); 48 | // } 49 | // 如果定义了关闭窗口函数,则调用该函数处理 50 | if (esContext->shutdownFunc != nullptr) { 51 | esContext->shutdownFunc(esContext); 52 | } 53 | // 如果用户数据不为空,则需要清空该数据释放内存 54 | if (esContext->userData != nullptr) { 55 | free(esContext->userData); 56 | } 57 | // 清空引用的上下文数据,防止内存泄漏 58 | memset(esContext, 0, sizeof(ESContext)); 59 | break; 60 | 61 | // 窗口大小改变 62 | case APP_CMD_WINDOW_RESIZED: 63 | if (esContext->updateFunc != nullptr) { 64 | esContext->onWindowResize(esContext, esContext->width, esContext->height); 65 | } 66 | break; 67 | 68 | // 窗口需要重绘 69 | case APP_CMD_WINDOW_REDRAW_NEEDED: 70 | if (esContext->onRedrawIfNeeded != nullptr) { 71 | esContext->onRedrawIfNeeded(esContext); 72 | } 73 | break; 74 | 75 | // 窗口内容区域发生改变 76 | case APP_CMD_CONTENT_RECT_CHANGED: 77 | if (esContext->onWindowContentChanged != nullptr) { 78 | esContext->onWindowContentChanged(esContext); 79 | } 80 | break; 81 | 82 | // 获取焦点 83 | case APP_CMD_GAINED_FOCUS: 84 | // if (esContext->accelerometerSensor != nullptr) { 85 | // // 启用传感器 86 | // ASensorEventQueue_enableSensor(esContext->sensorEventQueue, 87 | // esContext->accelerometerSensor); 88 | // // 设置获取事件的频率 89 | // ASensorEventQueue_setEventRate(esContext->sensorEventQueue, 90 | // esContext->accelerometerSensor, 91 | // (1000L / 60) * 1000); 92 | // } 93 | if (esContext->onWindowFocusChanged != nullptr) { 94 | esContext->onWindowFocusChanged(esContext, true); 95 | } 96 | break; 97 | 98 | // 失去焦点 99 | case APP_CMD_LOST_FOCUS: 100 | // // 失去焦点时需要关闭加速度传感器 101 | // if (esContext->accelerometerSensor != nullptr) { 102 | // ASensorEventQueue_disableSensor(esContext->sensorEventQueue, 103 | // esContext->accelerometerSensor); 104 | // } 105 | // 停止动画 106 | esContext->animate = false; 107 | 108 | if (esContext->onWindowFocusChanged != nullptr) { 109 | esContext->onWindowFocusChanged(esContext, false); 110 | } 111 | break; 112 | 113 | // 当前设备配置发生改变 114 | case APP_CMD_CONFIG_CHANGED: 115 | if (esContext->onConfigurationChanged != nullptr) { 116 | esContext->onConfigurationChanged(esContext); 117 | } 118 | break; 119 | 120 | // 低内存时 121 | case APP_CMD_LOW_MEMORY: 122 | if (esContext->onLowMemory != nullptr) { 123 | esContext->onLowMemory(esContext); 124 | } 125 | break; 126 | 127 | // 对应onStrart 128 | case APP_CMD_START: 129 | if (esContext->onStart != nullptr) { 130 | esContext->onStart(esContext); 131 | } 132 | break; 133 | 134 | // 对应onResume 135 | case APP_CMD_RESUME: 136 | if (esContext->onResume != nullptr) { 137 | esContext->onResume(esContext); 138 | } 139 | break; 140 | 141 | // 保存APP的状态,对应onSaveInstanceState 142 | case APP_CMD_SAVE_STATE: 143 | if (esContext->onSavedInstance != nullptr) { 144 | esContext->onSavedInstance(esContext, androidApp); 145 | } 146 | break; 147 | 148 | // 对应onPause 149 | case APP_CMD_PAUSE: 150 | if (esContext->onPause != nullptr) { 151 | esContext->onPause(esContext); 152 | } 153 | break; 154 | 155 | // 对应onStop 156 | case APP_CMD_STOP: 157 | if (esContext->onStop != nullptr) { 158 | esContext->onStop(esContext); 159 | } 160 | break; 161 | 162 | // 对应onDestory 163 | case APP_CMD_DESTROY: 164 | if (esContext->onDestroy != nullptr) { 165 | esContext->onDestroy(esContext); 166 | } 167 | // 如果用户数据不为空,则需要清空该数据释放内存 168 | if (esContext->userData != nullptr) { 169 | free(esContext->userData); 170 | } 171 | // 清空引用的上下文数据,防止内存泄漏 172 | memset(esContext, 0, sizeof(ESContext)); 173 | break; 174 | } 175 | } 176 | 177 | /** 178 | * 处理输出事件 179 | * @param androidApp 180 | * @param event 181 | * @return 182 | */ 183 | static int32_t handleInput(struct android_app* app, AInputEvent* event) { 184 | ESContext* esContext = (ESContext *)app->userData; 185 | switch(AInputEvent_getType(event)) { 186 | // 触摸事件 187 | case AINPUT_EVENT_TYPE_MOTION: 188 | if (esContext != nullptr && esContext->onTouchEvent != nullptr) { 189 | return esContext->onTouchEvent(esContext, event); 190 | } 191 | break; 192 | 193 | // 按键事件 194 | case AINPUT_EVENT_TYPE_KEY: 195 | if (esContext != nullptr && esContext->onKeyEvent != nullptr) { 196 | return esContext->onKeyEvent(esContext, event); 197 | } 198 | break; 199 | } 200 | return 0; 201 | } 202 | 203 | /** 204 | * 胶水层暴露出来的app入口程序,相当于Activity中的onCreate方法 205 | * @param app 206 | */ 207 | void android_main(struct android_app* app) { 208 | 209 | ESContext esContext; 210 | float lastTime; 211 | app_dummy(); 212 | memset(&esContext, 0, sizeof(ESContext)); 213 | esContext.activity = app->activity; 214 | // 处理命令 215 | app->onAppCmd = handleCommand; 216 | // 处理输入事件 217 | app->onInputEvent = handleInput; 218 | // 绑定用户数据 219 | app->userData = &esContext; 220 | // 准备传感器管理器 221 | esContext.sensorManager = ASensorManager_getInstance(); 222 | // 获得默认的加速度传感器 223 | esContext.accelerometerSensor = ASensorManager_getDefaultSensor(esContext.sensorManager, 224 | ASENSOR_TYPE_ACCELEROMETER); 225 | // 准备传感器事件队列 226 | esContext.sensorEventQueue = ASensorManager_createEventQueue(esContext.sensorManager, 227 | app->looper, LOOPER_ID_USER, 228 | nullptr, nullptr); 229 | // 获取暂存状态数据 230 | if (app->savedState != nullptr) { 231 | esContext.savedState = app->savedState; 232 | } 233 | 234 | // 获取当前配置信息 235 | if (app->config != nullptr) { 236 | esContext.config = app->config; 237 | } 238 | 239 | // 获取当前时间 240 | lastTime = getCurrentTime(); 241 | 242 | while (true) { 243 | int events; 244 | int ident; 245 | struct android_poll_source* source; 246 | // 如果消息队列中存在消息,则将消息取出来处理 247 | while((ident = ALooper_pollAll(0, nullptr, &events, (void**) &source)) >= 0) { 248 | if (source != nullptr) { 249 | source->process(app, source); 250 | } 251 | 252 | //如果Looper ID是用户的ID,则可以使用监听传感器事件队列 253 | // if (ident == LOOPER_ID_USER) { 254 | // if (esContext.accelerometerSensor != nullptr) { 255 | // ASensorEvent event; 256 | // // 取出加速度传感器的值 257 | // while (ASensorEventQueue_getEvents(esContext.sensorEventQueue, &event, 1) > 0) { 258 | // ALOGI("accelometer: x= %f, y=%f, z=%f", 259 | // event.acceleration.x, 260 | // event.acceleration.y, 261 | // event.acceleration.z); 262 | // } 263 | // } 264 | // } 265 | 266 | // 如果请求退出app 267 | if (app->destroyRequested != 0) { 268 | // 推出应用时需要关掉EGL 269 | if (esContext.shutdownFunc != nullptr) { 270 | esContext.shutdownFunc(&esContext); 271 | } 272 | return; 273 | } 274 | } 275 | 276 | // 等待native window 的创建 277 | if (esContext.eglNativeWindow == nullptr) { 278 | continue; 279 | } 280 | 281 | // 是否允许动画 282 | if (esContext.animate && esContext.onAnimate != nullptr) { 283 | esContext.onAnimate(&esContext); 284 | } 285 | 286 | // app请求刷新函数不为空,则刷新数据 287 | if (esContext.updateFunc != nullptr) { 288 | float curTime = getCurrentTime(); 289 | float deltaTime = curTime - lastTime; 290 | lastTime = curTime; 291 | esContext.updateFunc(&esContext, deltaTime); 292 | } 293 | 294 | // 绘制函数不为空,调用绘制函数,并且采用双缓冲方式绘制显示 295 | if (esContext.drawFunc != nullptr) { 296 | esContext.drawFunc(&esContext); 297 | // 双缓冲方式绘制,避免闪屏现象 298 | eglSwapBuffers(esContext.eglDisplay, esContext.eglSurface); 299 | } 300 | } 301 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/util/EGLUtil.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/5/23. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "EGLUtil.h" 10 | 11 | #define PI 3.1415926535897932384626433832795f 12 | 13 | // #pragma pack指定内存对齐方式 14 | #pragma pack(push,x1) 15 | // 这里表示按照1字节对齐方式对齐 16 | #pragma pack(1) 17 | // TGA图片格式,RLE算法 18 | typedef struct { 19 | unsigned char IdSize, // 图像信息字段长度, 范围 0 ~ 255, 0表示没有图像的信息字段 20 | MapType, // 颜色表类型,0表示没有颜色。 21 | ImageType; // 图像类型码,2表示非压缩格式,10表示压缩RGB格式,后面的图像数据采用RLE压缩 22 | 23 | unsigned short PaletteStart, // 颜色表首地址,颜色表头的入口,整形(低位 —— 高位) 24 | PaletteSize; // 颜色表的长度,整形(低位 —— 高位) 25 | unsigned char PaletteEntryDepth; // 颜色表的位数,16表示16位TGA,24表示24位TGA,32表示32位TGA 26 | 27 | unsigned short X, // 图像X坐标起始位置,左下角的X坐标 28 | Y, // 图像Y坐标起始位置,左下角的Y坐标 29 | Width, // 图像的宽度 30 | Height; // 图像的高度 31 | unsigned char ColorDepth, // 图像没像素存储占用位数 32 | Descriptor; // 图像描述符字节 33 | 34 | } TGA_HEADER; 35 | #pragma pack(pop,x1) 36 | 37 | /** 38 | * 查询可渲染版本类型 39 | * @param eglDisplay 40 | * @return 41 | */ 42 | GLint getContextRenderableType(EGLDisplay eglDisplay) { 43 | #ifdef EGL_KHR_create_context 44 | const char *extensions = eglQueryString(eglDisplay, EGL_EXTENSIONS); 45 | // 查询字符串并判断是否包含在extension 字符串中 46 | if (extensions != nullptr && strstr(extensions, "EGL_KHR_create_context")) { 47 | return EGL_OPENGL_ES3_BIT_KHR; 48 | } 49 | #endif 50 | return EGL_OPENGL_ES2_BIT; 51 | } 52 | 53 | /** 54 | * 创建窗口 55 | * @param esContext 上下文 56 | * @param title 标题 57 | * @param width 宽 58 | * @param height 高 59 | * @param flags 指定窗口缓冲区特性: 60 | * EGL_WINDOW_RGB, 基于RGB的颜色缓冲区 61 | * EGL_WINDOW_ALPHA, 分配目标alpha缓冲区 62 | * EGL_WINDOW_DEPTH, 分配深度缓冲区 63 | * EGGL_WINDOW_STENCIL, 分配模板缓冲区 64 | * EGL_WINDOW_MULTISAMPLE, 分配多重采样缓冲区 65 | * 66 | * @return 创建成功与否的标志 67 | */ 68 | GLboolean createWindow(ESContext* esContext, 69 | const char* title, 70 | GLint width, 71 | GLint height, 72 | GLuint flags) { 73 | // 1、初始化EGL 74 | EGLConfig config; 75 | EGLint majorVersion; 76 | EGLint minorVersion; 77 | EGLint contextAttribs[] = { 78 | EGL_CONTEXT_CLIENT_VERSION, 79 | 3, 80 | EGL_NONE 81 | }; 82 | 83 | // 获取宽和高 84 | esContext->width = ANativeWindow_getWidth(esContext->eglNativeWindow); 85 | esContext->height = ANativeWindow_getHeight(esContext->eglNativeWindow); 86 | 87 | // 打开与EGL显示服务器的连接,默认为EGL_DEFAULT_DISPLAY 88 | esContext->eglDisplay = eglGetDisplay(esContext->eglNativeDisplay); 89 | 90 | // 如果显示连接不可用,则返回EGL_NO_DISPLAY标志,此时无法创建窗口 91 | if (esContext->eglDisplay == EGL_NO_DISPLAY) { 92 | return GL_FALSE; 93 | } 94 | 95 | // 初始化egl并回传版本号 96 | if (!eglInitialize(esContext->eglDisplay, &majorVersion, &minorVersion)) { 97 | return GL_FALSE; 98 | } 99 | 100 | // 2.确定可用表面配置 101 | EGLint numConfigs = 0; 102 | EGLint attribList[] = { 103 | EGL_RED_SIZE, 5, 104 | EGL_GREEN_SIZE, 6, 105 | EGL_BLUE_SIZE, 5, 106 | EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE, 107 | EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE, 108 | EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE, 109 | EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0, 110 | EGL_RENDERABLE_TYPE, getContextRenderableType(esContext->eglDisplay), 111 | EGL_NONE 112 | }; 113 | 114 | // 选择Config 115 | if (!eglChooseConfig(esContext->eglDisplay, attribList, &config, 1, &numConfigs)) { 116 | return GL_FALSE; 117 | } 118 | if (numConfigs < 1) { 119 | return GL_FALSE; 120 | } 121 | // 3.查询EGLConfig 122 | // Android需要获取EGL_NATIVE_VISUAL_ID的值并将其放如ANativeWindow_setBuffersGeometry函数中 123 | EGLint format = 0; 124 | eglGetConfigAttrib(esContext->eglDisplay, config, EGL_NATIVE_VISUAL_ID, &format); 125 | ANativeWindow_setBuffersGeometry(esContext->eglNativeWindow, 0, 0, format); 126 | 127 | // 4.创建屏幕上的渲染区域:EGL窗口 128 | // 创建Window surface 129 | esContext->eglSurface = eglCreateWindowSurface(esContext->eglDisplay, config, 130 | esContext->eglNativeWindow, nullptr); 131 | // 判断是否创建成功 132 | if (esContext->eglSurface == EGL_NO_SURFACE) { 133 | return GL_FALSE; 134 | } 135 | 136 | // 5.创建上下文 137 | esContext->eglContext = eglCreateContext(esContext->eglDisplay, config, 138 | EGL_NO_CONTEXT, contextAttribs); 139 | 140 | // 判断上下文是否创建成功 141 | if (esContext->eglContext == EGL_NO_CONTEXT) { 142 | return GL_FALSE; 143 | } 144 | 145 | // 指定某个EGLContext为当前上下文 146 | if (!eglMakeCurrent(esContext->eglDisplay, esContext->eglSurface, 147 | esContext->eglSurface, esContext->eglContext)) { 148 | return GL_FALSE; 149 | } 150 | 151 | return GL_TRUE; 152 | } 153 | 154 | void registerDrawFunc(ESContext *esContext, void (drawFunc)(ESContext *)) { 155 | esContext->drawFunc = drawFunc; 156 | } 157 | 158 | void registerShutdownFunc(ESContext *esContext, void (*shutdownFunc)(ESContext *)) { 159 | esContext->shutdownFunc = shutdownFunc; 160 | } 161 | 162 | void registerUpdateFunc(ESContext *esContext, void(*updateFunc)(ESContext *, float)) { 163 | esContext->updateFunc = updateFunc; 164 | } 165 | 166 | 167 | 168 | /** 169 | * 读取assets文件夹中的文件 170 | * @param file assets目录下的文件名(包含路径) 171 | * @param manager AssetManager管理器 172 | * @return 返回字符串 173 | */ 174 | char* readAssetFile(const char* file, AAssetManager* manager) { 175 | AAsset* asset = nullptr; 176 | char* buffer = nullptr; 177 | off_t size = -1; 178 | if (!manager) { 179 | ALOGE("AssetManager is null!"); 180 | return nullptr; 181 | } 182 | // 使用asset文件管理器打开文件 183 | asset = AAssetManager_open(manager, file, AASSET_MODE_UNKNOWN); 184 | // 获取文件的长度 185 | size = AAsset_getLength(asset); 186 | // 如果文件长度小于1,则表示文件为空,直接返回空字符串 187 | if (size < 1) { 188 | ALOGE("file is null!"); 189 | return nullptr; 190 | } 191 | 192 | // 分配内存,最后需要添加一个字符串结尾地址'\0', (C/C++中char数组与字符串的区别) 193 | buffer = (char *) malloc(size + 1); 194 | buffer[size] = '\0'; 195 | 196 | // 从文件中读取内容,完成后需要关闭文件 197 | AAsset_read(asset, buffer, size); 198 | AAsset_close(asset); 199 | // 返回字符串 200 | return buffer; 201 | } 202 | 203 | /** 204 | * 打开文件 205 | * @param context 上下文 206 | * @param fileName 文件名 207 | * @return 返回AAsset 208 | */ 209 | static AAsset* fileOpen(void *context, const char *fileName) { 210 | AAsset* file = nullptr; 211 | if (context != nullptr) { 212 | AAssetManager *manager = (AAssetManager *)context; 213 | file = AAssetManager_open(manager, fileName, AASSET_MODE_BUFFER); 214 | } 215 | return file; 216 | } 217 | 218 | /** 219 | * 关闭文件 220 | * @param file 221 | */ 222 | static void fileClose(AAsset *file) { 223 | if (file != nullptr) { 224 | AAsset_close(file); 225 | } 226 | } 227 | 228 | /** 229 | * 读取文件 230 | * @param file 231 | * @param bytesToRead 232 | * @param buffer 233 | * @return 234 | */ 235 | static int fileRead(AAsset *file, int bytesToRead, void *buffer) { 236 | int bytes = 0; 237 | if (file != nullptr) { 238 | bytes = AAsset_read(file, buffer, bytesToRead); 239 | } 240 | return bytes; 241 | } 242 | 243 | /** 244 | * 加载一个 8bit,24bit或32bit TGA图片 245 | * @param context 246 | * @param fileName 247 | * @param width 248 | * @param height 249 | * @return 250 | */ 251 | char* loadTGA(void* context, const char *fileName, int *width, int *height) { 252 | char* buffer; 253 | AAsset* file; 254 | TGA_HEADER header; 255 | int bytes; 256 | file = fileOpen(context, fileName); 257 | if (file == nullptr) { 258 | ALOGE("fialed to load: {%s}\n", fileName); 259 | return nullptr; 260 | } 261 | 262 | bytes = fileRead(file, sizeof(TGA_HEADER), &header); 263 | *width = header.Width; 264 | *height = header.Height; 265 | // 266 | if (header.ColorDepth == 8 || header.ColorDepth == 24 || header.ColorDepth == 32) { 267 | int bytesToRead = sizeof(char) * (*width) * (*height) * header.ColorDepth / 8; 268 | 269 | buffer = (char *)malloc(bytesToRead); 270 | if (buffer) { 271 | bytes = fileRead(file, bytesToRead, buffer); 272 | fileClose(file); 273 | return buffer; 274 | } 275 | } 276 | 277 | return nullptr; 278 | } 279 | 280 | GLuint loadShader(GLenum type, const char* shaderSrc) { 281 | GLuint shader; 282 | GLint compiled; 283 | // 创建shader 284 | shader = glCreateShader(type); 285 | if (shader == 0) { 286 | return 0; 287 | } 288 | // 加载着色器的源码 289 | glShaderSource(shader, 1, &shaderSrc, nullptr); 290 | 291 | // 编译源码 292 | glCompileShader(shader); 293 | 294 | // 检查编译状态 295 | glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 296 | 297 | if (!compiled) { 298 | GLint infoLen = 0; 299 | // 查询日志的长度判断是否有日志产生 300 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 301 | 302 | if (infoLen > 1) { 303 | // 分配一个足以存储日志信息的字符串 304 | char* infoLog = (char *) malloc(sizeof(char) * infoLen); 305 | // 检索日志信息 306 | glGetShaderInfoLog(shader, infoLen, nullptr, infoLog); 307 | ALOGE("Error compiling shader:\n%s\n", infoLog); 308 | // 使用完成后需要释放字符串分配的内存 309 | free(infoLog); 310 | } 311 | // 删除编译出错的着色器释放内存 312 | glDeleteShader(shader); 313 | return 0; 314 | } 315 | return shader; 316 | } 317 | 318 | GLuint loadProgram(const char* vertexShader, const char* fragShader) { 319 | GLuint vertex; 320 | GLuint fragment; 321 | GLuint program; 322 | GLint linked; 323 | 324 | //加载顶点shader 325 | vertex = loadShader(GL_VERTEX_SHADER, vertexShader); 326 | if (vertex == 0) { 327 | return 0; 328 | } 329 | // 加载片元着色器 330 | fragment = loadShader(GL_FRAGMENT_SHADER, fragShader); 331 | if (fragment == 0) { 332 | glDeleteShader(vertex); 333 | return 0; 334 | } 335 | // 创建program 336 | program = glCreateProgram(); 337 | if (program == 0) { 338 | glDeleteShader(vertex); 339 | glDeleteShader(fragment); 340 | return 0; 341 | } 342 | // 绑定shader 343 | glAttachShader(program, vertex); 344 | glAttachShader(program, fragment); 345 | 346 | // 链接program程序 347 | glLinkProgram(program); 348 | // 检查链接状态 349 | glGetProgramiv(program, GL_LINK_STATUS, &linked); 350 | if (!linked) { 351 | GLint infoLen = 0; 352 | // 检查日志信息长度 353 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen); 354 | if (infoLen > 1) { 355 | // 分配一个足以存储日志信息的字符串 356 | char* infoLog = (char *) malloc(sizeof(char) * infoLen); 357 | // 检索日志信息 358 | glGetProgramInfoLog(program, infoLen, nullptr, infoLog); 359 | ALOGE("Error linking program:\n%s\n", infoLog); 360 | // 使用完成后需要释放字符串分配的内存 361 | free(infoLog); 362 | } 363 | // 删除着色器释放内存 364 | glDeleteShader(vertex); 365 | glDeleteShader(fragment); 366 | glDeleteProgram(program); 367 | return 0; 368 | } 369 | // 删除着色器释放内存 370 | glDeleteShader(vertex); 371 | glDeleteShader(fragment); 372 | 373 | return program; 374 | } 375 | 376 | 377 | /** 378 | * 查询活动的统一变量uniform 379 | * @param program 380 | */ 381 | void checkActiveUniform(const GLuint program) { 382 | GLint maxLen; 383 | GLint numUniforms; 384 | char* uniformName; 385 | 386 | glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms); 387 | glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLen); 388 | 389 | uniformName = (char *)malloc(sizeof(char) * maxLen); 390 | 391 | for (int i = 0; i < numUniforms; ++i) { 392 | GLint size; 393 | GLenum type; 394 | GLint location; 395 | 396 | glGetActiveUniform(program, i, maxLen, nullptr, &size, &type, uniformName); 397 | 398 | location = glGetUniformLocation(program, uniformName); 399 | 400 | ALOGD("location:", location); 401 | 402 | switch (type) { 403 | case GL_FLOAT: 404 | ALOGD("type : GL_FLOAT"); 405 | break; 406 | case GL_FLOAT_VEC2: 407 | ALOGD("type : GL_FLOAT_VEC2"); 408 | break; 409 | case GL_FLOAT_VEC3: 410 | ALOGD("type : GL_FLOAT_VEC3"); 411 | break; 412 | case GL_FLOAT_VEC4: 413 | ALOGD("type : GL_FLOAT_VEC4"); 414 | break; 415 | case GL_INT: 416 | ALOGD("type : GL_INT"); 417 | break; 418 | } 419 | } 420 | } 421 | 422 | /** 423 | * 缩放 424 | * @param result 425 | * @param sx 426 | * @param sy 427 | * @param sz 428 | */ 429 | void scale(ESMatrix* result, GLfloat sx, GLfloat sy, GLfloat sz) { 430 | result->m[0][0] *= sx; 431 | result->m[0][1] *= sx; 432 | result->m[0][2] *= sx; 433 | result->m[0][3] *= sx; 434 | 435 | result->m[1][0] *= sy; 436 | result->m[1][1] *= sy; 437 | result->m[1][2] *= sy; 438 | result->m[1][3] *= sy; 439 | 440 | result->m[2][0] *= sz; 441 | result->m[2][1] *= sz; 442 | result->m[2][2] *= sz; 443 | result->m[2][3] *= sz; 444 | } 445 | 446 | /** 447 | * 平移 448 | * @param result 449 | * @param x 450 | * @param y 451 | * @param z 452 | */ 453 | void translate(ESMatrix* result, GLfloat x, GLfloat y, GLfloat z) { 454 | result->m[3][0] += (result->m[0][0] * x + result->m[1][0] * y + result->m[2][0] * z); 455 | result->m[3][1] += (result->m[0][1] * x + result->m[1][1] * y + result->m[2][1] * z); 456 | result->m[3][2] += (result->m[0][2] * x + result->m[1][2] * y + result->m[2][2] * z); 457 | result->m[3][3] += (result->m[0][3] * x + result->m[1][3] * y + result->m[2][3] * z); 458 | } 459 | 460 | 461 | /** 462 | * 旋转 463 | * @param result 464 | * @param angle 465 | * @param x 466 | * @param y 467 | * @param z 468 | */ 469 | void rotate(ESMatrix* result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { 470 | GLfloat sinAngle, cosAngle; 471 | GLfloat mag = sqrtf ( x * x + y * y + z * z ); 472 | 473 | sinAngle = sinf ( angle * PI / 180.0f ); 474 | cosAngle = cosf ( angle * PI / 180.0f ); 475 | 476 | if ( mag > 0.0f ) 477 | { 478 | GLfloat xx, yy, zz, xy, yz, xz, xs, ys, zs; 479 | GLfloat oneMinusCos; 480 | ESMatrix rotMat; 481 | 482 | x /= mag; 483 | y /= mag; 484 | z /= mag; 485 | 486 | xx = x * x; 487 | yy = y * y; 488 | zz = z * z; 489 | xy = x * y; 490 | yz = y * z; 491 | xz = z * x; 492 | xs = x * sinAngle; 493 | ys = y * sinAngle; 494 | zs = z * sinAngle; 495 | oneMinusCos = 1.0f - cosAngle; 496 | 497 | rotMat.m[0][0] = ( oneMinusCos * xx ) + cosAngle; 498 | rotMat.m[0][1] = ( oneMinusCos * xy ) - zs; 499 | rotMat.m[0][2] = ( oneMinusCos * xz ) + ys; 500 | rotMat.m[0][3] = 0.0F; 501 | 502 | rotMat.m[1][0] = ( oneMinusCos * xy ) + zs; 503 | rotMat.m[1][1] = ( oneMinusCos * yy ) + cosAngle; 504 | rotMat.m[1][2] = ( oneMinusCos * yz ) - xs; 505 | rotMat.m[1][3] = 0.0F; 506 | 507 | rotMat.m[2][0] = ( oneMinusCos * xz ) - ys; 508 | rotMat.m[2][1] = ( oneMinusCos * yz ) + xs; 509 | rotMat.m[2][2] = ( oneMinusCos * zz ) + cosAngle; 510 | rotMat.m[2][3] = 0.0F; 511 | 512 | rotMat.m[3][0] = 0.0F; 513 | rotMat.m[3][1] = 0.0F; 514 | rotMat.m[3][2] = 0.0F; 515 | rotMat.m[3][3] = 1.0F; 516 | 517 | matrixMultiply(result, &rotMat, result); 518 | } 519 | } 520 | 521 | 522 | /** 523 | * 视锥体 524 | * @param result 525 | * @param left 526 | * @param top 527 | * @param right 528 | * @param bottom 529 | * @param nearz 530 | * @param farz 531 | */ 532 | void frustum(ESMatrix* result, float left, float top, 533 | float right, float bottom, float nearz, float farz) { 534 | float deltaX = right - left; 535 | float deltaY = top - bottom; 536 | float deltaZ = farz - nearz; 537 | ESMatrix frust; 538 | 539 | if ((nearz <= 0.0f) || (farz <= 0.0f) || (deltaX <= 0.0f) 540 | || (deltaY <= 0.0f) || (deltaZ <= 0.0f)) { 541 | return; 542 | } 543 | 544 | frust.m[0][0] = 2.0f * nearz / deltaX; 545 | frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f; 546 | 547 | frust.m[1][1] = 2.0f * nearz / deltaY; 548 | frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f; 549 | 550 | frust.m[2][0] = ( right + left ) / deltaX; 551 | frust.m[2][1] = ( top + bottom ) / deltaY; 552 | frust.m[2][2] = - ( nearz + farz ) / deltaZ; 553 | frust.m[2][3] = -1.0f; 554 | 555 | frust.m[3][2] = -2.0f * nearz * farz / deltaZ; 556 | frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f; 557 | 558 | matrixMultiply(result, &frust, result); 559 | } 560 | 561 | /** 562 | * 透视 563 | * @param result 564 | * @param fovy 565 | * @param aspect 566 | * @param nearz 567 | * @param farz 568 | */ 569 | void perspective(ESMatrix* result, float fovy, float aspect, float nearz, float farz) { 570 | GLfloat frustW, frustH; 571 | frustH = tanf ( fovy / 360.0f * PI ) * nearz; 572 | frustW = frustH * aspect; 573 | 574 | frustum(result, -frustW, frustW, -frustH, frustH, nearz, farz); 575 | 576 | } 577 | 578 | 579 | /** 580 | * 矩阵相乘 581 | * @param result 582 | * @param srcA 583 | * @param srcB 584 | */ 585 | void matrixMultiply(ESMatrix* result, ESMatrix* srcA, ESMatrix* srcB) { 586 | ESMatrix tmp; 587 | 588 | for (int i = 0; i < 4; ++i) { 589 | tmp.m[i][0] = srcA->m[i][0] * srcB->m[0][0] 590 | + srcA->m[i][1] * srcB->m[1][0] 591 | + srcA->m[i][2] * srcB->m[2][0] 592 | + srcA->m[i][3] * srcB->m[3][0]; 593 | 594 | tmp.m[i][1] = srcA->m[i][0] * srcB->m[0][1] 595 | + srcA->m[i][1] * srcB->m[1][1] 596 | + srcA->m[i][2] * srcB->m[2][1] 597 | + srcA->m[i][3] * srcB->m[3][1]; 598 | 599 | tmp.m[i][2] = srcA->m[i][0] * srcB->m[0][2] 600 | + srcA->m[i][1] * srcB->m[1][2] 601 | + srcA->m[i][2] * srcB->m[2][2] 602 | + srcA->m[i][3] * srcB->m[3][2]; 603 | 604 | tmp.m[i][3] = srcA->m[i][0] * srcB->m[0][3] 605 | + srcA->m[i][1] * srcB->m[1][3] 606 | + srcA->m[i][2] * srcB->m[2][3] 607 | + srcA->m[i][3] * srcB->m[3][3]; 608 | } 609 | 610 | memcpy(result, &tmp, sizeof(ESMatrix)); 611 | } 612 | 613 | /** 614 | * 产生一个单位矩阵 615 | * @param result 616 | */ 617 | void matrixLoadIdentity(ESMatrix* result) { 618 | memset(result, 0x0, sizeof(ESMatrix)); 619 | 620 | result->m[0][0] = 1.0f; 621 | result->m[1][1] = 1.0f; 622 | result->m[2][2] = 1.0f; 623 | result->m[3][3] = 1.0f; 624 | } 625 | 626 | 627 | /** 628 | * 创建球面 629 | * @param numSlices 630 | * @param radius 631 | * @param vertices 632 | * @param normals 633 | * @param texCoords 634 | * @param indices 635 | * @return 636 | */ 637 | int sphere(int numSlices, float radius, 638 | GLfloat **vertices, GLfloat **normals, GLfloat **texCoords, GLuint **indices) { 639 | 640 | int i; 641 | int j; 642 | int numParallels = numSlices / 2; 643 | int numVertices = (numParallels + 1) * (numSlices + 1); 644 | int numIndices = numParallels * numSlices * 6; 645 | float angleStep = (2.0f * ES_PI) / ((float) numSlices); 646 | 647 | if ( vertices != NULL ) { 648 | *vertices = (GLfloat *)malloc(sizeof(GLfloat) * 3 * numVertices); 649 | } 650 | 651 | if ( normals != NULL ) { 652 | *normals = (GLfloat *)malloc( sizeof(GLfloat) * 3 * numVertices); 653 | } 654 | 655 | if ( texCoords != NULL ) { 656 | *texCoords = (GLfloat *)malloc(sizeof(GLfloat) * 2 * numVertices); 657 | } 658 | 659 | if ( indices != NULL) { 660 | *indices = (GLuint *)malloc (sizeof(GLuint) * numIndices); 661 | } 662 | 663 | for (i = 0; i < numParallels + 1; i++) { 664 | for (j = 0; j < numSlices + 1; j++) { 665 | int vertex = (i * (numSlices + 1) + j) * 3; 666 | 667 | if (vertices) { 668 | (*vertices) [vertex + 0] = radius * sinf(angleStep * (float) i) * 669 | sinf (angleStep * (float) j); 670 | (*vertices) [vertex + 1] = radius * cosf(angleStep * (float) i); 671 | (*vertices) [vertex + 2] = radius * sinf(angleStep * (float) i) * 672 | cosf(angleStep * (float)j); 673 | } 674 | 675 | if (normals) { 676 | (*normals) [vertex + 0] = (*vertices) [vertex + 0] / radius; 677 | (*normals) [vertex + 1] = (*vertices) [vertex + 1] / radius; 678 | (*normals) [vertex + 2] = (*vertices) [vertex + 2] / radius; 679 | } 680 | 681 | if (texCoords) { 682 | int texIndex = (i * (numSlices + 1) + j) * 2; 683 | (*texCoords) [texIndex + 0] = (float) j / (float) numSlices; 684 | (*texCoords) [texIndex + 1] = (1.0f - (float) i) / (float) (numParallels - 1); 685 | } 686 | } 687 | } 688 | 689 | if (indices != NULL) { 690 | GLuint *indexBuf = *indices; 691 | 692 | for (i = 0; i < numParallels; i++) { 693 | for (j = 0; j < numSlices; j++) { 694 | *indexBuf++ = (GLuint)(i * (numSlices + 1) + j); 695 | *indexBuf++ = (GLuint)((i + 1) * (numSlices + 1) + j); 696 | *indexBuf++ = (GLuint)((i + 1) * (numSlices + 1) + (j + 1)); 697 | 698 | *indexBuf++ = (GLuint)(i * (numSlices + 1) + j); 699 | *indexBuf++ = (GLuint)((i + 1) * ( numSlices + 1) + (j + 1)); 700 | *indexBuf++ = (GLuint)(i * (numSlices + 1) + (j + 1)); 701 | } 702 | } 703 | } 704 | 705 | return numIndices; 706 | } -------------------------------------------------------------------------------- /Application/src/main/cpp/util/EGLUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cain on 2017/5/23. 3 | // 4 | 5 | #ifndef GLESNATIVESAMPLE_EGLUTIL_H 6 | #define GLESNATIVESAMPLE_EGLUTIL_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | #ifndef LOG_TAG 27 | #define LOG_TAG "NDK-LIB" 28 | #endif 29 | 30 | #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 31 | #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 32 | #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 33 | #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) 34 | 35 | #define ES_PI (3.14159265f) 36 | 37 | #ifdef __cplusplus 38 | 39 | extern "C" { 40 | #endif 41 | 42 | #define ES_WINDOW_RGB 0 43 | #define ES_WINDOW_ALPHA 1 44 | #define ES_WINDOW_DEPTH 2 45 | #define ES_WINDOW_STENCIL 4 46 | #define ES_WINDOW_MULTISAMPLE 8 47 | 48 | #ifndef FALSE 49 | #define FALSE 0 50 | #endif 51 | #ifndef TRUE 52 | #define TRUE 1 53 | #endif 54 | 55 | typedef struct ESContext ESContext; 56 | 57 | /** 58 | * OpenGLES绘制程序 59 | * @param esContext 60 | * @return 61 | */ 62 | extern int onCreate(ESContext *esContext); 63 | 64 | 65 | typedef struct { 66 | GLfloat m[4][4]; 67 | } ESMatrix; 68 | 69 | 70 | // 封装的上下文结构体 71 | struct ESContext { 72 | // 用于存放android_app对象 73 | ANativeActivity* activity; 74 | // 暂存的数据,类似onRestoreInstanceState 返回的值 75 | void* savedState; 76 | // 用户配置 77 | AConfiguration* config; 78 | // 用户数据 79 | void *userData; 80 | // 宽 81 | GLint width; 82 | // 高 83 | GLint height; 84 | // display handle 85 | EGLNativeDisplayType eglNativeDisplay; 86 | // window handle 87 | EGLNativeWindowType eglNativeWindow; 88 | 89 | EGLDisplay eglDisplay; 90 | 91 | EGLContext eglContext; 92 | 93 | EGLSurface eglSurface; 94 | 95 | /// 动画 96 | // 是否允许动画 97 | volatile bool animate; 98 | 99 | /// 传感器 100 | // 传感器管理器 101 | ASensorManager* sensorManager; 102 | // 传感器事件队列 103 | ASensorEventQueue* sensorEventQueue; 104 | // 加速度传感器 105 | const ASensor* accelerometerSensor; 106 | 107 | /// 各个生命周期回调方法 108 | // 绘制回调 109 | void (*drawFunc)(ESContext *esContext); 110 | // 关闭回调 111 | void (*shutdownFunc)(ESContext *esContext); 112 | // 更新回调 113 | void (*updateFunc)(ESContext *esContext, float deltaTime); 114 | // 窗口发生改变时的回调 115 | void (*onWindowResize)(ESContext *esContext, int width, int height); 116 | // 窗口需要重绘制时回调 117 | void (*onRedrawIfNeeded)(ESContext* esContext); 118 | // 窗口内容发生改变时回调 119 | void (*onWindowContentChanged)(ESContext* esContext); 120 | // 焦点发生变化时回调,其中focus表示获取焦点还是失去焦点 121 | void (*onWindowFocusChanged)(ESContext* esContext, bool focus); 122 | // 配置发生变化时回调 123 | void (*onConfigurationChanged)(ESContext* esContext); 124 | // 低内存时回调 125 | void (*onLowMemory)(ESContext* esContext); 126 | // 各个生命周期回调 127 | void (*onStart)(ESContext* esContext); 128 | void (*onResume)(ESContext* esContext); 129 | void (*onSavedInstance)(ESContext* esContext, struct android_app* app); 130 | void (*onPause)(ESContext* esContext); 131 | void (*onStop)(ESContext* esContext); 132 | void (*onDestroy)(ESContext* esContext); 133 | // 事件回调 134 | int32_t (*onTouchEvent)(ESContext* esContext, AInputEvent* event); 135 | int32_t (*onKeyEvent)(ESContext* esContext, AInputEvent* event); 136 | // 动画回调 137 | void (*onAnimate)(ESContext* esContext); 138 | }; 139 | 140 | 141 | /// EGL init 142 | GLboolean createWindow(ESContext* esContext, const char* title, 143 | GLint width, GLint height, GLuint flags); 144 | /// 注册回调函数 145 | void registerDrawFunc(ESContext *esContext, void (drawFunc)(ESContext *)); 146 | 147 | void registerShutdownFunc(ESContext *esContext, void (*shutdownFunc)(ESContext *)); 148 | 149 | void registerUpdateFunc(ESContext *esContext, void(*updateFunc)(ESContext *, float)); 150 | 151 | void registerWindowChange(ESContext *esContext, void(*onWindowResize)(ESContext*, int, int)); 152 | 153 | /** 154 | * 加载TGA图片 155 | * @param context 156 | * @param fileName 157 | * @param width 158 | * @param height 159 | * @return 160 | */ 161 | char* loadTGA(void* context, const char *fileName, int *width, int *height); 162 | 163 | /** 164 | * 读取assets文件夹中的文件 165 | * @param file assets目录下的文件名(包含路径) 166 | * @param manager AssetManager管理器 167 | * @return 返回字符串 168 | */ 169 | char* readAssetFile(const char* file, AAssetManager* manager); 170 | 171 | /** 172 | * 打开文件 173 | * @param context 上下文 174 | * @param fileName 文件名 175 | * @return 返回AAsset 176 | */ 177 | static AAsset* fileOpen(void *context, const char *fileName); 178 | 179 | 180 | /** 181 | * 关闭文件 182 | * @param file 183 | */ 184 | static void fileClose(AAsset *file); 185 | 186 | /** 187 | * 读取文件 188 | * @param file 189 | * @param bytesToRead 190 | * @param buffer 191 | * @return 192 | */ 193 | static int fileRead(AAsset *file, int bytesToRead, void *buffer); 194 | 195 | /// shader 196 | GLuint loadShader(GLenum type, const char* shaderSrc); 197 | 198 | GLuint loadProgram(const char* vertexShader, const char* fragShader); 199 | 200 | /** 201 | * 查询活动的统一变量uniform 202 | * @param program 203 | */ 204 | void checkActiveUniform(GLuint program); 205 | 206 | /// transform 207 | /** 208 | * 缩放 209 | * @param result 210 | * @param sx 211 | * @param sy 212 | * @param sz 213 | */ 214 | void scale(ESMatrix* result, GLfloat sx, GLfloat sy, GLfloat sz); 215 | 216 | /** 217 | * 平移 218 | * @param result 219 | * @param x 220 | * @param y 221 | * @param z 222 | */ 223 | void translate(ESMatrix* result, GLfloat x, GLfloat y, GLfloat z); 224 | 225 | /** 226 | * 旋转 227 | * @param result 228 | * @param angle 229 | * @param x 230 | * @param y 231 | * @param z 232 | */ 233 | void rotate(ESMatrix* result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); 234 | 235 | /** 236 | * 视锥体 237 | * @param result 238 | * @param left 239 | * @param top 240 | * @param right 241 | * @param bottom 242 | * @param nearz 243 | * @param z 244 | */ 245 | void frustum(ESMatrix* result, float left, float top, 246 | float right, float bottom, float nearz, float farz); 247 | 248 | /** 249 | * 透视 250 | * @param result 251 | * @param fovy 252 | * @param aspect 253 | * @param nearz 254 | * @param farz 255 | */ 256 | void perspective(ESMatrix* result, float fovy, float aspect, float nearz, float farz); 257 | 258 | 259 | /** 260 | * 矩阵相乘 261 | * @param result 262 | * @param srcA 263 | * @param srcB 264 | */ 265 | void matrixMultiply(ESMatrix* result, ESMatrix* srcA, ESMatrix* srcB); 266 | 267 | /** 268 | * 产生一个单位矩阵 269 | * @param result 270 | */ 271 | void matrixLoadIdentity(ESMatrix* result); 272 | 273 | /** 274 | * 创建球面 275 | * @param numSlices 276 | * @param radius 277 | * @param vertices 278 | * @param normals 279 | * @param texCoords 280 | * @param indices 281 | * @return 282 | */ 283 | int sphere(int numSlices, float radius, 284 | GLfloat **vertices, GLfloat **normals, GLfloat **texCoords, GLuint **indices); 285 | 286 | 287 | 288 | 289 | #ifdef __cplusplus 290 | } 291 | #endif 292 | 293 | #endif //GLESNATIVESAMPLE_EGLUTIL_H 294 | -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/Application/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Application/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /Application/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GLESNativeSample 3 | 4 | -------------------------------------------------------------------------------- /Application/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.3.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CainKernel/GLESNativeSample/f6c89d954c190a7b7a0928eb2696bf583bc0ce9b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 22 17:40:23 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':Application' 2 | --------------------------------------------------------------------------------