1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils;
17 
18 import android.opengl.GLES20;
19 import android.util.Log;
20 
21 /**
22  * Contains shader code and helper functions for compiling them.
23  */
24 public class ShaderHelper {
25     private static final String TAG = "ShaderHelper";
26 
getCameraPreviewFragmentShader()27     public static String getCameraPreviewFragmentShader() {
28         return "#extension GL_OES_EGL_image_external : require\n" +
29                 "precision mediump float;\n" +
30                 "uniform samplerExternalOES u_Texture;\n" +
31                 "\n" +
32                 "varying vec3 v_Position;\n" +
33                 "varying vec2 v_TexCoordinate;\n" +
34                 "\n" +
35                 "void main()\n" +
36                 "{\n" +
37                 "    gl_FragColor = texture2D(u_Texture, v_TexCoordinate);\n" +
38                 "}";
39     }
40 
getCameraPreviewVertexShader()41     public static String getCameraPreviewVertexShader() {
42         return "uniform mat4 u_MVPMatrix;\n" +
43                 "uniform mat4 u_MVMatrix;\n" +
44                 "attribute vec4 a_Position;\n" +
45                 "attribute vec2 a_TexCoordinate;\n" +
46                 "\n" +
47                 "varying vec3 v_Position;\n" +
48                 "varying vec2 v_TexCoordinate;\n" +
49                 "\n" +
50                 "void main()\n" +
51                 "{\n" +
52                 "   v_Position = vec3(u_MVMatrix * a_Position);\n" +
53                 "\n" +
54                 "   v_TexCoordinate = a_TexCoordinate;\n" +
55                 "\n" +
56                 "   gl_Position = u_MVPMatrix * a_Position;\n" +
57                 "}";
58     }
59 
getRectangleFragmentShader()60     public static String getRectangleFragmentShader() {
61         return "precision mediump float;" +
62                 "varying vec4 v_Color;" +
63                 "varying vec3 v_Position;" +
64                 "void main() {" +
65                 "  gl_FragColor = v_Color;" +
66                 "}";
67 
68     }
69 
getRectangleVertexShader()70     public static String getRectangleVertexShader() {
71         return "uniform mat4 u_MVPMatrix;" +
72                 "uniform mat4 u_MVMatrix;" +
73                 "varying vec3 v_Position;" +
74                 "varying vec4 v_Color;" +
75                 "attribute vec4 a_Position;" +
76                 "attribute vec4 a_Color;" +
77                 "void main() {" +
78                 "   v_Position = vec3(u_MVMatrix * a_Position);" +
79                 "   v_Color = a_Color;" +
80                 "   gl_Position = u_MVPMatrix * a_Position;" +
81                 "}";
82     }
83 
84     /**
85      * Contains lighting information for shadows that enhance AR effect.
86      *
87      * @return the vertex shader.
88      */
getAugmentedRealityVertexShader()89     public static String getAugmentedRealityVertexShader() {
90         return "uniform mat4 u_MVPMatrix;\n"
91                 + "uniform mat4 u_MVMatrix;\n"
92 
93                 + "attribute vec4 a_Position;\n"
94                 + "attribute vec4 a_Color;\n"
95                 + "attribute vec3 a_Normal;\n"
96 
97                 + "varying vec3 v_Position;\n"
98                 + "varying vec4 v_Color;\n"
99                 + "varying vec3 v_Normal;\n"
100 
101                 + "void main()\n"
102                 + "{\n"
103                 + "   v_Position = vec3(u_MVMatrix * a_Position);\n"
104                 + "   v_Color = a_Color;\n"
105                 + "   v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));\n"
106                 + "   gl_Position = u_MVPMatrix * a_Position;\n"
107                 + "}\n";
108     }
109 
110     /**
111      * Contains lighting information for shadows that enhance AR effect.
112      *
113      * @return the fragment shader.
114      */
getAugmentedRealityFragmentShader()115     public static String getAugmentedRealityFragmentShader() {
116         return "precision mediump float;\n"
117                 + "uniform vec3 u_LightPos;\n"
118                 + "uniform float u_LightStrength;\n"
119                 + "varying vec3 v_Position;\n"
120                 + "varying vec4 v_Color;\n"
121                 + "varying vec3 v_Normal;\n"
122 
123                 + "void main()\n"
124                 + "{\n"
125                 + "   float distance = length(u_LightPos - v_Position);\n"
126                 + "   vec3 lightVector = normalize(u_LightPos - v_Position);\n"
127                 + "   float diffuse = max(dot(v_Normal, lightVector), 0.25);\n"
128                 + "   diffuse = diffuse * (u_LightStrength / (1.0 + (0.25 * distance * distance)));\n"
129                 + "   gl_FragColor = v_Color * diffuse;\n"
130                 + "}";
131     }
132 
133     /**
134      * Helper function to compile a shader.
135      *
136      * @param shaderType   The shader type.
137      * @param shaderSource The shader source code.
138      * @return An OpenGL handle to the shader.
139      */
compileShader(final int shaderType, final String shaderSource)140     public static int compileShader(final int shaderType, final String shaderSource) {
141         int shaderHandle = GLES20.glCreateShader(shaderType);
142 
143         if (shaderHandle != 0) {
144             // Pass in the shader source.
145             GLES20.glShaderSource(shaderHandle, shaderSource);
146 
147             // Compile the shader.
148             GLES20.glCompileShader(shaderHandle);
149 
150             // Get the compilation status.
151             final int[] compileStatus = new int[1];
152             GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
153 
154             // If the compilation failed, delete the shader.
155             if (compileStatus[0] == 0) {
156                 Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
157                 GLES20.glDeleteShader(shaderHandle);
158                 shaderHandle = 0;
159             }
160         }
161 
162         if (shaderHandle == 0) {
163             throw new RuntimeException("Error creating shader.");
164         }
165 
166         return shaderHandle;
167     }
168 
169     /**
170      * Helper function to compile and link a program.
171      *
172      * @param vertexShaderHandle   An OpenGL handle to an already-compiled vertex shader.
173      * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
174      * @param attributes           Attributes that need to be bound to the program.
175      * @return An OpenGL handle to the program.
176      */
createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes)177     public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) {
178         int programHandle = GLES20.glCreateProgram();
179 
180         if (programHandle != 0) {
181             // Bind the vertex shader to the program.
182             GLES20.glAttachShader(programHandle, vertexShaderHandle);
183 
184             // Bind the fragment shader to the program.
185             GLES20.glAttachShader(programHandle, fragmentShaderHandle);
186 
187             // Bind attributes
188             if (attributes != null) {
189                 final int size = attributes.length;
190                 for (int i = 0; i < size; i++) {
191                     GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
192                 }
193             }
194 
195             // Link the two shaders together into a program.
196             GLES20.glLinkProgram(programHandle);
197 
198             // Get the link status.
199             final int[] linkStatus = new int[1];
200             GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
201 
202             // If the link failed, delete the program.
203             if (linkStatus[0] == 0) {
204                 Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
205                 GLES20.glDeleteProgram(programHandle);
206                 programHandle = 0;
207             }
208         }
209 
210         if (programHandle == 0) {
211             throw new RuntimeException("Error creating program.");
212         }
213 
214         return programHandle;
215     }
216 }
217