├── .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 | 6 | 7 | 8 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 31 | 32 | 33 | 34 | 35 | 36 | 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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------