├── .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 |
227 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
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 |
--------------------------------------------------------------------------------