├── .gitattributes
├── .gitignore
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README-en.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── image_0.jpg
│ ├── image_1.jpg
│ ├── image_2.jpg
│ ├── image_3.png
│ └── lighting
│ │ ├── brick.png
│ │ ├── brickn.png
│ │ ├── bumpedlighting.fs
│ │ ├── bumpedlighting.vs
│ │ ├── directionallight.fs
│ │ ├── directionallight.vs
│ │ ├── pointlight.fs
│ │ ├── pointlight.vs
│ │ ├── spotlight.vs
│ │ └── spotlightsoftedge.fs
│ ├── java
│ └── io
│ │ └── github
│ │ └── kenneycode
│ │ └── openglespro
│ │ ├── GlobalConstants.kt
│ │ ├── MainActivity.kt
│ │ ├── SampleActivity.kt
│ │ ├── Util.kt
│ │ └── samples
│ │ ├── fragment
│ │ ├── SampleBinaryProgram.kt
│ │ ├── SampleColorBlend.kt
│ │ ├── SampleEGL.kt
│ │ ├── SampleFenceSync.kt
│ │ ├── SampleLighting.kt
│ │ ├── SampleMatrixTransform.kt
│ │ ├── SampleMultiRenderTarget.kt
│ │ ├── SampleShader.kt
│ │ ├── SampleTextureArray.kt
│ │ └── SampleVBOAndIBO.kt
│ │ └── renderer
│ │ ├── SampleBinaryProgramRenderer.kt
│ │ ├── SampleColorBlendRenderer.kt
│ │ ├── SampleFenceSyncRenderer.kt
│ │ ├── SampleMatrixTransformRenderer.kt
│ │ ├── SampleMultiRenderTargetRenderer.kt
│ │ ├── SampleShaderRenderer.kt
│ │ ├── SampleTextureArrayRenderer.kt
│ │ ├── SampleVBOAndIBORenderer.kt
│ │ └── lighting
│ │ ├── BumpedLightRenderer.kt
│ │ ├── DirectionalLightRenderer.kt
│ │ ├── LightingRenderer.kt
│ │ ├── PointLightRenderer.kt
│ │ └── SpotLightRenderer.kt
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── activity_sample.xml
│ ├── fragment_common_sample.xml
│ ├── fragment_sample_fence_sync.xml
│ ├── fragment_sample_lighting.xml
│ ├── fragment_sample_matrix_transform.xml
│ ├── item_parameter_list.xml
│ └── layout_sample_list_item.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── 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
│ └── test_image.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
└── settings.gradle
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | *.aab
5 |
6 | # Files for the ART/Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 | out/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # IntelliJ
37 | *.iml
38 | .idea/
39 |
40 | # Keystore files
41 | # Uncomment the following lines if you do not want to check your keystore files in.
42 | #*.jks
43 | #*.keystore
44 |
45 | # External native build folder generated in Android Studio 2.2 and later
46 | .externalNativeBuild
47 |
48 | # Google Services (e.g. APIs or Firebase)
49 | google-services.json
50 |
51 | # Freeline
52 | freeline.py
53 | freeline/
54 | freeline_project_description.json
55 |
56 | # fastlane
57 | fastlane/report.xml
58 | fastlane/Preview.html
59 | fastlane/screenshots
60 | fastlane/test_output
61 | fastlane/readme.md
62 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.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 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/README-en.md:
--------------------------------------------------------------------------------
1 | # **OpenGLESPro**
2 |
3 | This is a `OpenGL ES` advanced learning project for Android, and I will continue to code and commit samples and write chinese and english commets for some import code.
4 |
5 | I will publish some Android OpenGL ES advanced learning articles on my **juejin**, including the articles related to every samples in this project, and other knowledge. Welcome! Link: https://juejin.im/user/5afabe81f265da0b7b361036/posts
6 |
7 |
8 |
9 | Now, this project contains the following samples.
10 |
11 |
12 |
13 | - **SampleShader**
14 |
15 | A sample demonstrates the usage of location in OpenGL 3.0 shader.
16 |
17 | [https://juejin.im/post/5ca9863151882543f400b745](https://juejin.im/post/5ca9863151882543f400b745)
18 |
19 |
20 |
21 | - **SampleTextureArray**
22 |
23 | A sample demonstrates the usage of texture array. In the fragment shader, we use sampler2DArray to hold an array of texture.
24 |
25 | https://juejin.im/post/5ce0aca6e51d4510a37bab4b
26 |
27 |
28 |
29 | - **SampleBinaryProgram**
30 |
31 | A sample demonstrates the usage of binary GL program. We can save the linked GL program to file and load a binary GL program from file.
32 |
33 |
34 |
35 | - **SampleFenceSync**
36 |
37 | a sample of using fence to synchronize the GL commands.
38 |
39 | https://juejin.im/post/5d33ed275188257f3850d5fb
40 |
41 |
42 |
43 | - **SampleMultiRenderTarget**
44 |
45 | This is a sample of multiple render targets, with which we can render to multiple textures at a time
46 |
47 |
48 |
49 | - **SampleVBOAndIBO**
50 |
51 | This sample demonstrates the usage of VBO(Vertex Buffer Object) and IBO(Index Buffer Object)
52 |
53 | https://juejin.im/post/5ce55ae95188253114078ad7
54 |
55 |
56 |
57 | - **SampleEGL**
58 |
59 | This sample demonstrates the usage of EGL
60 |
61 |
62 |
63 |
64 |
65 | - **SampleMatrixTransform**
66 |
67 | This sample demonstrates matrix transform, including model matrix, view matrix and project matrix
68 |
69 |
70 |
71 |
72 |
73 | - **SampleColorBlend**
74 |
75 | This sample demonstrates color blend
76 |
77 | https://juejin.im/post/5d33ee065188257bd829be0c
78 |
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [English README please click here](./README-en.md)
2 |
3 | # OpenGLESPro
4 |
5 |
6 | 这是一个`Android`上的`OpenGL ES` 高级进阶学习项目,我会不断地补充sample,并在关键代码处附上中英文注释。
7 |
8 | 在我的**掘金**上,我会发布相关的**OpenGL ES 高级进阶**教学文章,包括每个例子的对应的讲解文章,以及一些其它知识,欢迎关注:https://juejin.im/user/5afabe81f265da0b7b361036/posts
9 |
10 |
11 |
12 | 目前工程中有以下例子:
13 |
14 |
15 |
16 | - **SampleShader**
17 |
18 | 一个演示OpenGL 3.0 shader的例子,主要演示其中的location字段的作用
19 |
20 | [https://juejin.im/post/5ca9863151882543f400b745](https://juejin.im/post/5ca9863151882543f400b745)
21 |
22 |
23 |
24 | - **SampleTextureArray**
25 |
26 | 一个纹理数组的例子,通过使用sampler2DArray将一组纹理传给fragment shader
27 |
28 | https://juejin.im/post/5ce0aca6e51d4510a37bab4b
29 |
30 |
31 |
32 | - **SampleBinaryProgram**
33 |
34 | 一个使用二进制GL program的例子,演示将link好的GL Program以文件的方式保存,以及读取GL program文件并加载
35 |
36 |
37 |
38 | - **SampleFenceSync**
39 |
40 | 一个使用栅栏做GL命令同步的例子
41 |
42 | https://juejin.im/post/5d33ed275188257f3850d5fb
43 |
44 |
45 |
46 | - **SampleMultiRenderTarget**
47 |
48 | 一个多渲染目标的例子,可以一次渲染到多个纹理上
49 |
50 |
51 |
52 | - **SampleVBOAndIBO**
53 |
54 | VBO(Vertex Buffer Object)和IBO(Index Buffer Object)的使用方法
55 |
56 | https://juejin.im/post/5ce55ae95188253114078ad7
57 |
58 |
59 |
60 | - **SampleEGL**
61 |
62 | EGL的使用方法
63 |
64 |
65 |
66 |
67 |
68 | - **SampleMatrixTransform**
69 |
70 | 矩阵变换的例子,包括模型矩阵、视图矩阵和投影矩阵
71 |
72 |
73 |
74 |
75 |
76 | - **SampleColorBlend**
77 |
78 | 颜色混合例子
79 |
80 | https://juejin.im/post/5d33ee065188257bd829be0c
81 |
82 |
83 |
84 | - **SampleLighting**
85 |
86 | 光照
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 28
9 | defaultConfig {
10 | applicationId "io.github.kenneycode.openglespro"
11 | minSdkVersion 21
12 | targetSdkVersion 28
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(include: ['*.jar'], dir: 'libs')
26 | implementation 'com.android.support:appcompat-v7:28.0.0'
27 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
28 | implementation 'com.android.support:recyclerview-v7:28.0.0'
29 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
30 | implementation "org.jetbrains.kotlin:kotlin-reflect:1.2.71"
31 | }
32 | repositories {
33 | mavenCentral()
34 | }
35 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/assets/image_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/assets/image_0.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/image_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/assets/image_1.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/image_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/assets/image_2.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/assets/image_3.png
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/brick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/assets/lighting/brick.png
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/brickn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/assets/lighting/brickn.png
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/bumpedlighting.fs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout(location = 0) out vec4 fragColor;
6 |
7 | in vec2 texCoord;
8 | in vec3 fragPos;
9 |
10 | in vec3 tangentLightPos;
11 | in vec3 tangentViewPos;
12 | in vec3 tangentFragPos;
13 |
14 |
15 | uniform sampler2D imageTex;
16 | uniform sampler2D normalTex;
17 | uniform vec3 lightColor;
18 | uniform vec3 objectColor;
19 |
20 | float myPow(float x, int r) {
21 | float result = 1.0;
22 | for (int i = 0; i < r; i = i + 1) {
23 | result = result * x;
24 | }
25 | return result;
26 | }
27 |
28 | void main()
29 | {
30 |
31 | vec3 normal = texture(normalTex, texCoord).rgb;
32 | normal = normalize(normal * 2.0 - 1.0);
33 |
34 | vec3 texColor = texture(imageTex, texCoord).rgb;
35 |
36 | // ambient
37 | float ambientStrength = 0.5;
38 | vec3 ambient = ambientStrength * lightColor;
39 |
40 | // diffuse
41 | vec3 norm = normalize(normal);
42 | vec3 lightDir = normalize(tangentLightPos - tangentFragPos);
43 | float diff = max(dot(norm, lightDir), 0.0);
44 | vec3 diffuse = diff * lightColor;
45 |
46 | // specular
47 | float specularStrength = 2.0;
48 | vec3 viewDir = normalize(tangentViewPos - tangentFragPos);
49 | vec3 reflectDir = reflect(-lightDir, norm);
50 | float spec = myPow(max(dot(viewDir, reflectDir), 0.0), 4);
51 | vec3 specular = specularStrength * spec * lightColor;
52 |
53 | vec3 result = (ambient + diffuse + specular) * texColor;
54 | fragColor = vec4(result, 1.0);
55 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/bumpedlighting.vs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout (location = 0) in vec3 aPos;
6 | layout (location = 1) in vec2 aTexCoord;
7 | layout (location = 2) in vec3 aNormal;
8 | layout (location = 3) in vec3 tangent;
9 | layout (location = 4) in vec3 bitangent;
10 |
11 | out vec3 fragPos;
12 | out vec2 texCoord;
13 | out vec3 tangentLightPos;
14 | out vec3 tangentViewPos;
15 | out vec3 tangentFragPos;
16 |
17 | uniform vec3 lightPos;
18 | uniform vec3 viewPos;
19 | uniform mat4 model;
20 | uniform mat4 view;
21 | uniform mat4 projection;
22 |
23 | void main()
24 | {
25 | texCoord = aTexCoord;
26 | fragPos = vec3(model * vec4(aPos, 1.0));
27 | mat3 normalMatrix = transpose(inverse(mat3(model)));
28 | vec3 T = normalize(normalMatrix * tangent);
29 | vec3 B = normalize(normalMatrix * bitangent);
30 | vec3 N = normalize(normalMatrix * aNormal);
31 | mat3 TBN = transpose(mat3(T, B, N));
32 | tangentLightPos = TBN * lightPos;
33 | tangentViewPos = TBN * viewPos;
34 | tangentFragPos = TBN * fragPos;
35 | gl_Position = projection * view * vec4(fragPos, 1.0);
36 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/directionallight.fs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout(location = 0) out vec4 fragColor;
6 |
7 | in vec2 texCoord;
8 | in vec3 fragPos;
9 | in vec3 normal;
10 |
11 | uniform sampler2D imageTex;
12 | uniform sampler2D normalTex;
13 | uniform vec3 lightDirection;
14 | uniform vec3 viewPos;
15 | uniform vec3 lightColor;
16 | uniform vec3 objectColor;
17 |
18 | float myPow(float x, int r) {
19 | float result = 1.0;
20 | for (int i = 0; i < r; i = i + 1) {
21 | result = result * x;
22 | }
23 | return result;
24 | }
25 |
26 | void main()
27 | {
28 |
29 | vec3 texColor = texture(imageTex, texCoord).rgb;
30 |
31 | // ambient
32 | float ambientStrength = 0.5;
33 | vec3 ambient = ambientStrength * lightColor;
34 |
35 | // diffuse
36 | vec3 norm = normalize(normal);
37 | vec3 lightDir = normalize(-lightDirection);
38 | float diff = max(dot(norm, lightDir), 0.0);
39 | vec3 diffuse = diff * lightColor;
40 |
41 | // specular
42 | float specularStrength = 2.0;
43 | vec3 viewDir = normalize(viewPos - fragPos);
44 | vec3 reflectDir = reflect(-lightDir, norm);
45 | float spec = myPow(max(dot(viewDir, reflectDir), 0.0), 16);
46 | vec3 specular = specularStrength * spec * lightColor;
47 |
48 | vec3 result = (ambient + diffuse + specular) * texColor;
49 | fragColor = vec4(result, 1.0);
50 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/directionallight.vs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout (location = 0) in vec3 aPos;
6 | layout (location = 1) in vec2 aTexCoord;
7 | layout (location = 2) in vec3 aNormal;
8 |
9 | out vec3 fragPos;
10 | out vec2 texCoord;
11 | out vec3 normal;
12 |
13 | uniform mat4 model;
14 | uniform mat4 view;
15 | uniform mat4 projection;
16 |
17 | void main()
18 | {
19 | texCoord = aTexCoord;
20 | fragPos = vec3(model * vec4(aPos, 1.0));
21 | normal = mat3(transpose(inverse(model))) * aNormal;
22 | gl_Position = projection * view * vec4(fragPos, 1.0);
23 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/pointlight.fs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout(location = 0) out vec4 fragColor;
6 |
7 | in vec2 texCoord;
8 | in vec3 fragPos;
9 | in vec3 normal;
10 |
11 | uniform sampler2D imageTex;
12 | uniform vec3 lightPos;
13 | uniform vec3 viewPos;
14 | uniform vec3 lightColor;
15 | uniform vec3 objectColor;
16 |
17 | float myPow(float x, int r) {
18 | float result = 1.0;
19 | for (int i = 0; i < r; i = i + 1) {
20 | result = result * x;
21 | }
22 | return result;
23 | }
24 |
25 | void main()
26 | {
27 |
28 | vec3 texColor = texture(imageTex, texCoord).rgb;
29 |
30 | // ambient
31 | float ambientStrength = 0.5;
32 | vec3 ambient = ambientStrength * lightColor;
33 |
34 | // diffuse
35 | vec3 norm = normalize(normal);
36 | vec3 lightDir = normalize(lightPos - fragPos);
37 | float diff = max(dot(norm, lightDir), 0.0);
38 | vec3 diffuse = diff * lightColor;
39 |
40 | // specular
41 | float specularStrength = 2.0;
42 | vec3 viewDir = normalize(viewPos - fragPos);
43 | vec3 reflectDir = reflect(-lightDir, norm);
44 | float spec = myPow(max(dot(viewDir, reflectDir), 0.0), 16);
45 | vec3 specular = specularStrength * spec * lightColor;
46 |
47 | // attenuation
48 | float dist = length(lightPos - fragPos);
49 | float kc = 0.1;
50 | float kl = 0.05;
51 | float kq = 0.05;
52 | float attenuation = 1.0 / (kc + kl * dist + kq * (dist * dist));
53 | ambient *= attenuation;
54 | diffuse *= attenuation;
55 | specular *= attenuation;
56 |
57 | vec3 result = (ambient + diffuse + specular) * texColor;
58 | fragColor = vec4(result, 1.0);
59 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/pointlight.vs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout (location = 0) in vec3 aPos;
6 | layout (location = 1) in vec2 aTexCoord;
7 | layout (location = 2) in vec3 aNormal;
8 |
9 | out vec3 fragPos;
10 | out vec2 texCoord;
11 | out vec3 normal;
12 |
13 | uniform mat4 model;
14 | uniform mat4 view;
15 | uniform mat4 projection;
16 |
17 | void main()
18 | {
19 | texCoord = aTexCoord;
20 | fragPos = vec3(model * vec4(aPos, 1.0));
21 | normal = mat3(transpose(inverse(model))) * aNormal;
22 | gl_Position = projection * view * vec4(fragPos, 1.0);
23 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/spotlight.vs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout (location = 0) in vec3 aPos;
6 | layout (location = 1) in vec2 aTexCoord;
7 | layout (location = 2) in vec3 aNormal;
8 |
9 | out vec3 fragPos;
10 | out vec2 texCoord;
11 | out vec3 normal;
12 |
13 | uniform mat4 model;
14 | uniform mat4 view;
15 | uniform mat4 projection;
16 |
17 | void main()
18 | {
19 | texCoord = aTexCoord;
20 | fragPos = vec3(model * vec4(aPos, 1.0));
21 | normal = mat3(transpose(inverse(model))) * aNormal;
22 | gl_Position = projection * view * vec4(fragPos, 1.0);
23 | }
--------------------------------------------------------------------------------
/app/src/main/assets/lighting/spotlightsoftedge.fs:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision mediump float;
4 |
5 | layout(location = 0) out vec4 fragColor;
6 |
7 | in vec2 texCoord;
8 | in vec3 fragPos;
9 | in vec3 normal;
10 |
11 | uniform sampler2D imageTex;
12 | uniform sampler2D normalTex;
13 | uniform vec3 lightPos;
14 | uniform vec3 viewPos;
15 | uniform vec3 lightColor;
16 | uniform vec3 objectColor;
17 |
18 | float myPow(float x, int r) {
19 | float result = 1.0;
20 | for (int i = 0; i < r; i = i + 1) {
21 | result = result * x;
22 | }
23 | return result;
24 | }
25 |
26 | void main()
27 | {
28 |
29 | vec3 texColor = texture(imageTex, texCoord).rgb;
30 |
31 | // ambient
32 | float ambientStrength = 0.5;
33 | vec3 ambient = ambientStrength * lightColor;
34 |
35 | vec3 spotDir = vec3(-2.0, 0.0, 0.0);
36 | vec3 lightDir = normalize(lightPos - fragPos);
37 | float theta = dot(lightDir, normalize(-spotDir));
38 |
39 | // diffuse
40 | vec3 norm = normalize(normal);
41 | float diff = max(dot(norm, lightDir), 0.0);
42 | vec3 diffuse = diff * lightColor;
43 |
44 | // specular
45 | float specularStrength = 2.0;
46 | vec3 viewDir = normalize(viewPos - fragPos);
47 | vec3 reflectDir = reflect(-lightDir, norm);
48 | float spec = myPow(max(dot(viewDir, reflectDir), 0.0), 16);
49 | vec3 specular = specularStrength * spec * lightColor;
50 |
51 | // spotlight (soft edges)
52 | float epsilon = 0.15;
53 | float intensity = clamp((theta - 0.85) / epsilon, 0.0, 1.0);
54 | diffuse *= intensity;
55 | specular *= intensity;
56 |
57 | // attenuation
58 | float dist = length(lightPos - fragPos);
59 | float kc = 0.1;
60 | float kl = 0.1;
61 | float kq = 0.1;
62 | float attenuation = 1.0 / (kc + kl * dist + kq * (dist * dist));
63 | ambient *= attenuation;
64 | diffuse *= attenuation;
65 | specular *= attenuation;
66 |
67 | vec3 result = (ambient + diffuse + specular) * texColor;
68 | fragColor = vec4(result, 1.0);
69 |
70 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/GlobalConstants.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro
2 |
3 | /**
4 | *
5 | * Coded by kenney
6 | *
7 | * http://www.github.com/kenneycode
8 | *
9 | * 全局常量
10 | * Global constants
11 | **/
12 |
13 | class GlobalConstants {
14 | companion object {
15 | const val KEY_SAMPLE_INDEX = "sample_index"
16 | const val KEY_SAMPLE_NAME = "sample_name"
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.support.v7.app.AppCompatActivity
6 | import android.support.v7.widget.LinearLayoutManager
7 | import android.support.v7.widget.RecyclerView
8 | import android.view.LayoutInflater
9 | import android.view.View
10 | import android.view.ViewGroup
11 | import android.widget.Button
12 |
13 | /**
14 | *
15 | * Coded by kenney
16 | *
17 | * http://www.github.com/kenneycode
18 | *
19 | *
20 | **/
21 |
22 | class MainActivity : AppCompatActivity() {
23 |
24 | override fun onCreate(savedInstanceState: Bundle?) {
25 | super.onCreate(savedInstanceState)
26 | setContentView(R.layout.activity_main)
27 | Util.context = applicationContext
28 | val samplesList = findViewById(R.id.list)
29 | val layoutManager = LinearLayoutManager(this)
30 | layoutManager.orientation = LinearLayoutManager.VERTICAL
31 | samplesList.layoutManager = layoutManager
32 | samplesList.adapter = MyAdapter()
33 | }
34 |
35 | inner class MyAdapter : RecyclerView.Adapter() {
36 |
37 | private val sampleNames =
38 | arrayOf(resources.getString(R.string.sample_0),
39 | resources.getString(R.string.sample_1),
40 | resources.getString(R.string.sample_2),
41 | resources.getString(R.string.sample_3),
42 | resources.getString(R.string.sample_4),
43 | resources.getString(R.string.sample_5),
44 | resources.getString(R.string.sample_6),
45 | resources.getString(R.string.sample_7),
46 | resources.getString(R.string.sample_8),
47 | resources.getString(R.string.sample_9))
48 |
49 | override fun onCreateViewHolder(p0: ViewGroup, p1: Int): VH {
50 | val view = LayoutInflater.from(p0.context).inflate(R.layout.layout_sample_list_item, p0, false)
51 | return VH(view)
52 | }
53 |
54 | override fun getItemCount(): Int {
55 | return sampleNames.size
56 | }
57 |
58 | override fun onBindViewHolder(p0: VH, p1: Int) {
59 | p0.button.text = sampleNames[p1]
60 | p0.button.setOnClickListener {
61 | val intent = Intent(this@MainActivity, SimpleActivity::class.java)
62 | intent.putExtra(GlobalConstants.KEY_SAMPLE_INDEX, p1)
63 | intent.putExtra(GlobalConstants.KEY_SAMPLE_NAME, sampleNames[p1])
64 | this@MainActivity.startActivity(intent)
65 | }
66 | }
67 |
68 | }
69 |
70 | inner class VH(itemView : View) : RecyclerView.ViewHolder(itemView) {
71 | var button : Button = itemView.findViewById(R.id.button)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/SampleActivity.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro
2 |
3 | import android.os.Bundle
4 | import android.support.v7.app.AppCompatActivity
5 | import io.github.kenneycode.openglespro.samples.fragment.*
6 |
7 | /**
8 | *
9 | * Coded by kenney
10 | *
11 | * http://www.github.com/kenneycode
12 | *
13 | * Sample展示类
14 | * This sample activity
15 | *
16 | **/
17 |
18 | class SimpleActivity : AppCompatActivity() {
19 |
20 | private val samples =
21 | arrayOf(
22 | SampleShader(),
23 | SampleTextureArray(),
24 | SampleBinaryProgram(),
25 | SampleFenceSync(),
26 | SampleMultiRenderTarget(),
27 | SampleVBOAndIBO(),
28 | SampleEGL(),
29 | SampleMatrixTransform(),
30 | SampleColorBlend(),
31 | SampleLighting()
32 | )
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 | setContentView(R.layout.activity_sample)
37 | title = intent.getStringExtra(GlobalConstants.KEY_SAMPLE_NAME)
38 | val sampleIndex = intent.getIntExtra(GlobalConstants.KEY_SAMPLE_INDEX, -1)
39 | val transaction = supportFragmentManager.beginTransaction()
40 | transaction.replace(R.id.content, samples[sampleIndex])
41 | transaction.commit()
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/Util.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro
2 |
3 | import android.content.Context
4 | import android.graphics.Bitmap
5 | import android.graphics.BitmapFactory
6 | import android.opengl.GLES30
7 | import android.util.Log
8 | import java.nio.charset.Charset
9 |
10 | /**
11 | *
12 | * Coded by kenney
13 | *
14 | * http://www.github.com/kenneycode
15 | *
16 | *
17 | **/
18 |
19 | class Util {
20 |
21 | companion object {
22 |
23 | lateinit var context: Context
24 |
25 | fun decodeBitmapFromAssets(filename : String) : Bitmap {
26 | val options = BitmapFactory.Options()
27 | options.inSampleSize = 1
28 | val bitmap = BitmapFactory.decodeStream(context.assets.open(filename))
29 | if (bitmap == null) {
30 | Log.e("debug", "bitmap decode fail, path = $filename")
31 | }
32 | return bitmap
33 | }
34 |
35 | fun loadShaderFromAssets(path: String): String {
36 | val inputStream = context.assets.open(path)
37 | val length = inputStream.available()
38 | val bytes = ByteArray(length)
39 | inputStream.read(bytes)
40 | return String(bytes, Charset.defaultCharset())
41 | }
42 |
43 | fun checkGLError() {
44 | val error = GLES30.glGetError()
45 | if (error != GLES30.GL_NO_ERROR) {
46 | val hexErrorCode = Integer.toHexString(error)
47 | Log.e("debug", "glError: $hexErrorCode")
48 | throw RuntimeException("GLError")
49 | }
50 | }
51 |
52 | fun getScreenWidth() : Int {
53 | return 1440
54 | }
55 |
56 | fun getScreenHeight() : Int {
57 | return 2560
58 | }
59 |
60 | }
61 |
62 |
63 |
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleBinaryProgram.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleBinaryProgramRenderer
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个使用二进制GL program的例子,演示将link好的GL Program以文件的方式保存,以及读取GL program文件并加载
19 | * This sample demonstrates the usage of binary GL program. We can save the linked GL program to file and load a binary GL program from file.
20 | *
21 | **/
22 |
23 | class SampleBinaryProgram : Fragment() {
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
26 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
27 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
28 | // Set the size of RGBA、depth and stencil vertexDataBuffer
29 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
30 | // 设置GL版本,这里设置为3.0
31 | // Set GL version, here I set it to 3.0
32 | glSurfaceView.setEGLContextClientVersion(3)
33 | // 设置对应sample的渲染器
34 | // Set the corresponding sample renderer
35 | glSurfaceView.setRenderer(SampleBinaryProgramRenderer())
36 | return rootView
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleColorBlend.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleColorBlendRenderer
11 | import io.github.kenneycode.openglespro.samples.renderer.SampleVBOAndIBORenderer
12 |
13 | /**
14 | *
15 | * Coded by kenney
16 | *
17 | * http://www.github.com/kenneycode
18 | *
19 | * 这是一个使用颜色混合的例子
20 | * This sample demonstrates color blend
21 | *
22 | **/
23 |
24 | class SampleColorBlend : Fragment() {
25 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
26 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
27 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
28 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
29 | // Set the size of RGBA、depth and stencil vertexDataBuffer
30 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
31 | // 设置GL版本,这里设置为3.0
32 | // Set GL version, here I set it to 3.0
33 | glSurfaceView.setEGLContextClientVersion(3)
34 | // 设置对应sample的渲染器
35 | // Set the corresponding sample renderer
36 | glSurfaceView.setRenderer(SampleColorBlendRenderer())
37 | return rootView
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleEGL.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.*
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 |
11 | /**
12 | *
13 | * Coded by kenney
14 | *
15 | * http://www.github.com/kenneycode
16 | *
17 | * 这是一个使用EGL的例子
18 | * This is a sample of using EGL
19 | *
20 | **/
21 |
22 | class SampleEGL : Fragment() {
23 |
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
26 |
27 | Thread {
28 |
29 | val egl = EGL()
30 | egl.init()
31 |
32 | egl.bind()
33 |
34 | val textures = IntArray(1)
35 | GLES30.glGenTextures(textures.size, textures, 0)
36 | val imageTexture = textures[0]
37 | assert(GLES30.glIsTexture(imageTexture))
38 |
39 | egl.release()
40 |
41 | }.start()
42 |
43 | return rootView
44 | }
45 |
46 | inner class EGL {
47 |
48 | private var eglDisplay = EGL14.EGL_NO_DISPLAY
49 | private var eglSurface = EGL14.EGL_NO_SURFACE
50 | private var eglContext = EGL14.EGL_NO_CONTEXT
51 |
52 | fun init() {
53 |
54 | // 获取显示设备
55 | // Get the display
56 | eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
57 | val version = IntArray(2)
58 |
59 | // 初始化显示设备
60 | // Initialize the display
61 | EGL14.eglInitialize(eglDisplay, version, 0, version, 1)
62 | val attribList = intArrayOf(
63 | EGL14.EGL_RED_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_ALPHA_SIZE, 8,
64 | EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT or EGLExt.EGL_OPENGL_ES3_BIT_KHR, EGL14.EGL_NONE
65 | )
66 |
67 | // 选择config
68 | // Choose config
69 | val eglConfig = arrayOfNulls(1)
70 | val numConfigs = IntArray(1)
71 | EGL14.eglChooseConfig(
72 | eglDisplay, attribList, 0, eglConfig, 0, eglConfig.size,
73 | numConfigs, 0
74 | )
75 |
76 | // 创建EGL Context
77 | // Create EGL Context
78 | eglContext = EGL14.eglCreateContext(
79 | eglDisplay, eglConfig[0], EGL14.EGL_NO_CONTEXT,
80 | intArrayOf(EGL14.EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE), 0
81 | )
82 | val surfaceAttribs = intArrayOf(EGL14.EGL_NONE)
83 |
84 | // 创建Pbuffer Surface
85 | // Create Pbuffer Surface
86 | eglSurface = EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig[0], surfaceAttribs, 0)
87 |
88 | }
89 |
90 | fun bind() {
91 | EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)
92 | }
93 |
94 | fun release() {
95 | if (eglDisplay !== EGL14.EGL_NO_DISPLAY) {
96 | EGL14.eglMakeCurrent(eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT)
97 | EGL14.eglDestroySurface(eglDisplay, eglSurface)
98 | EGL14.eglDestroyContext(eglDisplay, eglContext)
99 | EGL14.eglReleaseThread()
100 | EGL14.eglTerminate(eglDisplay)
101 | }
102 | eglDisplay = EGL14.EGL_NO_DISPLAY
103 | eglContext = EGL14.EGL_NO_CONTEXT
104 | eglSurface = EGL14.EGL_NO_SURFACE
105 |
106 | }
107 |
108 | private fun checkEglError(msg: String) {
109 | val error= EGL14.eglGetError()
110 | if (error != EGL14.EGL_SUCCESS) {
111 | throw RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error))
112 | }
113 | }
114 |
115 | }
116 |
117 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleFenceSync.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleFenceSyncRenderer
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个使用栅栏做GL命令同步的例子
19 | * This is a sample of using fence to synchronize the GL commands
20 | *
21 | **/
22 |
23 | class SampleFenceSync : Fragment() {
24 |
25 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
26 | val rootView = inflater.inflate(R.layout.fragment_sample_fence_sync, container, false)
27 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
28 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
29 | // Set the size of RGBA、depth and stencil vertexDataBuffer
30 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
31 | // 设置GL版本,这里设置为3.0
32 | // Set GL version, here I set it to 3.0
33 | glSurfaceView.setEGLContextClientVersion(3)
34 | // 设置对应sample的渲染器
35 | // Set the corresponding sample renderer
36 | glSurfaceView.setRenderer(SampleFenceSyncRenderer(rootView.findViewById(R.id.image_view)))
37 | glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
38 |
39 | return rootView
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleLighting.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.content.Context
4 | import android.opengl.GLSurfaceView
5 | import android.os.Bundle
6 | import android.support.v4.app.Fragment
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import io.github.kenneycode.openglespro.R
11 | import io.github.kenneycode.openglespro.samples.renderer.lighting.BumpedLightRenderer
12 | import io.github.kenneycode.openglespro.samples.renderer.lighting.DirectionalLightRenderer
13 | import io.github.kenneycode.openglespro.samples.renderer.lighting.PointLightRenderer
14 | import io.github.kenneycode.openglespro.samples.renderer.lighting.SpotLightRenderer
15 | import kotlinx.android.synthetic.main.fragment_sample_lighting.*
16 |
17 | /**
18 | *
19 | * Coded by kenney
20 | *
21 | * http://www.github.com/kenneycode
22 | *
23 | * 光照例子,包括平行光、点光、聚光和法向图
24 | * Lighting samples, including directional light, point light, spot light and bumped
25 | *
26 | **/
27 |
28 | class SampleLighting : Fragment() {
29 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
30 | return inflater.inflate(R.layout.fragment_sample_lighting, container, false)
31 | }
32 |
33 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
34 | directionalLight.setOnClickListener {
35 | updateSample(glSurfaceViewContainer, DirectionalLightRenderer())
36 | }
37 | pointLight.setOnClickListener {
38 | updateSample(glSurfaceViewContainer, PointLightRenderer())
39 | }
40 | spotLight.setOnClickListener {
41 | updateSample(glSurfaceViewContainer, SpotLightRenderer())
42 | }
43 | bumped.setOnClickListener {
44 | updateSample(glSurfaceViewContainer, BumpedLightRenderer())
45 | }
46 | }
47 |
48 | private fun updateSample(rootView: View, renderer: GLSurfaceView.Renderer) {
49 | rootView as ViewGroup
50 | rootView.removeAllViews()
51 | rootView.addView(createGLSurfaceView(rootView.context, renderer))
52 | }
53 |
54 | private fun createGLSurfaceView(context: Context, renderer: GLSurfaceView.Renderer): GLSurfaceView {
55 | val glSurfaceView = GLSurfaceView(context)
56 | glSurfaceView.setEGLContextClientVersion(3)
57 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 8, 0)
58 | glSurfaceView.setRenderer(renderer)
59 | return glSurfaceView
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleMatrixTransform.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.support.v7.widget.LinearLayoutManager
7 | import android.support.v7.widget.RecyclerView
8 | import android.view.LayoutInflater
9 | import android.view.View
10 | import android.view.ViewGroup
11 | import io.github.kenneycode.openglespro.R
12 | import io.github.kenneycode.openglespro.samples.renderer.OnParameterChangeCallback
13 | import io.github.kenneycode.openglespro.samples.renderer.SampleMatrixTransformRenderer
14 | import kotlinx.android.synthetic.main.fragment_sample_matrix_transform.view.*
15 | import kotlinx.android.synthetic.main.item_parameter_list.view.*
16 |
17 | /**
18 | *
19 | * Coded by kenney
20 | *
21 | * http://www.github.com/kenneycode
22 | *
23 | * 这是一个演示矩阵变换的例子,包括模型矩阵、视图矩阵和投影矩阵
24 | * This sample demonstrates matrix transform, including model matrix, view matrix and project matrix
25 | *
26 | **/
27 |
28 | class SampleMatrixTransform : Fragment() {
29 |
30 | private lateinit var glSurfaceView: GLSurfaceView
31 |
32 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
33 | val rootView = inflater.inflate(R.layout.fragment_sample_matrix_transform, container, false)
34 | glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
35 | // 设置GL版本,这里设置为3.0
36 | // Set GL version, here I set it to 3.0
37 | glSurfaceView.setEGLContextClientVersion(3)
38 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
39 | // Set the size of RGBA、depth and stencil vertexDataBuffer
40 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 8, 0)
41 |
42 | // 设置对应sample的渲染器
43 | // Set the corresponding sample renderer
44 | val renderer = SampleMatrixTransformRenderer()
45 | glSurfaceView.setRenderer(renderer)
46 | glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
47 |
48 | glSurfaceView.post {
49 | val parameters = getParameterItems()
50 | val layoutManager = LinearLayoutManager(activity)
51 | layoutManager.orientation = RecyclerView.VERTICAL
52 | rootView.parameterList.layoutManager = layoutManager
53 | val adapter = Adapter(parameters)
54 | adapter.onParameterChangeCallback = renderer
55 | rootView.parameterList.adapter = adapter
56 |
57 | rootView.resetButton.setOnClickListener {
58 | renderer.onParameterReset()
59 | adapter.parameters = getParameterItems()
60 | adapter.notifyDataSetChanged()
61 | glSurfaceView.requestRender()
62 | }
63 | }
64 | return rootView
65 | }
66 |
67 | private fun getParameterItems(): Array {
68 | return arrayOf(
69 | ParameterItem("translateX", 0f),
70 | ParameterItem("translateY", 0f),
71 | ParameterItem("translateZ", 0f),
72 | ParameterItem("rotateX", 0f),
73 | ParameterItem("rotateY", 0f),
74 | ParameterItem("rotateZ", 0f),
75 | ParameterItem("scaleX", 1f),
76 | ParameterItem("scaleY", 1f),
77 | ParameterItem("scaleZ", 1f),
78 | ParameterItem("cameraPositionX", 0f),
79 | ParameterItem("cameraPositionY", 0f),
80 | ParameterItem("cameraPositionZ", 5f),
81 | ParameterItem("lookAtX", 0f),
82 | ParameterItem("lookAtY", 0f),
83 | ParameterItem("lookAtZ", 0f),
84 | ParameterItem("cameraUpX", 0f),
85 | ParameterItem("cameraUpY", 1f),
86 | ParameterItem("cameraUpZ", 0f),
87 | ParameterItem("nearPlaneLeft", -1f),
88 | ParameterItem("nearPlaneRight", 1f),
89 | ParameterItem("nearPlaneBottom", - glSurfaceView.height.toFloat() / glSurfaceView.width),
90 | ParameterItem("nearPlaneTop", glSurfaceView.height.toFloat() / glSurfaceView.width),
91 | ParameterItem("nearPlane", 2f),
92 | ParameterItem("farPlane", 100f)
93 | )
94 | }
95 |
96 | inner class Adapter(var parameters: Array) : RecyclerView.Adapter() {
97 |
98 | lateinit var onParameterChangeCallback: OnParameterChangeCallback
99 |
100 | override fun onCreateViewHolder(p0: ViewGroup, p1: Int): VH {
101 | return VH(LayoutInflater.from(p0.context).inflate(R.layout.item_parameter_list, null, false))
102 | }
103 |
104 | override fun getItemCount(): Int {
105 | return parameters.size
106 | }
107 |
108 | override fun onBindViewHolder(vh: VH, index: Int) {
109 | vh.parameterKey.text = parameters[index].key
110 | vh.parameterValue.text = String.format("%.2f", parameters[index].value)
111 | vh.reduceButton.setOnClickListener {
112 | val oldValue = vh.parameterValue.text.toString().toFloat()
113 | val newValue = oldValue - if (parameters[index].key.startsWith("scale")) { 0.1f } else { 1f }
114 | vh.parameterValue.text = String.format("%.2f", newValue)
115 | onParameterChangeCallback.onParameterChange(parameters[index].key, newValue)
116 | glSurfaceView.requestRender()
117 | }
118 | vh.addButton.setOnClickListener {
119 | val oldValue = vh.parameterValue.text.toString().toFloat()
120 | val newValue = oldValue + if (parameters[index].key.startsWith("scale")) { 0.1f } else { 1f }
121 | vh.parameterValue.text = String.format("%.2f", newValue)
122 | onParameterChangeCallback.onParameterChange(parameters[index].key, newValue)
123 | glSurfaceView.requestRender()
124 | }
125 | }
126 |
127 | }
128 |
129 | inner class VH(itemView: View) : RecyclerView.ViewHolder(itemView) {
130 | val parameterKey = itemView.parameterKey
131 | val parameterValue = itemView.parameterValue
132 | val reduceButton = itemView.reduceButton
133 | val addButton = itemView.addButton
134 | }
135 |
136 | inner class ParameterItem(val key: String, val value: Float)
137 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleMultiRenderTarget.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleMultiRenderTargetRenderer
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是多渲染目标的例子,可以一次渲染到多个纹理上
19 | * This is a sample of multiple render targets, with which we can render to multiple textures at a time
20 | *
21 | **/
22 |
23 | class SampleMultiRenderTarget : Fragment() {
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
26 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
27 | // 设置GL版本,这里设置为3.0
28 | // Set GL version, here I set it to 3.0
29 | glSurfaceView.setEGLContextClientVersion(3)
30 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
31 | // Set the size of RGBA、depth and stencil vertexDataBuffer
32 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
33 |
34 | // 设置对应sample的渲染器
35 | // Set the corresponding sample renderer
36 | glSurfaceView.setRenderer(SampleMultiRenderTargetRenderer())
37 | return rootView
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleShader.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleShaderRenderer
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个演示OpenGL 3.0 shader的例子,主要演示其中的location字段的作用
19 | * This sample demonstrates the usage of location in OpenGL 3.0 shader
20 | *
21 | **/
22 |
23 | class SampleShader : Fragment() {
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
26 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
27 | // 设置GL版本,这里设置为3.0
28 | // Set GL version, here I set it to 3.0
29 | glSurfaceView.setEGLContextClientVersion(3)
30 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
31 | // Set the size of RGBA、depth and stencil vertexDataBuffer
32 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
33 |
34 | // 设置对应sample的渲染器
35 | // Set the corresponding sample renderer
36 | glSurfaceView.setRenderer(SampleShaderRenderer())
37 | glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
38 | return rootView
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleTextureArray.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleTextureArrayRenderer
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个纹理数组的例子,通用使用sampler2DArray将一组纹理传给fragment shader
19 | * This sample demonstrates the usage of texture array. In the fragment shader, we use sampler2DArray to hold an array of texture.
20 | *
21 | **/
22 |
23 | class SampleTextureArray : Fragment() {
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
26 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
27 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
28 | // Set the size of RGBA、depth and stencil vertexDataBuffer
29 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
30 | // 设置GL版本,这里设置为3.0
31 | // Set GL version, here I set it to 3.0
32 | glSurfaceView.setEGLContextClientVersion(3)
33 | // 设置对应sample的渲染器
34 | // Set the corresponding sample renderer
35 | glSurfaceView.setRenderer(SampleTextureArrayRenderer())
36 | return rootView
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/fragment/SampleVBOAndIBO.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.fragment
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import io.github.kenneycode.openglespro.R
10 | import io.github.kenneycode.openglespro.samples.renderer.SampleVBOAndIBORenderer
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个使用VBO(Vertex Buffer Object)和IBO(Index Buffer Object)的例子
19 | * This sample demonstrates the usage of VBO(Vertex Buffer Object) and IBO(Index Buffer Object)
20 | *
21 | **/
22 |
23 | class SampleVBOAndIBO : Fragment() {
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | val rootView = inflater.inflate(R.layout.fragment_common_sample, container, false)
26 | val glSurfaceView = rootView.findViewById(R.id.glsurfaceview)
27 | // 设置RGBA颜色缓冲、深度缓冲及stencil缓冲大小
28 | // Set the size of RGBA、depth and stencil vertexDataBuffer
29 | glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0)
30 | // 设置GL版本,这里设置为3.0
31 | // Set GL version, here I set it to 3.0
32 | glSurfaceView.setEGLContextClientVersion(3)
33 | // 设置对应sample的渲染器
34 | // Set the corresponding sample renderer
35 | glSurfaceView.setRenderer(SampleVBOAndIBORenderer())
36 | return rootView
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleBinaryProgramRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import io.github.kenneycode.openglespro.Util
6 | import java.io.File
7 | import java.nio.ByteBuffer
8 | import java.nio.ByteOrder
9 | import java.nio.FloatBuffer
10 | import java.nio.IntBuffer
11 | import javax.microedition.khronos.egl.EGLConfig
12 | import javax.microedition.khronos.opengles.GL10
13 |
14 | /**
15 | *
16 | * Coded by kenney
17 | *
18 | * http://www.github.com/kenneycode
19 | *
20 | * 这是一个使用二进制GL program的例子,演示将link好的GL Program以文件的方式保存,以及读取GL program文件并加载
21 | * This sample demonstrates the usage of binary GL program. We can save the linked GL program to file and load a binary GL program from file.
22 | *
23 | **/
24 |
25 | class SampleBinaryProgramRenderer : GLSurfaceView.Renderer {
26 |
27 | private val vertexShaderCode =
28 | "#version 300 es\n" +
29 | "precision mediump float;\n" +
30 | "layout(location = 0) in vec4 a_position;\n" +
31 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
32 | "out vec2 v_textureCoordinate;\n" +
33 | "void main() {\n" +
34 | " v_textureCoordinate = a_textureCoordinate;\n" +
35 | " gl_Position = a_position;\n" +
36 | "}"
37 |
38 | private val fragmentShaderCode =
39 | "#version 300 es\n" +
40 | "precision mediump float;\n" +
41 | "layout(location = 0) out vec4 fragColor;\n" +
42 | "in vec2 v_textureCoordinate;\n" +
43 | "uniform sampler2D u_texture;\n" +
44 | "void main() {\n" +
45 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
46 | "}"
47 |
48 | // GLSurfaceView的宽高
49 | // The width and height of GLSurfaceView
50 | private var glSurfaceViewWidth = 0
51 | private var glSurfaceViewHeight = 0
52 |
53 | // 三角形顶点数据
54 | // The vertex data of a triangle
55 | private val vertexData = floatArrayOf(-1f, -1f, -1f, 1f, 1f, 1f, -1f, -1f, 1f, 1f, 1f, -1f)
56 | private val VERTEX_COMPONENT_COUNT = 2
57 | private lateinit var vertexDataBuffer : FloatBuffer
58 |
59 | // 纹理坐标
60 | // The texture coordinate
61 | private val textureCoordinateData = floatArrayOf(0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 1f, 1f)
62 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 2
63 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
64 |
65 | // 要渲染的图片纹理
66 | // The texture of the image to be rendered
67 | private var imageTexture = 0
68 |
69 | // a_position、a_textureCoordinate和u_texture的位置,与shader中写的对应
70 | // The location of a_position、a_textureCoordinate and u_texture, corresponding with which in shader
71 | private val LOCATION_ATTRIBUTE_POSITION = 0
72 | private val LOCATION_ATTRIBUTE_TEXTURE_COORDINATE = 1
73 | private val LOCATION_UNIFORM_TEXTURE = 0
74 |
75 | override fun onDrawFrame(gl: GL10?) {
76 |
77 | // 设置清屏颜色
78 | // Set the color which the screen will be cleared to
79 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
80 |
81 | // 清屏
82 | // Clear the screen
83 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
84 |
85 | // 设置视口,这里设置为整个GLSurfaceView区域
86 | // Set the viewport to the full GLSurfaceView
87 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
88 |
89 | // 设置好状态,准备渲染
90 | // Set the status before rendering
91 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
92 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
93 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
94 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
95 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
96 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
97 |
98 | // 调用draw方法用TRIANGLES的方式执行渲染,顶点数量为3个
99 | // Call the draw method with GL_TRIANGLES to render 3 vertices
100 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
101 |
102 | }
103 |
104 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
105 |
106 | // 记录GLSurfaceView的宽高
107 | // Record the width and height of the GLSurfaceView
108 | glSurfaceViewWidth = width
109 | glSurfaceViewHeight = height
110 |
111 | }
112 |
113 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
114 |
115 | // 创建GL程序
116 | // Create GL program
117 | var programId = GLES30.glCreateProgram()
118 |
119 | // 加载、编译vertex shader和fragment shader
120 | // Load and compile vertex shader and fragment shader
121 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
122 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
123 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
124 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
125 | GLES30.glCompileShader(vertexShader)
126 | GLES30.glCompileShader(fragmentShader)
127 |
128 | // 将shader程序附着到GL程序上
129 | // Attach the compiled shaders to the GL program
130 | GLES30.glAttachShader(programId, vertexShader)
131 | GLES30.glAttachShader(programId, fragmentShader)
132 |
133 | // 链接GL程序
134 | // Link the GL program
135 | GLES30.glLinkProgram(programId)
136 |
137 | // 将链接好的二进制GL program保存到文件中
138 | // Save the linked binary GL program to file
139 | val binaryBuffer = ByteBuffer.allocate(65536)
140 | val lengthBuffer = IntBuffer.allocate(1)
141 | val formatBuffer = IntBuffer.allocate(1)
142 | GLES30.glGetProgramBinary(programId, binaryBuffer.capacity(), lengthBuffer, formatBuffer, binaryBuffer)
143 | saveGLProgramBinary(binaryBuffer, lengthBuffer[0], formatBuffer[0])
144 | GLES30.glDeleteProgram(programId)
145 |
146 | // 从文件中读取进二进制GL program并加载
147 | // Read and load the binary GL program from file
148 | val glProgramBinary = getGLProgramBinary()
149 | programId = GLES30.glCreateProgram()
150 | GLES30.glProgramBinary(programId, glProgramBinary.format, glProgramBinary.binaryBuffer, glProgramBinary.length)
151 |
152 | // 应用GL程序
153 | // Use the GL program
154 | GLES30.glUseProgram(programId)
155 |
156 | // 将三角形顶点数据放入buffer中
157 | // Put the triangle vertex data into the vertexDataBuffer
158 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
159 | .order(ByteOrder.nativeOrder())
160 | .asFloatBuffer()
161 | vertexDataBuffer.put(vertexData)
162 | vertexDataBuffer.position(0)
163 |
164 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_POSITION,而无需像OpenGL 2.0那样需要先获取参数的location
165 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_POSITION, while in OpenGL 2.0 we have to query the location of the parameter
166 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
167 |
168 | // 指定a_position所使用的顶点数据
169 | // Specify the data of a_position
170 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
171 |
172 | // 将纹理坐标数据放入buffer中
173 | // Put the texture coordinates into the textureCoordinateDataBuffer
174 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE / 8)
175 | .order(ByteOrder.nativeOrder())
176 | .asFloatBuffer()
177 | textureCoordinateDataBuffer.put(textureCoordinateData)
178 | textureCoordinateDataBuffer.position(0)
179 |
180 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_TEXTURE_COORDINATE,而无需像OpenGL 2.0那样需要先获取参数的location
181 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, while in OpenGL 2.0 we have to query the location of the parameter
182 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
183 |
184 | // 指定a_textureCoordinate所使用的顶点数据
185 | // Specify the data of a_textureCoordinate
186 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
187 |
188 | // 创建图片纹理
189 | // Create texture for image
190 | val textures = IntArray(1)
191 | GLES30.glGenTextures(textures.size, textures, 0)
192 | imageTexture = textures[0]
193 |
194 | // 将图片解码并加载到纹理中
195 | // Decode image and load it into texture
196 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
197 | val bitmap = Util.decodeBitmapFromAssets("image_0.jpg")
198 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
199 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
200 | bitmap.copyPixelsToBuffer(b)
201 | b.position(0)
202 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
203 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
204 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
205 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
206 | GLES30.glTexImage2D(
207 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width,
208 | bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
209 | bitmap.recycle()
210 |
211 | // 启动对应位置的参数,这里直接使用LOCATION_UNIFORM_TEXTURE,而无需像OpenGL 2.0那样需要先获取参数的location
212 | // Enable the parameter of the location. Here we can simply use LOCATION_UNIFORM_TEXTURE, while in OpenGL 2.0 we have to query the location of the parameter
213 | GLES30.glUniform1i(LOCATION_UNIFORM_TEXTURE, 0)
214 |
215 | }
216 |
217 | private fun saveGLProgramBinary(binaryBuffer : ByteBuffer, length : Int, format : Int) {
218 | val fileLengthAndFormat = File("/sdcard/length_and_format.txt")
219 | fileLengthAndFormat.writeText(length.toString())
220 | fileLengthAndFormat.appendText("\n")
221 | fileLengthAndFormat.appendText(format.toString())
222 | val fileProgramBinary = File("/sdcard/program_binary.bin")
223 | val bytes = ByteArray(length)
224 | binaryBuffer.get(bytes)
225 | fileProgramBinary.writeBytes(bytes)
226 | }
227 |
228 | private fun getGLProgramBinary() : GLProgramBinary {
229 | val fileLengthAndFormat = File("/sdcard/length_and_format.txt")
230 | val lines = fileLengthAndFormat.readLines()
231 | val fileProgramBinary = File("/sdcard/program_binary.bin")
232 | return GLProgramBinary(ByteBuffer.wrap(fileProgramBinary.readBytes()), lines[0].toInt(), lines[1].toInt())
233 | }
234 |
235 | class GLProgramBinary(val binaryBuffer : ByteBuffer, val length : Int, val format : Int)
236 |
237 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleColorBlendRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import io.github.kenneycode.openglespro.Util
6 | import java.nio.ByteBuffer
7 | import java.nio.ByteOrder
8 | import java.nio.FloatBuffer
9 | import javax.microedition.khronos.egl.EGLConfig
10 | import javax.microedition.khronos.opengles.GL10
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个使用颜色混合的例子
19 | * This sample demonstrates color blend
20 | *
21 | **/
22 |
23 | class SampleColorBlendRenderer : GLSurfaceView.Renderer {
24 |
25 | private val vertexShaderCode =
26 | "#version 300 es\n" +
27 | "precision mediump float;\n" +
28 | "layout(location = 0) in vec4 a_position;\n" +
29 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
30 | "out vec2 v_textureCoordinate;\n" +
31 | "void main() {\n" +
32 | " v_textureCoordinate = a_textureCoordinate;\n" +
33 | " gl_Position = a_position;\n" +
34 | "}"
35 |
36 | private val fragmentShaderCode =
37 | "#version 300 es\n" +
38 | "precision mediump float;\n" +
39 | "layout(location = 0) out vec4 fragColor;\n" +
40 | "in vec2 v_textureCoordinate;\n" +
41 | "uniform sampler2D u_texture;\n" +
42 | "void main() {\n" +
43 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
44 | "}"
45 |
46 | // GLSurfaceView的宽高
47 | // The width and height of GLSurfaceView
48 | private var glSurfaceViewWidth = 0
49 | private var glSurfaceViewHeight = 0
50 |
51 | // 纹理顶点数据
52 | // The vertex data of the texture
53 | private val vertexData0 = floatArrayOf(-1f, -1f, -1f, 1f, 1f, 1f, -1f, -1f, 1f, 1f, 1f, -1f)
54 | private val vertexData1 = floatArrayOf(-0.5f, -0.3f, -0.5f, 0.35f, 0.5f, 0.35f, -0.5f, -0.3f, 0.5f, 0.35f, 0.5f, -0.3f)
55 | private lateinit var vertexDataBuffer0 : FloatBuffer
56 | private lateinit var vertexDataBuffer1 : FloatBuffer
57 | private val VERTEX_COMPONENT_COUNT = 2
58 |
59 | // 纹理坐标
60 | // The texture coordinate
61 | private val textureCoordinateData = floatArrayOf(0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 1f, 1f)
62 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
63 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 2
64 |
65 | private var programId = 0
66 |
67 | // 图片texture
68 | // image texture
69 | private var imageTexture0 = 0
70 | private var imageTexture1 = 0
71 |
72 |
73 | override fun onDrawFrame(gl: GL10?) {
74 |
75 | // 渲染底图
76 | // Render the background image
77 | bindGLProgram(programId, imageTexture0, vertexDataBuffer0)
78 | render()
79 |
80 | // 渲染带透明部分的图
81 | // Render the image with transparent parts
82 | bindGLProgram(programId, imageTexture1, vertexDataBuffer1)
83 | render()
84 |
85 | }
86 |
87 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
88 |
89 | // 记录GLSurfaceView的宽高
90 | // Record the width and height of the GLSurfaceView
91 | glSurfaceViewWidth = width
92 | glSurfaceViewHeight = height
93 |
94 | }
95 |
96 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
97 |
98 | initData()
99 |
100 | programId = createGLProgram(vertexShaderCode, fragmentShaderCode)
101 |
102 | }
103 |
104 | private fun initData() {
105 |
106 | // 将三角形顶点数据放入buffer中
107 | // Put the triangle vertex data into the vertexDataBuffer
108 | vertexDataBuffer0 = ByteBuffer.allocateDirect(vertexData0.size * java.lang.Float.SIZE / 8)
109 | .order(ByteOrder.nativeOrder())
110 | .asFloatBuffer()
111 | vertexDataBuffer0.put(vertexData0)
112 | vertexDataBuffer0.position(0)
113 | vertexDataBuffer1 = ByteBuffer.allocateDirect(vertexData1.size * java.lang.Float.SIZE / 8)
114 | .order(ByteOrder.nativeOrder())
115 | .asFloatBuffer()
116 | vertexDataBuffer1.put(vertexData1)
117 | vertexDataBuffer1.position(0)
118 |
119 | // 将纹理坐标数据放入buffer中
120 | // Put the texture coordinates into the textureCoordinateDataBuffer
121 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE / 8)
122 | .order(ByteOrder.nativeOrder())
123 | .asFloatBuffer()
124 | textureCoordinateDataBuffer.put(textureCoordinateData)
125 | textureCoordinateDataBuffer.position(0)
126 |
127 | // 创建图片纹理
128 | // Create texture
129 | val textures = IntArray(2)
130 | GLES30.glGenTextures(textures.size, textures, 0)
131 | imageTexture0 = textures[0]
132 | imageTexture1 = textures[1]
133 |
134 | loadImageIntoTexture("image_2.jpg", imageTexture0)
135 | loadImageIntoTexture("image_3.png", imageTexture1)
136 |
137 | Util.checkGLError()
138 |
139 | }
140 |
141 | private fun createGLProgram(vertexShaderCode : String, fragmentShaderCode : String) : Int {
142 |
143 | // 创建GL程序
144 | // Create the GL program
145 | val programId = GLES30.glCreateProgram()
146 |
147 | // 加载、编译vertex shader和fragment shader
148 | // Load and compile vertex shader and fragment shader
149 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
150 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
151 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
152 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
153 | GLES30.glCompileShader(vertexShader)
154 | GLES30.glCompileShader(fragmentShader)
155 |
156 | // 将shader程序附着到GL程序上
157 | // Attach the compiled shaders to the GL program
158 | GLES30.glAttachShader(programId, vertexShader)
159 | GLES30.glAttachShader(programId, fragmentShader)
160 |
161 | // 链接GL程序
162 | // Link the GL program
163 | GLES30.glLinkProgram(programId)
164 |
165 | Util.checkGLError()
166 |
167 | return programId
168 |
169 | }
170 |
171 | private fun bindGLProgram(programId : Int, texture : Int, vertexDataBuffer : FloatBuffer) {
172 |
173 | // 应用GL程序
174 | // Use the GL program
175 | GLES30.glUseProgram(programId)
176 |
177 | // 获取字段a_position在shader中的位置
178 | // Get the location of a_position in the shader
179 | val aPositionLocation = GLES30.glGetAttribLocation(programId, "a_position")
180 |
181 | // 启动对应位置的参数
182 | // Enable the parameter of the location
183 | GLES30.glEnableVertexAttribArray(aPositionLocation)
184 |
185 | // 指定a_position所使用的顶点数据
186 | // Specify the data of a_position
187 | GLES30.glVertexAttribPointer(aPositionLocation, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
188 |
189 | // 获取字段a_textureCoordinate在shader中的位置
190 | // Get the location of a_textureCoordinate in the shader
191 | val aTextureCoordinateLocation = GLES30.glGetAttribLocation(programId, "a_textureCoordinate")
192 |
193 | // 启动对应位置的参数
194 | // Enable the parameter of the location
195 | GLES30.glEnableVertexAttribArray(aTextureCoordinateLocation)
196 |
197 | // 指定a_textureCoordinate所使用的顶点数据
198 | // Specify the data of a_textureCoordinate
199 | GLES30.glVertexAttribPointer(aTextureCoordinateLocation, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
200 |
201 | // 绑定纹理并设置u_texture参数
202 | // Bind the texture and set the u_texture parameter
203 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texture)
204 | val uTextureLocation = GLES30.glGetUniformLocation(programId, "u_texture")
205 | GLES30.glUniform1i(uTextureLocation, 0)
206 |
207 | }
208 |
209 | private fun loadImageIntoTexture(imageFileName: String, texture: Int) {
210 |
211 | // 设置纹理参数
212 | // Set texture parameters
213 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texture)
214 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
215 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
216 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
217 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
218 |
219 | // 解码图片并加载到纹理中
220 | // Decode the image and load it into texture
221 | val bitmap = Util.decodeBitmapFromAssets(imageFileName)
222 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
223 | bitmap.copyPixelsToBuffer(b)
224 | b.position(0)
225 | GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width, bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
226 |
227 | }
228 |
229 | private fun render() {
230 |
231 | // 设置视口,这里设置为整个GLSurfaceView区域
232 | // Set the viewport to the full GLSurfaceView
233 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
234 |
235 | // 启用颜色混合
236 | // Enable color blend
237 | GLES30.glEnable(GLES30.GL_BLEND)
238 |
239 | // 设置混合方式
240 | // Set blend functions
241 | GLES30.glBlendFunc(GLES30.GL_ONE, GLES30.GL_ONE)
242 |
243 | // 调用draw方法用TRIANGLES的方式执行渲染,顶点数量为6个
244 | // Call the draw method with GL_TRIANGLES to render 6 vertices
245 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 6)
246 |
247 | }
248 |
249 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleFenceSyncRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.graphics.Bitmap
4 | import android.opengl.*
5 | import android.os.Handler
6 | import android.os.HandlerThread
7 | import android.widget.ImageView
8 | import io.github.kenneycode.openglespro.Util
9 | import java.nio.ByteBuffer
10 | import java.nio.ByteOrder
11 | import java.nio.FloatBuffer
12 | import javax.microedition.khronos.egl.EGLConfig
13 | import javax.microedition.khronos.opengles.GL10
14 |
15 | /**
16 | *
17 | * Coded by kenney
18 | *
19 | * http://www.github.com/kenneycode
20 | *
21 | * 这是一个使用栅栏做GL命令同步的例子
22 | * This is a sample of using fence to synchronize the GL commands
23 | *
24 | **/
25 |
26 | class SampleFenceSyncRenderer(val imageView : ImageView) : GLSurfaceView.Renderer {
27 |
28 | private val vertexShaderCode =
29 | "#version 300 es\n" +
30 | "precision mediump float;\n" +
31 | "layout(location = 0) in vec4 a_Position;\n" +
32 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
33 | "out vec2 v_textureCoordinate;\n" +
34 | "void main() {\n" +
35 | " v_textureCoordinate = a_textureCoordinate;\n" +
36 | " gl_Position = a_Position;\n" +
37 | "}"
38 |
39 | private val fragmentShaderCode =
40 | "#version 300 es\n" +
41 | "precision mediump float;\n" +
42 | "layout(location = 0) out vec4 fragColor;\n" +
43 | "in vec2 v_textureCoordinate;\n" +
44 | "uniform sampler2D u_texture;\n" +
45 | "void main() {\n" +
46 | " float offset = 0.01;\n" +
47 | " vec4 colorCenter = texture(u_texture, vec2(v_textureCoordinate.x, v_textureCoordinate.y));\n" +
48 | " vec4 colorLeft = texture(u_texture, vec2(v_textureCoordinate.x - offset, v_textureCoordinate.y));\n" +
49 | " vec4 colorTop = texture(u_texture, vec2(v_textureCoordinate.x, v_textureCoordinate.y + offset));\n" +
50 | " vec4 colorRight = texture(u_texture, vec2(v_textureCoordinate.x + offset, v_textureCoordinate.y));\n" +
51 | " vec4 colorBottom = texture(u_texture, vec2(v_textureCoordinate.x, v_textureCoordinate.y - offset));\n" +
52 | " fragColor = (colorCenter + colorLeft + colorTop + colorRight + colorBottom) / 5.0;\n" +
53 | "}"
54 | // 三角形顶点数据
55 | // The vertex data of a triangle
56 | private val vertexData = floatArrayOf(-1f, -1f, -1f, 1f, 1f, 1f, -1f, -1f, 1f, 1f, 1f, -1f)
57 | private val textureCoordinateData = floatArrayOf(0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 1f, 1f)
58 |
59 | lateinit var vertexDataBuffer : FloatBuffer
60 | lateinit var textureCoordinateDataBuffer : FloatBuffer
61 |
62 | private var glSurfaceViewWidth = 0
63 | private var glSurfaceViewHeight = 0
64 |
65 | private val LOCATION_ATTRBUTE_POSITION = 0
66 | private val LOCATION_ATTRBUTE_TEXTURE_COORDINATE = 1
67 |
68 | private val LOCATION_UNIFORM_POSITION = 0
69 |
70 | // 每个顶点的成份数
71 | // The num of components of per vertex
72 | private val VERTEX_COMPONENT_COUNT = 2
73 |
74 | private var frameBuffer = 0
75 | private var sharedTexture = 0
76 |
77 | private lateinit var otherThreadHandler : Handler
78 |
79 | var flag = false
80 | var imageTexture = 0
81 |
82 | override fun onDrawFrame(gl: GL10?) {
83 | GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
84 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, sharedTexture)
85 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBuffer)
86 | GLES30.glFramebufferTexture2D(
87 | GLES30.GL_FRAMEBUFFER,
88 | GLES30.GL_COLOR_ATTACHMENT0,
89 | GLES30.GL_TEXTURE_2D,
90 | sharedTexture,
91 | 0
92 | )
93 |
94 | // 设置清屏颜色
95 | // Set the color which the screen will be cleared to
96 | GLES30.glClearColor(0f, 0f, 0f, 1f)
97 |
98 | // 清屏
99 | // Clear the screen
100 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
101 |
102 | // 设置视口,这里设置为整个GLSurfaceView区域
103 | // Set the viewport to the full GLSurfaceView
104 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
105 |
106 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
107 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
108 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE)
109 | .order(ByteOrder.nativeOrder())
110 | .asFloatBuffer()
111 | vertexDataBuffer.put(vertexData)
112 | vertexDataBuffer.position(0)
113 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRBUTE_POSITION)
114 | GLES30.glVertexAttribPointer(LOCATION_ATTRBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
115 |
116 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE)
117 | .order(ByteOrder.nativeOrder())
118 | .asFloatBuffer()
119 | textureCoordinateDataBuffer.put(textureCoordinateData)
120 | textureCoordinateDataBuffer.position(0)
121 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRBUTE_TEXTURE_COORDINATE)
122 | GLES30.glVertexAttribPointer(LOCATION_ATTRBUTE_TEXTURE_COORDINATE, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
123 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, textureCoordinateData.size / VERTEX_COMPONENT_COUNT)
124 |
125 | // 向OpenGL的Command Buffer中插入一个fence
126 | // Insert a fence into the OpenGL command buffer
127 | val fenceSyncObject = GLES30.glFenceSync(GLES30.GL_SYNC_GPU_COMMANDS_COMPLETE, 0)
128 |
129 | // 在另一个线程中读取当前线程的渲染结果
130 | // Read the render result in the other thread
131 | otherThreadHandler.post {
132 | if (!flag) {
133 |
134 | // 等待fence前的OpenGL命令执行完毕
135 | // Waiting for completion of the OpenGL commands before our fence
136 | GLES30.glWaitSync(fenceSyncObject, 0, GLES30.GL_TIMEOUT_IGNORED)
137 |
138 | // 删除fence同步对象
139 | // Delete the fence sync object
140 | GLES30.glDeleteSync(fenceSyncObject)
141 |
142 | val frameBuffers = IntArray(1)
143 | GLES30.glGenFramebuffers(frameBuffers.size, frameBuffers, 0)
144 | GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
145 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, sharedTexture)
146 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBuffers[0])
147 | GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, sharedTexture, 0)
148 | val buffer = ByteBuffer.wrap(ByteArray(glSurfaceViewWidth * glSurfaceViewHeight * 4))
149 | GLES30.glReadPixels(0, 0, glSurfaceViewWidth, glSurfaceViewHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, buffer)
150 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
151 | val bitmap = Bitmap.createBitmap(glSurfaceViewWidth, glSurfaceViewHeight, Bitmap.Config.ARGB_8888)
152 | buffer.position(0)
153 | bitmap.copyPixelsFromBuffer(buffer)
154 | flag = true
155 |
156 | // 将读取到的渲染结果显示到一个ImageView上
157 | // Display the read render result on a ImageView
158 | imageView.post {
159 | imageView.setImageBitmap(bitmap)
160 | }
161 | }
162 |
163 | }
164 |
165 | // 将frame buffer绑回0号,将渲染结果同时也显示到屏幕上
166 | // Bind frame buffer to 0# and also render the result on screen
167 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
168 |
169 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
170 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
171 |
172 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
173 |
174 | // 清屏
175 | // Clear the screen
176 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
177 |
178 | // 设置视口,这里设置为整个GLSurfaceView区域
179 | // Set the viewport to the full GLSurfaceView
180 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
181 |
182 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
183 | }
184 |
185 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
186 | // 记录GLSurfaceView的宽高
187 | // Record the width and height of the GLSurfaceView
188 | glSurfaceViewWidth = width
189 | glSurfaceViewHeight = height
190 |
191 | GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
192 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, sharedTexture)
193 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBuffer)
194 | GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, sharedTexture, 0)
195 | GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, glSurfaceViewWidth, glSurfaceViewHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null)
196 | }
197 |
198 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
199 | // 创建GL程序
200 | // Create GL program
201 | val programId = GLES30.glCreateProgram()
202 |
203 | // 加载、编译vertex shader和fragment shader
204 | // Load and compile vertex shader and fragment shader
205 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
206 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
207 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
208 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
209 | GLES30.glCompileShader(vertexShader)
210 | GLES30.glCompileShader(fragmentShader)
211 |
212 | // 将shader程序附着到GL程序上
213 | // Attach the compiled shaders to the GL program
214 | GLES30.glAttachShader(programId, vertexShader)
215 | GLES30.glAttachShader(programId, fragmentShader)
216 |
217 | // 链接GL程序
218 | // Link the GL program
219 | GLES30.glLinkProgram(programId)
220 |
221 | // 将三角形顶点数据放入buffer中
222 | // Put the triangle vertex data into the vertexDataBuffer
223 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE)
224 | .order(ByteOrder.nativeOrder())
225 | .asFloatBuffer()
226 | vertexDataBuffer.put(vertexData)
227 | vertexDataBuffer.position(0)
228 |
229 | // 应用GL程序
230 | // Use the GL program
231 | GLES30.glUseProgram(programId)
232 |
233 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE)
234 | .order(ByteOrder.nativeOrder())
235 | .asFloatBuffer()
236 | textureCoordinateDataBuffer.put(textureCoordinateData)
237 | textureCoordinateDataBuffer.position(0)
238 |
239 | val textures = IntArray(1)
240 | GLES30.glGenTextures(textures.size, textures, 0)
241 |
242 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
243 | val bitmap = Util.decodeBitmapFromAssets("image_0.jpg")
244 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0])
245 | imageTexture = textures[0]
246 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
247 | bitmap.copyPixelsToBuffer(b)
248 | b.position(0)
249 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
250 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
251 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
252 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
253 | GLES30.glTexImage2D(
254 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width,
255 | bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
256 | bitmap.recycle()
257 | GLES30.glUniform1i(LOCATION_UNIFORM_POSITION, 0)
258 |
259 | val sharedTextures = IntArray(1)
260 | GLES30.glGenTextures(sharedTextures.size, sharedTextures, 0)
261 | sharedTexture = sharedTextures[0]
262 |
263 | val frameBuffers = IntArray(1)
264 | GLES30.glGenFramebuffers(frameBuffers.size, frameBuffers, 0)
265 | frameBuffer = frameBuffers[0]
266 |
267 | // 创建另一个线程
268 | // Create another thread
269 | val thread = HandlerThread("OtherThread")
270 | thread.start()
271 | otherThreadHandler = Handler(thread.looper)
272 |
273 | // 给创建的线程配置EGL环境,与当前GL线程做共享EGL Context
274 | // Configure EGL environment for the created thread and share the current thread's EGL context to it
275 | val sharedContext = EGL14.eglGetCurrentContext()
276 | otherThreadHandler.post {
277 | val eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
278 | if (eglDisplay === EGL14.EGL_NO_DISPLAY) {
279 | throw RuntimeException("unable to get EGL14 display")
280 | }
281 | if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
282 | throw RuntimeException()
283 | }
284 | val version = IntArray(2)
285 | if (!EGL14.eglInitialize(eglDisplay, version, 0, version, 1)) {
286 | throw RuntimeException()
287 | }
288 | if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
289 | throw RuntimeException()
290 | }
291 | val attribList = intArrayOf(
292 | EGL14.EGL_RED_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_ALPHA_SIZE, 8,
293 | EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT or EGLExt.EGL_OPENGL_ES3_BIT_KHR, EGL14.EGL_NONE, 0,
294 | EGL14.EGL_NONE
295 | )
296 | val eglConfig = arrayOfNulls(1)
297 | val numConfigs = IntArray(1)
298 | if (!EGL14.eglChooseConfig(
299 | eglDisplay, attribList, 0, eglConfig, 0, eglConfig.size,
300 | numConfigs, 0
301 | )) {
302 | throw RuntimeException()
303 | }
304 | if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
305 | throw RuntimeException()
306 | }
307 | val myContext = EGL14.eglCreateContext(
308 | eglDisplay, eglConfig[0], sharedContext,
309 | intArrayOf(EGL14.EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE), 0
310 | )
311 | if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
312 | throw RuntimeException()
313 | }
314 | val values = IntArray(1)
315 | EGL14.eglQueryContext(
316 | eglDisplay, myContext, EGL14.EGL_CONTEXT_CLIENT_VERSION,
317 | values, 0
318 | )
319 | val pBufferSurface = EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig[0], attribList, 0)
320 | if (!EGL14.eglMakeCurrent(eglDisplay, pBufferSurface, pBufferSurface, myContext)) {
321 | throw RuntimeException()
322 | }
323 | }
324 | }
325 |
326 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleMatrixTransformRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import android.opengl.Matrix
6 | import io.github.kenneycode.openglespro.Util
7 | import java.nio.ByteBuffer
8 | import java.nio.ByteOrder
9 | import java.nio.FloatBuffer
10 | import javax.microedition.khronos.egl.EGLConfig
11 | import javax.microedition.khronos.opengles.GL10
12 |
13 | /**
14 | *
15 | * Coded by kenney
16 | *
17 | * http://www.github.com/kenneycode
18 | *
19 | * 这是一个演示矩阵变换的例子,包括模型矩阵、视图矩阵和投影矩阵
20 | * This sample demonstrates matrix transform, including model matrix, view matrix and project matrix
21 | *
22 | **/
23 |
24 | class SampleMatrixTransformRenderer : GLSurfaceView.Renderer, OnParameterChangeCallback {
25 |
26 | private val vertexShaderCode =
27 | "#version 300 es\n" +
28 | "precision mediump float;\n" +
29 | "layout(location = 0) in vec4 a_position;\n" +
30 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
31 | "layout(location = 2) uniform mat4 u_mvp;\n" +
32 | "out vec2 v_textureCoordinate;\n" +
33 | "void main() {\n" +
34 | " v_textureCoordinate = a_textureCoordinate;\n" +
35 | " gl_Position = u_mvp * a_position;\n" +
36 | "}"
37 |
38 | private val fragmentShaderCode =
39 | "#version 300 es\n" +
40 | "precision mediump float;\n" +
41 | "precision mediump sampler2D;\n" +
42 | "layout(location = 0) out vec4 fragColor;\n" +
43 | "layout(location = 0) uniform sampler2D u_texture;\n" +
44 | "in vec2 v_textureCoordinate;\n" +
45 | "void main() {\n" +
46 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
47 | "}"
48 |
49 | // GLSurfaceView的宽高
50 | // The width and height of GLSurfaceView
51 | private var glSurfaceViewWidth = 0
52 | private var glSurfaceViewHeight = 0
53 |
54 | // 三角形顶点数据
55 | // The vertex data of a triangle
56 | private val vertexData = floatArrayOf(
57 | // 正面
58 | // front face
59 | -1f, -1f, 1f,
60 | -1f, 1f, 1f,
61 | 1f, 1f, 1f,
62 | -1f, -1f, 1f,
63 | 1f, 1f, 1f,
64 | 1f, -1f, 1f,
65 | // 背面
66 | // back face
67 | -1f, -1f, -1f,
68 | -1f, 1f, -1f,
69 | 1f, 1f, -1f,
70 | -1f, -1f, -1f,
71 | 1f, 1f, -1f,
72 | 1f, -1f, -1f,
73 | // 顶面
74 | // Top face
75 | -1f, 1f, -1f,
76 | -1f, 1f, 1f,
77 | 1f, 1f, 1f,
78 | -1f, 1f, -1f,
79 | 1f, 1f, 1f,
80 | 1f, 1f, -1f,
81 | // 底面
82 | // Bottom face
83 | -1f, -1f, -1f,
84 | -1f, -1f, 1f,
85 | 1f, -1f, 1f,
86 | -1f, -1f, -1f,
87 | 1f, -1f, 1f,
88 | 1f, -1f, -1f,
89 | // // 左面
90 | // // Left face
91 | -1f, -1f, -1f,
92 | -1f, -1f, 1f,
93 | -1f, 1f, 1f,
94 | -1f, -1f, -1f,
95 | -1f, 1f, 1f,
96 | -1f, 1f, -1f,
97 | // 右面
98 | // Right face
99 | 1f, -1f, -1f,
100 | 1f, -1f, 1f,
101 | 1f, 1f, 1f,
102 | 1f, -1f, -1f,
103 | 1f, 1f, 1f,
104 | 1f, 1f, -1f
105 | )
106 | private val VERTEX_COMPONENT_COUNT = 3
107 | private lateinit var vertexDataBuffer : FloatBuffer
108 |
109 | // 纹理坐标
110 | // The texture coordinate
111 | private val textureCoordinateData = floatArrayOf(
112 | 0f, 1f,
113 | 0f, 0f,
114 | 1f, 0f,
115 | 0f, 1f,
116 | 1f, 0f,
117 | 1f, 1f,
118 | 0f, 1f,
119 | 0f, 0f,
120 | 1f, 0f,
121 | 0f, 1f,
122 | 1f, 0f,
123 | 1f, 1f,
124 | 0f, 1f,
125 | 0f, 0f,
126 | 1f, 0f,
127 | 0f, 1f,
128 | 1f, 0f,
129 | 1f, 1f,
130 | 0f, 1f,
131 | 0f, 0f,
132 | 1f, 0f,
133 | 0f, 1f,
134 | 1f, 0f,
135 | 1f, 1f,
136 | 0f, 1f,
137 | 0f, 0f,
138 | 1f, 0f,
139 | 0f, 1f,
140 | 1f, 0f,
141 | 1f, 1f,
142 | 0f, 1f,
143 | 0f, 0f,
144 | 1f, 0f,
145 | 0f, 1f,
146 | 1f, 0f,
147 | 1f, 1f
148 | )
149 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 2
150 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
151 |
152 | // 要渲染的图片纹理
153 | // The texture of the image to be rendered
154 | private var imageTexture = 0
155 |
156 | // a_position、a_textureCoordinate和u_texture的位置,与shader中写的对应
157 | // The location of a_position、a_textureCoordinate and u_texture, corresponding with which in shader
158 | private val LOCATION_ATTRIBUTE_POSITION = 0
159 | private val LOCATION_ATTRIBUTE_TEXTURE_COORDINATE = 1
160 | private val LOCATION_UNIFORM_MVP = 2
161 | private val LOCATION_UNIFORM_TEXTURE = 0
162 |
163 | var translateX = 0f
164 | var translateY = 0f
165 | var translateZ = 0f
166 | var rotateX = 0f
167 | var rotateY = 0f
168 | var rotateZ = 0f
169 | var scaleX = 1f
170 | var scaleY = 1f
171 | var scaleZ = 1f
172 | var cameraPositionX = 0f
173 | var cameraPositionY = 0f
174 | var cameraPositionZ = 5f
175 | var lookAtX = 0f
176 | var lookAtY = 0f
177 | var lookAtZ = 0f
178 | var cameraUpX = 0f
179 | var cameraUpY = 1f
180 | var cameraUpZ = 0f
181 | var nearPlaneLeft = -1f
182 | var nearPlaneRight = 1f
183 | var nearPlaneBottom = -1f
184 | var nearPlaneTop = 1f
185 | var nearPlane = 2f
186 | var farPlane = 100f
187 |
188 | override fun onDrawFrame(gl: GL10?) {
189 |
190 | // 设置清屏颜色
191 | // Set the color which the screen will be cleared to
192 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
193 |
194 | // 清屏
195 | // Clear the screen
196 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
197 |
198 | GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT)
199 |
200 | // 设置视口,这里设置为整个GLSurfaceView区域
201 | // Set the viewport to the full GLSurfaceView
202 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
203 |
204 | // 设置好状态,准备渲染
205 | // Set the status before rendering
206 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
207 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
208 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
209 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
210 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
211 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
212 |
213 | val mvpMatrix = getIdentity()
214 | val translateMatrix = getIdentity()
215 | val rotateMatrix = getIdentity()
216 | val scaleMatrix = getIdentity()
217 | val modelMatrix = getIdentity()
218 | val viewMatrix = getIdentity()
219 | val projectMatrix = getIdentity()
220 |
221 | // 模型矩阵计算
222 | // Calculate the Model matrix
223 | Matrix.translateM(translateMatrix, 0, translateX, translateY, translateZ)
224 | Matrix.rotateM(rotateMatrix, 0, rotateX, 1f, 0f, 0f)
225 | Matrix.rotateM(rotateMatrix, 0, rotateY, 0f, 1f, 0f)
226 | Matrix.rotateM(rotateMatrix, 0, rotateZ, 0f, 0f, 1f)
227 | Matrix.scaleM(scaleMatrix, 0, scaleX, scaleY, scaleZ)
228 | Matrix.multiplyMM(modelMatrix, 0, rotateMatrix, 0, scaleMatrix, 0)
229 | Matrix.multiplyMM(modelMatrix, 0, modelMatrix, 0, translateMatrix, 0)
230 |
231 | // 视图矩阵计算
232 | // Calculate the View matrix
233 | Matrix.setLookAtM(
234 | viewMatrix,
235 | 0,
236 | cameraPositionX, cameraPositionY, cameraPositionZ,
237 | lookAtX, lookAtY, lookAtZ,
238 | cameraUpX, cameraUpY, cameraUpZ
239 | )
240 |
241 | // 透视投影矩阵计算
242 | // Calculate the Project matrix
243 | Matrix.frustumM(
244 | projectMatrix,
245 | 0,
246 | nearPlaneLeft, nearPlaneRight, nearPlaneBottom, nearPlaneTop,
247 | nearPlane,
248 | farPlane
249 | )
250 |
251 | // MVP矩阵计算
252 | // Calculate the MVP matrix
253 | Matrix.multiplyMM(mvpMatrix, 0, viewMatrix, 0, modelMatrix, 0)
254 | Matrix.multiplyMM(mvpMatrix, 0, projectMatrix, 0, mvpMatrix, 0)
255 |
256 | GLES30.glUniformMatrix4fv(LOCATION_UNIFORM_MVP, 1, false, mvpMatrix, 0)
257 |
258 | // 调用draw方法用TRIANGLES的方式执行渲染,顶点数量为3个
259 | // Call the draw method with GL_TRIANGLES to render 3 vertices
260 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
261 |
262 | }
263 |
264 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
265 |
266 | // 记录GLSurfaceView的宽高
267 | // Record the width and height of the GLSurfaceView
268 | glSurfaceViewWidth = width
269 | glSurfaceViewHeight = height
270 | nearPlaneBottom = -height.toFloat() / width
271 | nearPlaneTop = height.toFloat() / width
272 |
273 | }
274 |
275 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
276 |
277 | // 创建GL程序
278 | // Create GL program
279 | val programId = GLES30.glCreateProgram()
280 |
281 | // 加载、编译vertex shader和fragment shader
282 | // Load and compile vertex shader and fragment shader
283 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
284 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
285 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
286 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
287 | GLES30.glCompileShader(vertexShader)
288 | GLES30.glCompileShader(fragmentShader)
289 |
290 | // 将shader程序附着到GL程序上
291 | // Attach the compiled shaders to the GL program
292 | GLES30.glAttachShader(programId, vertexShader)
293 | GLES30.glAttachShader(programId, fragmentShader)
294 |
295 | // 链接GL程序
296 | // Link the GL program
297 | GLES30.glLinkProgram(programId)
298 |
299 | // 应用GL程序
300 | // Use the GL program
301 | GLES30.glUseProgram(programId)
302 |
303 | // 将三角形顶点数据放入buffer中
304 | // Put the triangle vertex data into the vertexDataBuffer
305 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
306 | .order(ByteOrder.nativeOrder())
307 | .asFloatBuffer()
308 | vertexDataBuffer.put(vertexData)
309 | vertexDataBuffer.position(0)
310 |
311 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_POSITION,而无需像OpenGL 2.0那样需要先获取参数的location
312 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_POSITION, while in OpenGL 2.0 we have to query the location of the parameter
313 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
314 |
315 | // 指定a_position所使用的顶点数据
316 | // Specify the data of a_position
317 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
318 |
319 | // 将纹理坐标数据放入buffer中
320 | // Put the texture coordinates into the textureCoordinateDataBuffer
321 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE / 8)
322 | .order(ByteOrder.nativeOrder())
323 | .asFloatBuffer()
324 | textureCoordinateDataBuffer.put(textureCoordinateData)
325 | textureCoordinateDataBuffer.position(0)
326 |
327 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_TEXTURE_COORDINATE,而无需像OpenGL 2.0那样需要先获取参数的location
328 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, while in OpenGL 2.0 we have to query the location of the parameter
329 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
330 |
331 | // 指定a_textureCoordinate所使用的顶点数据
332 | // Specify the data of a_textureCoordinate
333 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
334 |
335 | // 创建图片纹理
336 | // Create texture for image
337 | val textures = IntArray(1)
338 | GLES30.glGenTextures(textures.size, textures, 0)
339 | imageTexture = textures[0]
340 |
341 | // 将图片解码并加载到纹理中
342 | // Decode image and load it into texture
343 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
344 | val bitmap = Util.decodeBitmapFromAssets("image_2.jpg")
345 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
346 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
347 | bitmap.copyPixelsToBuffer(b)
348 | b.position(0)
349 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
350 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
351 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
352 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
353 | GLES30.glTexImage2D(
354 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width,
355 | bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
356 | bitmap.recycle()
357 |
358 | // 启动对应位置的参数,这里直接使用LOCATION_UNIFORM_TEXTURE,而无需像OpenGL 2.0那样需要先获取参数的location
359 | // Enable the parameter of the location. Here we can simply use LOCATION_UNIFORM_TEXTURE, while in OpenGL 2.0 we have to query the location of the parameter
360 | GLES30.glUniform1i(LOCATION_UNIFORM_TEXTURE, 0)
361 |
362 | GLES30.glEnable(GLES30.GL_DEPTH_TEST)
363 |
364 | }
365 |
366 | fun getIdentity(): FloatArray {
367 | return floatArrayOf(
368 | 1f, 0f, 0f, 0f,
369 | 0f, 1f, 0f, 0f,
370 | 0f, 0f, 1f, 0f,
371 | 0f, 0f, 0f, 1f
372 | )
373 | }
374 |
375 | override fun onParameterChange(parameterKey: String, parameterValue: Float) {
376 | when (parameterKey) {
377 | "translateX" -> { translateX = parameterValue }
378 | "translateY" -> { translateY = parameterValue }
379 | "translateZ" -> { translateZ = parameterValue }
380 | "rotateX" -> { rotateX = parameterValue }
381 | "rotateY" -> { rotateY = parameterValue }
382 | "rotateZ" -> { rotateZ = parameterValue }
383 | "scaleX" -> { scaleX = parameterValue }
384 | "scaleY" -> { scaleY = parameterValue }
385 | "scaleZ" -> { scaleZ = parameterValue }
386 | "cameraPositionX" -> { cameraPositionX = parameterValue }
387 | "cameraPositionY" -> { cameraPositionY = parameterValue }
388 | "cameraPositionZ" -> { cameraPositionZ = parameterValue }
389 | "lookAtX" -> { lookAtX = parameterValue }
390 | "lookAtY" -> { lookAtY = parameterValue }
391 | "lookAtZ" -> { lookAtZ = parameterValue }
392 | "cameraUpX" -> { cameraUpX = parameterValue }
393 | "cameraUpY" -> { cameraUpY = parameterValue }
394 | "cameraUpZ" -> { cameraUpZ = parameterValue }
395 | "nearPlaneLeft" -> { nearPlaneLeft = parameterValue }
396 | "nearPlaneRight" -> { nearPlaneRight = parameterValue }
397 | "nearPlaneBottom" -> { nearPlaneBottom = parameterValue }
398 | "nearPlaneTop" -> { nearPlaneTop = parameterValue }
399 | "nearPlane" -> { nearPlane = parameterValue }
400 | "farPlane" -> { farPlane = parameterValue }
401 | }
402 | }
403 |
404 | override fun onParameterReset() {
405 | translateX = 0f
406 | translateY = 0f
407 | translateZ = 0f
408 | rotateX = 0f
409 | rotateY = 0f
410 | rotateZ = 0f
411 | scaleX = 1f
412 | scaleY = 1f
413 | scaleZ = 1f
414 | cameraPositionX = 0f
415 | cameraPositionY = 0f
416 | cameraPositionZ = 5f
417 | lookAtX = 0f
418 | lookAtY = 0f
419 | lookAtZ = 0f
420 | cameraUpX = 0f
421 | cameraUpY = 1f
422 | cameraUpZ = 0f
423 | nearPlaneLeft = -1f
424 | nearPlaneRight = 1f
425 | nearPlaneBottom = -glSurfaceViewHeight.toFloat() / glSurfaceViewWidth
426 | nearPlaneTop = glSurfaceViewHeight.toFloat() / glSurfaceViewWidth
427 | nearPlane = 2f
428 | farPlane = 100f
429 | }
430 |
431 | }
432 |
433 | interface OnParameterChangeCallback {
434 | fun onParameterChange(parameterKey: String, parameterValue: Float)
435 | fun onParameterReset()
436 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleMultiRenderTargetRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import android.util.Log
6 | import io.github.kenneycode.openglespro.Util
7 | import java.nio.ByteBuffer
8 | import java.nio.ByteOrder
9 | import java.nio.FloatBuffer
10 | import java.nio.IntBuffer
11 | import javax.microedition.khronos.egl.EGLConfig
12 | import javax.microedition.khronos.opengles.GL10
13 |
14 | /**
15 | *
16 | * Coded by kenney
17 | *
18 | * http://www.github.com/kenneycode
19 | *
20 | * 这是多渲染目标的例子,可以一次渲染到多个纹理上
21 | * This is a sample of multiple render targets, with which we can render to multiple textures at a time
22 | *
23 | **/
24 |
25 | class SampleMultiRenderTargetRenderer : GLSurfaceView.Renderer {
26 |
27 | private val vertexShaderCode =
28 | "#version 300 es\n" +
29 | "precision mediump float;\n" +
30 | "layout(location = 0) in vec4 a_position;\n" +
31 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
32 | "out vec2 v_textureCoordinate;\n" +
33 | "void main() {\n" +
34 | " v_textureCoordinate = a_textureCoordinate;\n" +
35 | " gl_Position = a_position;\n" +
36 | "}"
37 |
38 | // 多渲染目标fragment shader,这里我们输出三种效果,分别将纹理的R、G、B三个通道设为1.0
39 | // The fragment shader of multiple render targets. Here we render 3 effects, which set the R, G and B to 1.0 respectively
40 | private val fragmentShaderMRTCode =
41 | "#version 300 es\n" +
42 | "precision mediump float;\n" +
43 | "layout(location = 0) out vec4 fragColor0;\n" +
44 | "layout(location = 1) out vec4 fragColor1;\n" +
45 | "layout(location = 2) out vec4 fragColor2;\n" +
46 | "uniform sampler2D u_texture;\n" +
47 | "in vec2 v_textureCoordinate;\n" +
48 | "void main() {\n" +
49 | " vec4 color = texture(u_texture, v_textureCoordinate);\n" +
50 | " fragColor0 = vec4(1.0, color.g, color.b, color.a);\n" +
51 | " fragColor1 = vec4(color.r, 1.0, color.b, color.a);\n" +
52 | " fragColor2 = vec4(color.r, color.g, 1.0, color.a);\n" +
53 | "}"
54 |
55 | private val fragmentShaderCode =
56 | "#version 300 es\n" +
57 | "precision mediump float;\n" +
58 | "layout(location = 0) out vec4 fragColor;\n" +
59 | "in vec2 v_textureCoordinate;\n" +
60 | "uniform sampler2D u_texture;\n" +
61 | "void main() {\n" +
62 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
63 | "}"
64 |
65 | private var glSurfaceViewWidth = 0
66 | private var glSurfaceViewHeight = 0
67 |
68 | private val LOCATION_ATTRBUTE_POSITION = 0
69 | private val LOCATION_ATTRBUTE_TEXTURE_COORDINATE = 1
70 | private val VERTEX_COMPONENT_COUNT = 2
71 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 2
72 |
73 | val vertexData = floatArrayOf(-1f, -1f, -1f, 1f, 1f, 1f, -1f, -1f, 1f, 1f, 1f, -1f)
74 | val textureCoordinateData = floatArrayOf(0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 1f, 1f)
75 | private lateinit var vertexDataBuffer : FloatBuffer
76 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
77 |
78 | private var imageTexture = 0
79 | private var programIdMTR = 0
80 | private var programIdRTS = 0
81 | private var frameBufferMTR = 0
82 | private lateinit var targets : IntArray
83 |
84 | override fun onDrawFrame(gl: GL10?) {
85 |
86 | GLES30.glUseProgram(programIdMTR)
87 |
88 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRBUTE_POSITION)
89 | GLES30.glVertexAttribPointer(LOCATION_ATTRBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
90 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRBUTE_TEXTURE_COORDINATE)
91 | GLES30.glVertexAttribPointer(LOCATION_ATTRBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
92 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
93 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
94 | GLES30.glUniform1i(GLES30.glGetUniformLocation(programIdMTR, "u_texture"), 0)
95 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBufferMTR)
96 |
97 | // 设置清屏颜色
98 | // Set the color which the screen will be cleared to
99 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
100 |
101 | // 清屏
102 | // Clear the screen
103 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
104 |
105 | // 设置视口,这里设置为整个GLSurfaceView区域
106 | // Set the viewport to the full GLSurfaceView
107 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
108 |
109 | // 调用draw方法用TRIANGLES的方式执行渲染,顶点数量为3个
110 | // Call the draw method with GL_TRIANGLES to render 3 vertices
111 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
112 |
113 | // 将渲染得到的多个结果渲染到屏幕上
114 | // Render the multiple render results to screen
115 | renderTargetsToScreen(targets)
116 | }
117 |
118 | private fun renderTargetsToScreen(targets : IntArray) {
119 | GLES30.glUseProgram(programIdRTS)
120 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
121 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
122 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
123 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
124 | val vertexDataLeftBottom = floatArrayOf(-1f, -1f, -1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f, 0f, -1f)
125 | val offsetVertexData = FloatArray(vertexDataLeftBottom.size)
126 | for (i in 0 until targets.size) {
127 | for (j in 0 until vertexDataLeftBottom.size) {
128 | offsetVertexData[j] = vertexDataLeftBottom[j] + 0.5f * i
129 | }
130 | val vertexDataBuffer = ByteBuffer.allocateDirect(12 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer()
131 | vertexDataBuffer.put(offsetVertexData)
132 | vertexDataBuffer.position(0)
133 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRBUTE_POSITION)
134 | GLES30.glVertexAttribPointer(LOCATION_ATTRBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
135 | textureCoordinateDataBuffer.put(textureCoordinateData)
136 | textureCoordinateDataBuffer.position(0)
137 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRBUTE_TEXTURE_COORDINATE)
138 | GLES30.glVertexAttribPointer(LOCATION_ATTRBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
139 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
140 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, targets[i])
141 | GLES30.glUniform1i(GLES30.glGetUniformLocation(programIdRTS, "u_texture"), 0)
142 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, offsetVertexData.size / VERTEX_COMPONENT_COUNT)
143 | }
144 | }
145 |
146 |
147 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
148 |
149 | // 记录GLSurfaceView的宽高
150 | // Record the width and height of the GLSurfaceView
151 | glSurfaceViewWidth = width
152 | glSurfaceViewHeight = height
153 |
154 |
155 | // 创建一个frame buffer用于绑定多个渲染目标
156 | // Create a frame buffer to bind multiple render targets
157 | val frameBuffers = IntArray(1)
158 | GLES30.glGenFramebuffers(frameBuffers.size, frameBuffers, 0)
159 | frameBufferMTR = frameBuffers[0]
160 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBufferMTR)
161 |
162 | // 将3个渲染目标绑定到frame buffer上的3个attachment上
163 | // Bind 3 render targets to the 3 attachments of frame buffer
164 | for (i in 0 until targets.size) {
165 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, targets[i])
166 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
167 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
168 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
169 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
170 | GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, glSurfaceViewWidth, glSurfaceViewHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null)
171 | GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0 + i, GLES30.GL_TEXTURE_2D, targets[i], 0)
172 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
173 | }
174 |
175 | // 将0~2号attachment设置为draw目标
176 | // Set 0~2# attachments to draw target
177 | val attachments = intArrayOf(GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_COLOR_ATTACHMENT1, GLES30.GL_COLOR_ATTACHMENT2)
178 | val attachmentBuffer = IntBuffer.allocate(attachments.size)
179 | attachmentBuffer.put(attachments)
180 | attachmentBuffer.position(0)
181 | GLES30.glDrawBuffers(attachments.size, attachmentBuffer)
182 | GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
183 | }
184 |
185 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
186 |
187 | // 初始化多渲染目标效果的GL程序
188 | // Initialize the GL program of multiple render targets
189 | initMTRProgram()
190 |
191 | // 初始化渲染到屏幕的GL程序
192 | // Initialize the GL program of rendering to screen
193 | initRTSProgram()
194 |
195 | initData()
196 | }
197 |
198 | private fun initMTRProgram() {
199 | programIdMTR = GLES30.glCreateProgram()
200 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
201 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
202 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
203 | GLES30.glShaderSource(fragmentShader, fragmentShaderMRTCode)
204 | GLES30.glCompileShader(vertexShader)
205 | GLES30.glCompileShader(fragmentShader)
206 | val shaderInfo = GLES30.glGetShaderInfoLog(fragmentShader)
207 | GLES30.glAttachShader(programIdMTR, vertexShader)
208 | GLES30.glAttachShader(programIdMTR, fragmentShader)
209 | GLES30.glLinkProgram(programIdMTR)
210 | }
211 |
212 | private fun initRTSProgram() {
213 | programIdRTS = GLES30.glCreateProgram()
214 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
215 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
216 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
217 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
218 | GLES30.glCompileShader(vertexShader)
219 | GLES30.glCompileShader(fragmentShader)
220 | val shaderInfo = GLES30.glGetShaderInfoLog(fragmentShader)
221 | GLES30.glAttachShader(programIdRTS, vertexShader)
222 | GLES30.glAttachShader(programIdRTS, fragmentShader)
223 | GLES30.glLinkProgram(programIdRTS)
224 | Log.e("debug", "glGetProgramInfoLog = ${GLES30.glGetProgramInfoLog(programIdRTS)}")
225 | }
226 |
227 | private fun initData() {
228 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE)
229 | .order(ByteOrder.nativeOrder())
230 | .asFloatBuffer()
231 | vertexDataBuffer.put(vertexData)
232 | vertexDataBuffer.position(0)
233 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE)
234 | .order(ByteOrder.nativeOrder())
235 | .asFloatBuffer()
236 | textureCoordinateDataBuffer.put(textureCoordinateData)
237 | textureCoordinateDataBuffer.position(0)
238 | val textures = IntArray(1)
239 | GLES30.glGenTextures(textures.size, textures, 0)
240 | imageTexture = textures[0]
241 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
242 | val bitmap = Util.decodeBitmapFromAssets("image_0.jpg")
243 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
244 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
245 | bitmap.copyPixelsToBuffer(b)
246 | b.position(0)
247 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
248 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
249 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
250 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
251 | GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width, bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
252 | bitmap.recycle()
253 | GLES30.glUseProgram(programIdMTR)
254 | val locationUniformTexture = GLES30.glGetUniformLocation(programIdMTR, "u_texture")
255 | GLES30.glUniform1i(locationUniformTexture, 0)
256 |
257 | val targetCount = 3
258 | targets = IntArray(targetCount)
259 | GLES30.glGenTextures(targets.size, targets, 0)
260 | }
261 |
262 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleShaderRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import io.github.kenneycode.openglespro.Util
6 | import java.nio.ByteBuffer
7 | import java.nio.ByteOrder
8 | import java.nio.FloatBuffer
9 | import javax.microedition.khronos.egl.EGLConfig
10 | import javax.microedition.khronos.opengles.GL10
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个演示OpenGL 3.0 shader的例子,主要演示其中的location字段的作用
19 | * This sample demonstrates the usage of location in OpenGL 3.0 shader
20 | *
21 | **/
22 |
23 | class SampleShaderRenderer : GLSurfaceView.Renderer {
24 |
25 | private val vertexShaderCode =
26 | "#version 300 es\n" +
27 | "precision mediump float;\n" +
28 | "layout(location = 0) in vec4 a_position;\n" +
29 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
30 | "out vec2 v_textureCoordinate;\n" +
31 | "void main() {\n" +
32 | " v_textureCoordinate = a_textureCoordinate;\n" +
33 | " gl_Position = a_position;\n" +
34 | "}"
35 |
36 | private val fragmentShaderCode =
37 | "#version 300 es\n" +
38 | "precision mediump float;\n" +
39 | "precision mediump sampler2D;\n" +
40 | "layout(location = 0) out vec4 fragColor;\n" +
41 | "layout(location = 0) uniform sampler2D u_texture;\n" +
42 | "in vec2 v_textureCoordinate;\n" +
43 | "void main() {\n" +
44 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
45 | "}"
46 |
47 | // GLSurfaceView的宽高
48 | // The width and height of GLSurfaceView
49 | private var glSurfaceViewWidth = 0
50 | private var glSurfaceViewHeight = 0
51 |
52 | // 三角形顶点数据
53 | // The vertex data of a triangle
54 | private val vertexData = floatArrayOf(-1f, -1f, -1f, 1f, 1f, 1f, -1f, -1f, 1f, 1f, 1f, -1f)
55 | private val VERTEX_COMPONENT_COUNT = 2
56 | private lateinit var vertexDataBuffer : FloatBuffer
57 |
58 | // 纹理坐标
59 | // The texture coordinate
60 | private val textureCoordinateData = floatArrayOf(0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 1f, 1f)
61 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 2
62 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
63 |
64 | // 要渲染的图片纹理
65 | // The texture of the image to be rendered
66 | private var imageTexture = 0
67 |
68 | // a_position、a_textureCoordinate和u_texture的位置,与shader中写的对应
69 | // The location of a_position、a_textureCoordinate and u_texture, corresponding with which in shader
70 | private val LOCATION_ATTRIBUTE_POSITION = 0
71 | private val LOCATION_ATTRIBUTE_TEXTURE_COORDINATE = 1
72 | private val LOCATION_UNIFORM_TEXTURE = 0
73 |
74 | override fun onDrawFrame(gl: GL10?) {
75 |
76 | // 设置清屏颜色
77 | // Set the color which the screen will be cleared to
78 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
79 |
80 | // 清屏
81 | // Clear the screen
82 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
83 |
84 | // 设置视口,这里设置为整个GLSurfaceView区域
85 | // Set the viewport to the full GLSurfaceView
86 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
87 |
88 | // 设置好状态,准备渲染
89 | // Set the status before rendering
90 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
91 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
92 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
93 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
94 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
95 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
96 |
97 | // 调用draw方法用TRIANGLES的方式执行渲染,顶点数量为3个
98 | // Call the draw method with GL_TRIANGLES to render 3 vertices
99 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
100 |
101 | }
102 |
103 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
104 |
105 | // 记录GLSurfaceView的宽高
106 | // Record the width and height of the GLSurfaceView
107 | glSurfaceViewWidth = width
108 | glSurfaceViewHeight = height
109 |
110 | }
111 |
112 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
113 |
114 | // 创建GL程序
115 | // Create GL program
116 | val programId = GLES30.glCreateProgram()
117 |
118 | // 加载、编译vertex shader和fragment shader
119 | // Load and compile vertex shader and fragment shader
120 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
121 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
122 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
123 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
124 | GLES30.glCompileShader(vertexShader)
125 | GLES30.glCompileShader(fragmentShader)
126 |
127 | // 将shader程序附着到GL程序上
128 | // Attach the compiled shaders to the GL program
129 | GLES30.glAttachShader(programId, vertexShader)
130 | GLES30.glAttachShader(programId, fragmentShader)
131 |
132 | // 链接GL程序
133 | // Link the GL program
134 | GLES30.glLinkProgram(programId)
135 |
136 | // 应用GL程序
137 | // Use the GL program
138 | GLES30.glUseProgram(programId)
139 |
140 | // 将三角形顶点数据放入buffer中
141 | // Put the triangle vertex data into the vertexDataBuffer
142 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
143 | .order(ByteOrder.nativeOrder())
144 | .asFloatBuffer()
145 | vertexDataBuffer.put(vertexData)
146 | vertexDataBuffer.position(0)
147 |
148 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_POSITION,而无需像OpenGL 2.0那样需要先获取参数的location
149 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_POSITION, while in OpenGL 2.0 we have to query the location of the parameter
150 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
151 |
152 | // 指定a_position所使用的顶点数据
153 | // Specify the data of a_position
154 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
155 |
156 | // 将纹理坐标数据放入buffer中
157 | // Put the texture coordinates into the textureCoordinateDataBuffer
158 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE / 8)
159 | .order(ByteOrder.nativeOrder())
160 | .asFloatBuffer()
161 | textureCoordinateDataBuffer.put(textureCoordinateData)
162 | textureCoordinateDataBuffer.position(0)
163 |
164 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_TEXTURE_COORDINATE,而无需像OpenGL 2.0那样需要先获取参数的location
165 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, while in OpenGL 2.0 we have to query the location of the parameter
166 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
167 |
168 | // 指定a_textureCoordinate所使用的顶点数据
169 | // Specify the data of a_textureCoordinate
170 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
171 |
172 | // 创建图片纹理
173 | // Create texture for image
174 | val textures = IntArray(1)
175 | GLES30.glGenTextures(textures.size, textures, 0)
176 | imageTexture = textures[0]
177 |
178 | // 将图片解码并加载到纹理中
179 | // Decode image and load it into texture
180 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
181 | val bitmap = Util.decodeBitmapFromAssets("image_0.jpg")
182 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
183 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
184 | bitmap.copyPixelsToBuffer(b)
185 | b.position(0)
186 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
187 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
188 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
189 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
190 | GLES30.glTexImage2D(
191 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width,
192 | bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
193 | bitmap.recycle()
194 |
195 | // 启动对应位置的参数,这里直接使用LOCATION_UNIFORM_TEXTURE,而无需像OpenGL 2.0那样需要先获取参数的location
196 | // Enable the parameter of the location. Here we can simply use LOCATION_UNIFORM_TEXTURE, while in OpenGL 2.0 we have to query the location of the parameter
197 | GLES30.glUniform1i(LOCATION_UNIFORM_TEXTURE, 0)
198 |
199 | }
200 |
201 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleTextureArrayRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import io.github.kenneycode.openglespro.Util
6 | import java.nio.ByteBuffer
7 | import java.nio.ByteOrder
8 | import java.nio.FloatBuffer
9 | import javax.microedition.khronos.egl.EGLConfig
10 | import javax.microedition.khronos.opengles.GL10
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 这是一个纹理数组的例子,通用使用sampler2DArray将一组纹理传给fragment shader
19 | * This sample demonstrates the usage of texture array. In the fragment shader, we use sampler2DArray to hold an array of texture.
20 | *
21 | **/
22 |
23 | class SampleTextureArrayRenderer : GLSurfaceView.Renderer {
24 |
25 | private val vertexShaderCode =
26 | "#version 300 es\n" +
27 | "precision mediump float;\n" +
28 | "layout(location = 0) in vec4 a_Position;\n" +
29 | "layout(location = 1) in vec3 a_textureCoordinate;\n" +
30 | "out vec3 v_textureCoordinate;\n" +
31 | "void main() {\n" +
32 | " v_textureCoordinate = a_textureCoordinate;\n" +
33 | " gl_Position = a_Position;\n" +
34 | "}"
35 |
36 | private val fragmentShaderCode =
37 | "#version 300 es\n" +
38 | "precision mediump float;\n" +
39 | "precision mediump sampler2DArray;\n" +
40 | "layout(location = 0) out vec4 fragColor;\n" +
41 | "in vec3 v_textureCoordinate;\n" +
42 | "// 注意这里用的是sampler2DArray而不是sampler2D\n" +
43 | "// Note that the type of u_texture is sampler2DArray instead of sampler2D\n" +
44 | "layout(location = 0) uniform sampler2DArray u_texture;\n" +
45 | "void main() {\n" +
46 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
47 | "}"
48 |
49 | // GLSurfaceView的宽高
50 | // The width and height of GLSurfaceView
51 | private var glSurfaceViewWidth = 0
52 | private var glSurfaceViewHeight = 0
53 |
54 | // 三角形顶点数据
55 | // The vertex data of a triangle
56 | private val vertexData = floatArrayOf(-1f, -1f, -1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f, 0f, -1f,
57 | 0f, 0f, 0f, 1f, 1f, 1f, 0f, 0f, 1f, 1f, 1f, 0f)
58 | private val VERTEX_COMPONENT_COUNT = 2
59 | private lateinit var vertexDataBuffer : FloatBuffer
60 |
61 | // 纹理坐标
62 | // The texture coordinate
63 | private val textureCoordinateData = floatArrayOf(
64 | 0f, 1f, 0f,
65 | 0f, 0f, 0f,
66 | 1f, 0f, 0f,
67 | 0f, 1f, 0f,
68 | 1f, 0f, 0f,
69 | 1f, 1f, 0f,
70 | 0f, 1f, 1f,
71 | 0f, 0f, 1f,
72 | 1f, 0f, 1f,
73 | 0f, 1f, 1f,
74 | 1f, 0f, 1f,
75 | 1f, 1f, 1f
76 | )
77 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 3
78 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
79 |
80 | // 要渲染的图片纹理
81 | // The texture of the image to be rendered
82 | private var imageTexture = 0
83 |
84 | // a_position、a_textureCoordinate和u_texture的位置,与shader中写的对应
85 | // The location of a_position、a_textureCoordinate and u_texture, corresponding with which in shader
86 | private val LOCATION_ATTRIBUTE_POSITION = 0
87 | private val LOCATION_ATTRIBUTE_TEXTURE_COORDINATE = 1
88 | private val LOCATION_UNIFORM_TEXTURE = 0
89 |
90 | override fun onDrawFrame(gl: GL10?) {
91 |
92 | // 设置清屏颜色
93 | // Set the color which the screen will be cleared to
94 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
95 |
96 | // 清屏
97 | // Clear the screen
98 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
99 |
100 | // 设置视口,这里设置为整个GLSurfaceView区域
101 | // Set the viewport to the full GLSurfaceView
102 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
103 |
104 | // 设置好状态,准备渲染
105 | // Set the status before rendering
106 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
107 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
108 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
109 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
110 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
111 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
112 |
113 | // 调用draw方法用TRIANGLES的方式执行渲染,顶点数量为3个
114 | // Call the draw method with GL_TRIANGLES to render 3 vertices
115 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
116 |
117 | }
118 |
119 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
120 | // 记录GLSurfaceView的宽高
121 | // Record the width and height of the GLSurfaceView
122 | glSurfaceViewWidth = width
123 | glSurfaceViewHeight = height
124 | }
125 |
126 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
127 |
128 | // 创建GL程序
129 | // Create GL program
130 | val programId = GLES30.glCreateProgram()
131 |
132 | // 加载、编译vertex shader和fragment shader
133 | // Load and compile vertex shader and fragment shader
134 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
135 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
136 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
137 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
138 | GLES30.glCompileShader(vertexShader)
139 | GLES30.glCompileShader(fragmentShader)
140 |
141 | // 将shader程序附着到GL程序上
142 | // Attach the compiled shaders to the GL program
143 | GLES30.glAttachShader(programId, vertexShader)
144 | GLES30.glAttachShader(programId, fragmentShader)
145 |
146 | val info1 = GLES30.glGetShaderInfoLog(fragmentShader)
147 | // 链接GL程序
148 | // Link the GL program
149 | GLES30.glLinkProgram(programId)
150 |
151 | // 应用GL程序
152 | // Use the GL program
153 | GLES30.glUseProgram(programId)
154 |
155 | // 将三角形顶点数据放入buffer中
156 | // Put the triangle vertex data into the vertexDataBuffer
157 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
158 | .order(ByteOrder.nativeOrder())
159 | .asFloatBuffer()
160 | vertexDataBuffer.put(vertexData)
161 | vertexDataBuffer.position(0)
162 |
163 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_POSITION,而无需像OpenGL 2.0那样需要先获取参数的location
164 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_POSITION, while in OpenGL 2.0 we have to query the location of the parameter
165 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
166 |
167 | // 指定a_position所使用的顶点数据
168 | // Specify the data of a_position
169 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
170 |
171 | // 将纹理坐标数据放入buffer中
172 | // Put the texture coordinates into the textureCoordinateDataBuffer
173 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE / 8)
174 | .order(ByteOrder.nativeOrder())
175 | .asFloatBuffer()
176 | textureCoordinateDataBuffer.put(textureCoordinateData)
177 | textureCoordinateDataBuffer.position(0)
178 |
179 | // 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_TEXTURE_COORDINATE,而无需像OpenGL 2.0那样需要先获取参数的location
180 | // Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, while in OpenGL 2.0 we have to query the location of the parameter
181 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
182 |
183 | // 指定a_textureCoordinate所使用的顶点数据
184 | // Specify the data of a_textureCoordinate
185 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
186 |
187 | // 创建图片纹理数组
188 | // Create texture for image
189 | val textures = IntArray(1)
190 | GLES30.glGenTextures(textures.size, textures, 0)
191 | imageTexture = textures[0]
192 |
193 | // 注意这里是GL_TEXTURE_2D_ARRAY
194 | // Note that the type is GL_TEXTURE_2D_ARRAY
195 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D_ARRAY, textures[0])
196 | GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA8, 390, 270, 2)
197 |
198 | // 通过glTexSubImage3D指定每层的纹理
199 | // Specify the texture of each layer via glTexSubImage3D
200 | for (i in 0 until 2) {
201 | val bitmap = Util.decodeBitmapFromAssets("image_$i.jpg")
202 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
203 | bitmap.copyPixelsToBuffer(b)
204 | b.position(0)
205 | GLES30.glTexSubImage3D(GLES30.GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, bitmap.width, bitmap.height, 1, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
206 | bitmap.recycle()
207 | }
208 |
209 | // 启动对应位置的参数,这里直接使用LOCATION_UNIFORM_TEXTURE,而无需像OpenGL 2.0那样需要先获取参数的location
210 | // Enable the parameter of the location. Here we can simply use LOCATION_UNIFORM_TEXTURE, while in OpenGL 2.0 we have to query the location of the parameter
211 | GLES30.glUniform1i(LOCATION_UNIFORM_TEXTURE, 0)
212 |
213 | }
214 |
215 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/SampleVBOAndIBORenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import io.github.kenneycode.openglespro.Util
6 | import java.nio.ByteBuffer
7 | import java.nio.ByteOrder
8 | import javax.microedition.khronos.egl.EGLConfig
9 | import javax.microedition.khronos.opengles.GL10
10 |
11 | /**
12 | *
13 | * Coded by kenney
14 | *
15 | * http://www.github.com/kenneycode
16 | *
17 | * 这是一个使用VBO(Vertex Buffer Object)和IBO(Index Buffer Object)的例子
18 | * This sample demonstrates the usage of VBO(Vertex Buffer Object) and IBO(Index Buffer Object)
19 | *
20 | **/
21 |
22 | class SampleVBOAndIBORenderer : GLSurfaceView.Renderer {
23 |
24 | private val vertexShaderCode =
25 | "#version 300 es\n" +
26 | "precision mediump float;\n" +
27 | "layout(location = 0) in vec4 a_position;\n" +
28 | "layout(location = 1) in vec2 a_textureCoordinate;\n" +
29 | "out vec2 v_textureCoordinate;\n" +
30 | "void main() {\n" +
31 | " v_textureCoordinate = a_textureCoordinate;\n" +
32 | " gl_Position = a_position;\n" +
33 | "}"
34 |
35 | private val fragmentShaderCode =
36 | "#version 300 es\n" +
37 | "precision mediump float;\n" +
38 | "layout(location = 0) out vec4 fragColor;\n" +
39 | "in vec2 v_textureCoordinate;\n" +
40 | "uniform sampler2D u_texture;\n" +
41 | "void main() {\n" +
42 | " fragColor = texture(u_texture, v_textureCoordinate);\n" +
43 | "}"
44 |
45 | // GLSurfaceView的宽高
46 | // The width and height of GLSurfaceView
47 | private var glSurfaceViewWidth = 0
48 | private var glSurfaceViewHeight = 0
49 |
50 | // 三角形顶点、纹理数据
51 | // The vertex data and texture coordinate data of triangles
52 | private val vertexData = floatArrayOf(
53 | -1f, -1f, 0f, 1f, // x, y, u, v
54 | -1f, 1f, 0f, 0f,
55 | 1f, 1f, 1f, 0f,
56 | 1f, -1f, 1f, 1f
57 | )
58 | // 顶点索引数据
59 | // The vertex data of triangles
60 | private val indexData = intArrayOf(0, 1, 2, 0, 2, 3)
61 |
62 | // 要渲染的图片纹理
63 | // The texture of the image to be rendered
64 | private var imageTexture = 0
65 |
66 | // a_position、a_textureCoordinate和u_texture的位置,与shader中写的对应
67 | // The location of a_position、a_textureCoordinate and u_texture, corresponding with which in shader
68 | private val LOCATION_ATTRIBUTE_POSITION = 0
69 | private val LOCATION_ATTRIBUTE_TEXTURE_COORDINATE = 1
70 | private val LOCATION_UNIFORM_TEXTURE = 0
71 |
72 | // VBO和IBO
73 | // VBO and IBO
74 | private var vbo = 0
75 | private var ibo = 0
76 |
77 | override fun onDrawFrame(gl: GL10?) {
78 |
79 | // 设置清屏颜色
80 | // Set the color which the screen will be cleared to
81 | GLES30.glClearColor(0.9f, 0.9f, 0.9f, 1f)
82 |
83 | // 清屏
84 | // Clear the screen
85 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
86 |
87 | // 设置视口,这里设置为整个GLSurfaceView区域
88 | // Set the viewport to the full GLSurfaceView
89 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
90 |
91 | // 设置好状态,准备渲染
92 | // Set the status before rendering
93 | GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo)
94 | GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ibo)
95 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
96 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
97 |
98 | // 调用glDrawElements方法用TRIANGLES的方式执行渲染
99 | // Call the glDrawElements method with GL_TRIANGLES
100 | GLES30.glDrawElements(GLES30.GL_TRIANGLES, indexData.size, GLES30.GL_UNSIGNED_INT, 0)
101 |
102 | }
103 |
104 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
105 |
106 | // 记录GLSurfaceView的宽高
107 | // Record the width and height of the GLSurfaceView
108 | glSurfaceViewWidth = width
109 | glSurfaceViewHeight = height
110 |
111 | }
112 |
113 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
114 |
115 | // 创建GL程序
116 | // Create GL program
117 | val programId = GLES30.glCreateProgram()
118 |
119 | // 加载、编译vertex shader和fragment shader
120 | // Load and compile vertex shader and fragment shader
121 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
122 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
123 | GLES30.glShaderSource(vertexShader, vertexShaderCode)
124 | GLES30.glShaderSource(fragmentShader, fragmentShaderCode)
125 | GLES30.glCompileShader(vertexShader)
126 | GLES30.glCompileShader(fragmentShader)
127 |
128 | // 将shader程序附着到GL程序上
129 | // Attach the compiled shaders to the GL program
130 | GLES30.glAttachShader(programId, vertexShader)
131 | GLES30.glAttachShader(programId, fragmentShader)
132 |
133 | // 链接GL程序
134 | // Link the GL program
135 | GLES30.glLinkProgram(programId)
136 |
137 | // 应用GL程序
138 | // Use the GL program
139 | GLES30.glUseProgram(programId)
140 |
141 | // 创建VBO和IBO
142 | // Create VBO and IBO
143 | val buffers = IntArray(2)
144 | GLES30.glGenBuffers(buffers.size, buffers, 0)
145 | vbo = buffers[0]
146 | ibo = buffers[1]
147 |
148 | // 将顶点和纹理数据载入VBO
149 | // Load vertex data into VBO
150 | val vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
151 | .order(ByteOrder.nativeOrder())
152 | .asFloatBuffer()
153 | vertexDataBuffer.put(vertexData)
154 | vertexDataBuffer.position(0)
155 | GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo)
156 | GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexDataBuffer.capacity() * java.lang.Float.SIZE / 8, vertexDataBuffer, GLES30.GL_STATIC_DRAW)
157 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
158 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
159 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, 2, GLES30.GL_FLOAT, false, 16, 0)
160 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, 2, GLES30.GL_FLOAT, false, 16, 8)
161 |
162 | // 将顶点索引数据载入IBO
163 | // Load index data into IBO
164 | val indexDataBuffer = ByteBuffer.allocateDirect(indexData.size * Integer.SIZE / 8)
165 | .order(ByteOrder.nativeOrder())
166 | .asIntBuffer()
167 | indexDataBuffer.put(indexData)
168 | indexDataBuffer.position(0)
169 | GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ibo)
170 | GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, indexDataBuffer.capacity() * Integer.SIZE / 8, indexDataBuffer, GLES30.GL_STATIC_DRAW)
171 |
172 | // 创建图片纹理
173 | // Create texture for image
174 | val textures = IntArray(1)
175 | GLES30.glGenTextures(textures.size, textures, 0)
176 | imageTexture = textures[0]
177 |
178 | // 将图片解码并加载到纹理中
179 | // Decode image and load it into texture
180 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
181 | val bitmap = Util.decodeBitmapFromAssets("image_2.jpg")
182 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
183 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
184 | bitmap.copyPixelsToBuffer(b)
185 | b.position(0)
186 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
187 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
188 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
189 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
190 | GLES30.glTexImage2D(
191 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width,
192 | bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
193 | bitmap.recycle()
194 |
195 | // 启动对应位置的参数,这里直接使用LOCATION_UNIFORM_TEXTURE,而无需像OpenGL 2.0那样需要先获取参数的location
196 | // Enable the parameter of the location. Here we can simply use LOCATION_UNIFORM_TEXTURE, while in OpenGL 2.0 we have to query the location of the parameter
197 | GLES30.glUniform1i(LOCATION_UNIFORM_TEXTURE, 0)
198 |
199 | }
200 |
201 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/lighting/BumpedLightRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer.lighting
2 |
3 | import android.opengl.GLES30
4 | import io.github.kenneycode.openglespro.Util
5 | import java.nio.ByteBuffer
6 | import java.nio.ByteOrder
7 | import java.nio.FloatBuffer
8 | import javax.microedition.khronos.egl.EGLConfig
9 | import javax.microedition.khronos.opengles.GL10
10 | import kotlin.math.sqrt
11 |
12 | /**
13 | *
14 | * Coded by kenney
15 | *
16 | * http://www.github.com/kenneycode
17 | *
18 | * 法向图例子
19 | * Bumped sample
20 | *
21 | **/
22 |
23 | class BumpedLightRenderer : LightingRenderer("lighting/bumpedlighting.vs", "lighting/bumpedlighting.fs") {
24 |
25 | private var normalTexture = 0
26 |
27 | private val LOCATION_ATTRIBUTE_TANGENT = 3
28 | private val LOCATION_ATTRIBUTE_BITANGENT = 4
29 |
30 | private val TANGENT_COMPONENT_COUNT = 3
31 | private lateinit var tangentDataBuffer : FloatBuffer
32 |
33 | private val BITANGENT_COMPONENT_COUNT = 3
34 | private lateinit var bitangentDataBuffer : FloatBuffer
35 |
36 | override fun onDrawFrame(gl: GL10?) {
37 | super.onDrawFrame(gl)
38 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TANGENT)
39 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TANGENT, TANGENT_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, tangentDataBuffer)
40 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_BITANGENT)
41 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_BITANGENT, BITANGENT_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, bitangentDataBuffer)
42 | GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
43 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, normalTexture)
44 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "lightPos"), 2f, 0f, 2f)
45 | }
46 |
47 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
48 | super.onSurfaceCreated(gl, config)
49 | val textures = IntArray(1)
50 | GLES30.glGenTextures(textures.size, textures, 0)
51 | normalTexture = textures[0]
52 | GLES30.glActiveTexture(GLES30.GL_TEXTURE1)
53 | val bitmap2 = Util.decodeBitmapFromAssets("lighting/brickn.png")
54 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, normalTexture)
55 | val b2 = ByteBuffer.allocate(bitmap2.width * bitmap2.height * 4)
56 | bitmap2.copyPixelsToBuffer(b2)
57 | b2.position(0)
58 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
59 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
60 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
61 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
62 | GLES30.glTexImage2D(
63 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap2.width,
64 | bitmap2.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b2)
65 | bitmap2.recycle()
66 | GLES30.glUniform1i(GLES30.glGetUniformLocation(programId, "normalTex"), 1)
67 | calculateTangents()
68 | }
69 |
70 | private fun calculateTangents() {
71 | tangentDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
72 | .order(ByteOrder.nativeOrder())
73 | .asFloatBuffer()
74 | bitangentDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
75 | .order(ByteOrder.nativeOrder())
76 | .asFloatBuffer()
77 | val tangents = mutableListOf()
78 | val bitangents = mutableListOf()
79 | for (i in 0 until vertexData.size / 9) {
80 | val e1x = vertexData[i * 9 + 3] - vertexData[i * 9]
81 | val e1y = vertexData[i * 9 + 3 + 1] - vertexData[i * 9 + 1]
82 | val e1z = vertexData[i * 9 + 3 + 2] - vertexData[i * 9 + 2]
83 | val e2x = vertexData[i * 9 + 6] - vertexData[i * 9]
84 | val e2y = vertexData[i * 9 + 6 + 1] - vertexData[i * 9 + 1]
85 | val e2z = vertexData[i * 9 + 6 + 2] - vertexData[i * 9 + 2]
86 | val deltaUV1x = textureCoordinateData[i * 6 + 2] - textureCoordinateData[i * 6]
87 | val deltaUV1y = textureCoordinateData[i * 6 + 2 + 1] - textureCoordinateData[i * 6 + 1]
88 | val deltaUV2x = textureCoordinateData[i * 6 + 4] - textureCoordinateData[i * 6]
89 | val deltaUV2y = textureCoordinateData[i * 6 + 4 + 1] - textureCoordinateData[i * 6 + 1]
90 | val f = 1f / (deltaUV1x * deltaUV2y - deltaUV2x * deltaUV1y)
91 | var tangentx = f * (deltaUV2y * e1x - deltaUV1y * e2x)
92 | var tangenty = f * (deltaUV2y * e1y - deltaUV1y * e2y)
93 | var tangentz = f * (deltaUV2y * e1z - deltaUV1y * e2z)
94 | val tangentLength = sqrt(tangentx * tangentx + tangenty * tangenty + tangentz * tangentz)
95 | tangentx /= tangentLength
96 | tangenty /= tangentLength
97 | tangentz /= tangentLength
98 | var bitangentx = f * (-deltaUV2x * e1x + deltaUV1x * e2x)
99 | var bitangenty = f * (-deltaUV2x * e1y + deltaUV1x * e2y)
100 | var bitangentz = f * (-deltaUV2x * e1z + deltaUV1x * e2z)
101 | val bitangentLength = sqrt(bitangentx * bitangentx + bitangenty * bitangenty + bitangentz * bitangentz)
102 | bitangentx /= bitangentLength
103 | bitangenty /= bitangentLength
104 | bitangentz /= bitangentLength
105 | for (j in 0 until 9) {
106 | when (j % 3) {
107 | 0 -> {
108 | tangents.add(tangentx)
109 | bitangents.add(bitangentx)
110 | }
111 | 1 -> {
112 | tangents.add(tangenty)
113 | bitangents.add(bitangenty)
114 | }
115 | 2 -> {
116 | tangents.add(tangentz)
117 | bitangents.add(bitangentz)
118 | }
119 | }
120 | }
121 | }
122 | tangentDataBuffer.put(tangents.toFloatArray())
123 | tangentDataBuffer.position(0)
124 | bitangentDataBuffer.put(bitangents.toFloatArray())
125 | bitangentDataBuffer.position(0)
126 | }
127 |
128 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/lighting/DirectionalLightRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer.lighting
2 |
3 | import android.opengl.GLES30
4 | import javax.microedition.khronos.opengles.GL10
5 |
6 | /**
7 | *
8 | * Coded by kenney
9 | *
10 | * http://www.github.com/kenneycode
11 | *
12 | * 平行光光照例子
13 | * Directional light sample
14 | *
15 | **/
16 |
17 | class DirectionalLightRenderer : LightingRenderer("lighting/directionallight.vs", "lighting/directionallight.fs") {
18 |
19 | override fun onDrawFrame(gl: GL10?) {
20 | super.onDrawFrame(gl)
21 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "lightDirection"), -5f, 0f, 0f)
22 | assert(GLES30.glGetError() == 0)
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/lighting/LightingRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer.lighting
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import android.opengl.Matrix
6 | import io.github.kenneycode.openglespro.Util
7 | import io.github.kenneycode.openglespro.samples.renderer.OnParameterChangeCallback
8 | import java.nio.ByteBuffer
9 | import java.nio.ByteOrder
10 | import java.nio.FloatBuffer
11 | import javax.microedition.khronos.egl.EGLConfig
12 | import javax.microedition.khronos.opengles.GL10
13 |
14 | /**
15 | *
16 | * Coded by kenney
17 | *
18 | * http://www.github.com/kenneycode
19 | *
20 | * 光照例子基类
21 | * Base class of lighting samples
22 | *
23 | **/
24 |
25 | open class LightingRenderer(private val vertexShaderPath: String, private val fragmentShaderPath: String) : GLSurfaceView.Renderer {
26 |
27 | private var glSurfaceViewWidth = 0
28 | private var glSurfaceViewHeight = 0
29 |
30 | protected val vertexData = floatArrayOf(
31 | // 正面
32 | // front face
33 | -1f, -1f, 1f,
34 | -1f, 1f, 1f,
35 | 1f, 1f, 1f,
36 | -1f, -1f, 1f,
37 | 1f, 1f, 1f,
38 | 1f, -1f, 1f,
39 | // 背面
40 | // back face
41 | -1f, -1f, -1f,
42 | -1f, 1f, -1f,
43 | 1f, 1f, -1f,
44 | -1f, -1f, -1f,
45 | 1f, 1f, -1f,
46 | 1f, -1f, -1f,
47 | // 顶面
48 | // Top face
49 | -1f, 1f, -1f,
50 | -1f, 1f, 1f,
51 | 1f, 1f, 1f,
52 | -1f, 1f, -1f,
53 | 1f, 1f, 1f,
54 | 1f, 1f, -1f,
55 | // 底面
56 | // Bottom face
57 | -1f, -1f, -1f,
58 | -1f, -1f, 1f,
59 | 1f, -1f, 1f,
60 | -1f, -1f, -1f,
61 | 1f, -1f, 1f,
62 | 1f, -1f, -1f,
63 | // 左面
64 | // Left face
65 | -1f, -1f, -1f,
66 | -1f, -1f, 1f,
67 | -1f, 1f, 1f,
68 | -1f, -1f, -1f,
69 | -1f, 1f, 1f,
70 | -1f, 1f, -1f,
71 | // 右面
72 | // Right face
73 | 1f, -1f, -1f,
74 | 1f, -1f, 1f,
75 | 1f, 1f, 1f,
76 | 1f, -1f, -1f,
77 | 1f, 1f, 1f,
78 | 1f, 1f, -1f
79 | )
80 | private val VERTEX_COMPONENT_COUNT = 3
81 | private lateinit var vertexDataBuffer : FloatBuffer
82 |
83 | private val normalData = floatArrayOf(
84 | // 正面
85 | // front face
86 | 0f, 0f, 1f,
87 | 0f, 0f, 1f,
88 | 0f, 0f, 1f,
89 | 0f, 0f, 1f,
90 | 0f, 0f, 1f,
91 | 0f, 0f, 1f,
92 | // 背面
93 | // back face
94 | 0f, 0f, -1f,
95 | 0f, 0f, -1f,
96 | 0f, 0f, -1f,
97 | 0f, 0f, -1f,
98 | 0f, 0f, -1f,
99 | 0f, 0f, -1f,
100 | // 顶面
101 | // Top face
102 | 0f, 1f, 0f,
103 | 0f, 1f, 0f,
104 | 0f, 1f, 0f,
105 | 0f, 1f, 0f,
106 | 0f, 1f, 0f,
107 | 0f, 1f, 0f,
108 | // 底面
109 | // Bottom face
110 | 0f, -1f, 0f,
111 | 0f, -1f, 0f,
112 | 0f, -1f, 0f,
113 | 0f, -1f, 0f,
114 | 0f, -1f, 0f,
115 | 0f, -1f, 0f,
116 | // 左面
117 | // Left face
118 | -1f, 0f, 0f,
119 | -1f, 0f, 0f,
120 | -1f, 0f, 0f,
121 | -1f, 0f, 0f,
122 | -1f, 0f, 0f,
123 | -1f, 0f, 0f,
124 | // 右面
125 | // Right face
126 | 1f, 0f, 0f,
127 | 1f, 0f, 0f,
128 | 1f, 0f, 0f,
129 | 1f, 0f, 0f,
130 | 1f, 0f, 0f,
131 | 1f, 0f, 0f
132 | )
133 | private val NORMAL_COMPONENT_COUNT = 3
134 | private lateinit var normalDataBuffer : FloatBuffer
135 |
136 | protected val textureCoordinateData = floatArrayOf(
137 | 0f, 1f,
138 | 0f, 0f,
139 | 1f, 0f,
140 | 0f, 1f,
141 | 1f, 0f,
142 | 1f, 1f,
143 | 0f, 1f,
144 | 0f, 0f,
145 | 1f, 0f,
146 | 0f, 1f,
147 | 1f, 0f,
148 | 1f, 1f,
149 | 0f, 1f,
150 | 0f, 0f,
151 | 1f, 0f,
152 | 0f, 1f,
153 | 1f, 0f,
154 | 1f, 1f,
155 | 0f, 1f,
156 | 0f, 0f,
157 | 1f, 0f,
158 | 0f, 1f,
159 | 1f, 0f,
160 | 1f, 1f,
161 | 0f, 1f,
162 | 0f, 0f,
163 | 1f, 0f,
164 | 0f, 1f,
165 | 1f, 0f,
166 | 1f, 1f,
167 | 0f, 1f,
168 | 0f, 0f,
169 | 1f, 0f,
170 | 0f, 1f,
171 | 1f, 0f,
172 | 1f, 1f
173 | )
174 | private val TEXTURE_COORDINATE_COMPONENT_COUNT = 2
175 | private lateinit var textureCoordinateDataBuffer : FloatBuffer
176 |
177 | private var imageTexture = 0
178 |
179 | protected var programId = 0
180 |
181 | private val LOCATION_ATTRIBUTE_POSITION = 0
182 | private val LOCATION_ATTRIBUTE_TEXTURE_COORDINATE = 1
183 | private val LOCATION_ATTRIBUTE_NORMAL = 2
184 | private val LOCATION_UNIFORM_TEXTURE = 0
185 |
186 | var translateX = 0f
187 | var translateY = 0f
188 | var translateZ = 0f
189 | var rotateX = 30f
190 | var rotateY = -45f
191 | var rotateZ = 0f
192 | var scaleX = 1f
193 | var scaleY = 1f
194 | var scaleZ = 1f
195 | var cameraPositionX = 0f
196 | var cameraPositionY = 0f
197 | var cameraPositionZ = 5f
198 | var lookAtX = 0f
199 | var lookAtY = 0f
200 | var lookAtZ = 0f
201 | var cameraUpX = 0f
202 | var cameraUpY = 1f
203 | var cameraUpZ = 0f
204 | var nearPlaneLeft = -1f
205 | var nearPlaneRight = 1f
206 | var nearPlaneBottom = -1f
207 | var nearPlaneTop = 1f
208 | var nearPlane = 2f
209 | var farPlane = 100f
210 |
211 | override fun onDrawFrame(gl: GL10?) {
212 |
213 | rotateY += 1f
214 |
215 | GLES30.glUseProgram(programId)
216 |
217 | GLES30.glClearColor(0f, 0f, 0f, 0f)
218 |
219 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
220 |
221 | GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT)
222 |
223 | GLES30.glViewport(0, 0, glSurfaceViewWidth, glSurfaceViewHeight)
224 |
225 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
226 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
227 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
228 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, textureCoordinateDataBuffer)
229 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_NORMAL)
230 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_NORMAL, NORMAL_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, normalDataBuffer)
231 |
232 | val mvpMatrix = getIdentity()
233 | val translateMatrix = getIdentity()
234 | val rotateMatrix = getIdentity()
235 | val scaleMatrix = getIdentity()
236 | val modelMatrix = getIdentity()
237 | val viewMatrix = getIdentity()
238 | val projectMatrix = getIdentity()
239 |
240 | Matrix.translateM(translateMatrix, 0, translateX, translateY, translateZ)
241 | Matrix.rotateM(rotateMatrix, 0, rotateZ, 1f, 0f, 0f)
242 | Matrix.rotateM(rotateMatrix, 0, rotateY, 0f, 1f, 0f)
243 | Matrix.rotateM(rotateMatrix, 0, rotateX, 0f, 0f, 1f)
244 | Matrix.scaleM(scaleMatrix, 0, scaleX, scaleY, scaleZ)
245 | Matrix.multiplyMM(modelMatrix, 0, rotateMatrix, 0, scaleMatrix, 0)
246 | Matrix.multiplyMM(modelMatrix, 0, modelMatrix, 0, translateMatrix, 0)
247 |
248 | Matrix.setLookAtM(
249 | viewMatrix,
250 | 0,
251 | cameraPositionX, cameraPositionY, cameraPositionZ,
252 | lookAtX, lookAtY, lookAtZ,
253 | cameraUpX, cameraUpY, cameraUpZ
254 | )
255 |
256 | Matrix.frustumM(
257 | projectMatrix,
258 | 0,
259 | nearPlaneLeft, nearPlaneRight, nearPlaneBottom, nearPlaneTop,
260 | nearPlane,
261 | farPlane
262 | )
263 |
264 | Matrix.multiplyMM(mvpMatrix, 0, viewMatrix, 0, modelMatrix, 0)
265 | Matrix.multiplyMM(mvpMatrix, 0, projectMatrix, 0, mvpMatrix, 0)
266 |
267 | GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(programId, "model"), 1, false, modelMatrix, 0)
268 | GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(programId, "view"), 1, false, viewMatrix, 0)
269 | GLES30.glUniformMatrix4fv(GLES30.glGetUniformLocation(programId, "projection"), 1, false, projectMatrix, 0)
270 |
271 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
272 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
273 | GLES30.glUniform1i(GLES30.glGetUniformLocation(programId, "imageTex"), 0)
274 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "viewPos"), 0f, 0f, 5f)
275 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "lightColor"), 1f, 1f, 1f)
276 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "objectColor"), 1f, 1f, 0f)
277 |
278 | GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexData.size / VERTEX_COMPONENT_COUNT)
279 | assert(GLES30.glGetError() == 0)
280 |
281 | }
282 |
283 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
284 |
285 | glSurfaceViewWidth = width
286 | glSurfaceViewHeight = height
287 | nearPlaneBottom = -height.toFloat() / width
288 | nearPlaneTop = height.toFloat() / width
289 |
290 | }
291 |
292 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
293 |
294 | programId = GLES30.glCreateProgram()
295 |
296 | val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
297 | val fragmentShader= GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
298 | GLES30.glShaderSource(vertexShader, Util.loadShaderFromAssets(vertexShaderPath))
299 | GLES30.glShaderSource(fragmentShader, Util.loadShaderFromAssets(fragmentShaderPath))
300 | GLES30.glCompileShader(vertexShader)
301 | GLES30.glCompileShader(fragmentShader)
302 |
303 | GLES30.glAttachShader(programId, vertexShader)
304 | GLES30.glAttachShader(programId, fragmentShader)
305 |
306 | GLES30.glLinkProgram(programId)
307 | GLES30.glUseProgram(programId)
308 |
309 | val log0 = GLES30.glGetProgramInfoLog(fragmentShader)
310 | val log = GLES30.glGetProgramInfoLog(programId)
311 |
312 | vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
313 | .order(ByteOrder.nativeOrder())
314 | .asFloatBuffer()
315 | vertexDataBuffer.put(vertexData)
316 | vertexDataBuffer.position(0)
317 |
318 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
319 |
320 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false,0, vertexDataBuffer)
321 |
322 | normalDataBuffer = ByteBuffer.allocateDirect(normalData.size * java.lang.Float.SIZE / 8)
323 | .order(ByteOrder.nativeOrder())
324 | .asFloatBuffer()
325 | normalDataBuffer.put(normalData)
326 | normalDataBuffer.position(0)
327 |
328 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_NORMAL)
329 |
330 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_NORMAL, NORMAL_COMPONENT_COUNT, GLES30.GL_FLOAT, false, 0, normalDataBuffer)
331 |
332 |
333 | textureCoordinateDataBuffer = ByteBuffer.allocateDirect(textureCoordinateData.size * java.lang.Float.SIZE / 8)
334 | .order(ByteOrder.nativeOrder())
335 | .asFloatBuffer()
336 | textureCoordinateDataBuffer.put(textureCoordinateData)
337 | textureCoordinateDataBuffer.position(0)
338 | GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
339 | GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, TEXTURE_COORDINATE_COMPONENT_COUNT, GLES30.GL_FLOAT, false, 0, textureCoordinateDataBuffer)
340 |
341 | val textures = IntArray(1)
342 | GLES30.glGenTextures(textures.size, textures, 0)
343 | imageTexture = textures[0]
344 |
345 | GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
346 | val bitmap = Util.decodeBitmapFromAssets("lighting/brick.png")
347 | GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)
348 | val b = ByteBuffer.allocate(bitmap.width * bitmap.height * 4)
349 | bitmap.copyPixelsToBuffer(b)
350 | b.position(0)
351 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
352 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
353 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
354 | GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
355 | GLES30.glTexImage2D(
356 | GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, bitmap.width,
357 | bitmap.height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, b)
358 | bitmap.recycle()
359 |
360 | GLES30.glUniform1i(LOCATION_UNIFORM_TEXTURE, 0)
361 |
362 | GLES30.glEnable(GLES30.GL_DEPTH_TEST)
363 |
364 | }
365 |
366 | private fun getIdentity(): FloatArray {
367 | return floatArrayOf(
368 | 1f, 0f, 0f, 0f,
369 | 0f, 1f, 0f, 0f,
370 | 0f, 0f, 1f, 0f,
371 | 0f, 0f, 0f, 1f
372 | )
373 | }
374 |
375 | }
376 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/lighting/PointLightRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer.lighting
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import android.opengl.Matrix
6 | import io.github.kenneycode.openglespro.Util
7 | import java.nio.ByteBuffer
8 | import java.nio.ByteOrder
9 | import java.nio.FloatBuffer
10 | import javax.microedition.khronos.egl.EGLConfig
11 | import javax.microedition.khronos.opengles.GL10
12 |
13 | /**
14 | *
15 | * Coded by kenney
16 | *
17 | * http://www.github.com/kenneycode
18 | *
19 | * 点光例子
20 | * Point light sample
21 | *
22 | **/
23 |
24 | class PointLightRenderer : LightingRenderer("lighting/pointlight.vs", "lighting/pointlight.fs") {
25 |
26 | override fun onDrawFrame(gl: GL10?) {
27 | super.onDrawFrame(gl)
28 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "lightPos"), 5f, 0f, 0f)
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/kenneycode/openglespro/samples/renderer/lighting/SpotLightRenderer.kt:
--------------------------------------------------------------------------------
1 | package io.github.kenneycode.openglespro.samples.renderer.lighting
2 |
3 | import android.opengl.GLES30
4 | import android.opengl.GLSurfaceView
5 | import android.opengl.Matrix
6 | import io.github.kenneycode.openglespro.Util
7 | import java.nio.ByteBuffer
8 | import java.nio.ByteOrder
9 | import java.nio.FloatBuffer
10 | import javax.microedition.khronos.egl.EGLConfig
11 | import javax.microedition.khronos.opengles.GL10
12 |
13 | /**
14 | *
15 | * Coded by kenney
16 | *
17 | * http://www.github.com/kenneycode
18 | *
19 | * 聚光例子
20 | * Spot light sample
21 | *
22 | **/
23 |
24 | class SpotLightRenderer : LightingRenderer("lighting/spotlight.vs", "lighting/spotlightsoftedge.fs") {
25 |
26 | override fun onDrawFrame(gl: GL10?) {
27 | super.onDrawFrame(gl)
28 | GLES30.glUniform3f(GLES30.glGetUniformLocation(programId, "lightPos"), 2f, 0f, 0f)
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_common_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sample_fence_sync.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sample_lighting.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
20 |
21 |
27 |
28 |
34 |
35 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sample_matrix_transform.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_parameter_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
14 |
15 |
20 |
21 |
26 |
27 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_sample_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/test_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xhdpi/test_image.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | OpenGLESPro
3 | 着色器(Shader)
4 | 纹理数组(Texture Array)
5 | 二进制GL程序(Binary GL Program)
6 | 栅栏(Fence)
7 | 多重目标渲染(Multiple Render Target)
8 | VBO和IBO(VBO and IBO)
9 | EGL(EGL)
10 | 矩阵变换(Matrix Transform)
11 | 颜色混合(Color Blend)
12 | 光照(Lighting)
13 |
14 |
--------------------------------------------------------------------------------
/app/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 | ext.kotlin_version = '1.2.71'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.1'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenneycode/OpenGLESPro/e154744d3eee62ff5f7b2fa044b6fbd552a65777/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------