• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Google LLC All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.skar.examples.helloskar.rendering;
18 
19 import android.content.Context;
20 import android.opengl.GLES11Ext;
21 import android.opengl.GLES20;
22 import android.opengl.GLSurfaceView;
23 
24 import com.google.ar.core.Frame;
25 import com.google.ar.core.Session;
26 
27 import java.io.IOException;
28 import java.nio.ByteBuffer;
29 import java.nio.ByteOrder;
30 import java.nio.FloatBuffer;
31 
32 /**
33  * This class renders the AR background from camera feed. It creates and hosts the texture given to
34  * ARCore to be filled with the camera image.
35  */
36 public class BackgroundRenderer {
37     private static final String TAG = BackgroundRenderer.class.getSimpleName();
38 
39     // Shader names.
40     private static final String VERTEX_SHADER_NAME = "shaders/screenquad.vert";
41     private static final String FRAGMENT_SHADER_NAME = "shaders/screenquad.frag";
42 
43     private static final int COORDS_PER_VERTEX = 3;
44     private static final int TEXCOORDS_PER_VERTEX = 2;
45     private static final int FLOAT_SIZE = 4;
46 
47     private FloatBuffer quadVertices;
48     private FloatBuffer quadTexCoord;
49     private FloatBuffer quadTexCoordTransformed;
50 
51     private int quadProgram;
52 
53     private int quadPositionParam;
54     private int quadTexCoordParam;
55     private int textureId = -1;
56 
BackgroundRenderer()57     public BackgroundRenderer() {
58     }
59 
getTextureId()60     public int getTextureId() {
61         return textureId;
62     }
63 
64     /**
65      * Allocates and initializes OpenGL resources needed by the background renderer. Must be called on
66      * the OpenGL thread, typically in {@link GLSurfaceView.Renderer#onSurfaceCreated(GL10,
67      * EGLConfig)}.
68      *
69      * @param context Needed to access shader source.
70      */
createOnGlThread(Context context)71     public void createOnGlThread(Context context) throws IOException {
72         // Generate the background texture.
73         int[] textures = new int[1];
74         GLES20.glGenTextures(1, textures, 0);
75         textureId = textures[0];
76         int textureTarget = GLES11Ext.GL_TEXTURE_EXTERNAL_OES;
77         GLES20.glBindTexture(textureTarget, textureId);
78         GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
79         GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
80         GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
81         GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
82 
83         int numVertices = 4;
84         if (numVertices != QUAD_COORDS.length / COORDS_PER_VERTEX) {
85             throw new RuntimeException("Unexpected number of vertices in BackgroundRenderer.");
86         }
87 
88         ByteBuffer bbVertices = ByteBuffer.allocateDirect(QUAD_COORDS.length * FLOAT_SIZE);
89         bbVertices.order(ByteOrder.nativeOrder());
90         quadVertices = bbVertices.asFloatBuffer();
91         quadVertices.put(QUAD_COORDS);
92         quadVertices.position(0);
93 
94         ByteBuffer bbTexCoords =
95                 ByteBuffer.allocateDirect(numVertices * TEXCOORDS_PER_VERTEX * FLOAT_SIZE);
96         bbTexCoords.order(ByteOrder.nativeOrder());
97         quadTexCoord = bbTexCoords.asFloatBuffer();
98         quadTexCoord.put(QUAD_TEXCOORDS);
99         quadTexCoord.position(0);
100 
101         ByteBuffer bbTexCoordsTransformed =
102                 ByteBuffer.allocateDirect(numVertices * TEXCOORDS_PER_VERTEX * FLOAT_SIZE);
103         bbTexCoordsTransformed.order(ByteOrder.nativeOrder());
104         quadTexCoordTransformed = bbTexCoordsTransformed.asFloatBuffer();
105 
106         int vertexShader =
107                 ShaderUtil.loadGLShader(TAG, context, GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_NAME);
108         int fragmentShader =
109                 ShaderUtil.loadGLShader(TAG, context, GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_NAME);
110 
111         quadProgram = GLES20.glCreateProgram();
112         GLES20.glAttachShader(quadProgram, vertexShader);
113         GLES20.glAttachShader(quadProgram, fragmentShader);
114         GLES20.glLinkProgram(quadProgram);
115         GLES20.glUseProgram(quadProgram);
116 
117         ShaderUtil.checkGLError(TAG, "Program creation");
118 
119         quadPositionParam = GLES20.glGetAttribLocation(quadProgram, "a_Position");
120         quadTexCoordParam = GLES20.glGetAttribLocation(quadProgram, "a_TexCoord");
121 
122         ShaderUtil.checkGLError(TAG, "Program parameters");
123     }
124 
125     /**
126      * Draws the AR background image. The image will be drawn such that virtual content rendered with
127      * the matrices provided by {@link com.google.ar.core.Camera#getViewMatrix(float[], int)} and
128      * {@link com.google.ar.core.Camera#getProjectionMatrix(float[], int, float, float)} will
129      * accurately follow static physical objects. This must be called <b>before</b> drawing virtual
130      * content.
131      *
132      * @param frame The last {@code Frame} returned by {@link Session#update()}.
133      */
draw(Frame frame)134     public void draw(Frame frame) {
135         // If display rotation changed (also includes view size change), we need to re-query the uv
136         // coordinates for the screen rect, as they may have changed as well.
137         if (frame.hasDisplayGeometryChanged()) {
138             frame.transformDisplayUvCoords(quadTexCoord, quadTexCoordTransformed);
139         }
140 
141         // No need to test or write depth, the screen quad has arbitrary depth, and is expected
142         // to be drawn first.
143         GLES20.glDisable(GLES20.GL_DEPTH_TEST);
144         GLES20.glDepthMask(false);
145 
146         GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
147 
148         GLES20.glUseProgram(quadProgram);
149 
150         // Set the vertex positions.
151         GLES20.glVertexAttribPointer(
152                 quadPositionParam, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadVertices);
153 
154         // Set the texture coordinates.
155         GLES20.glVertexAttribPointer(
156                 quadTexCoordParam,
157                 TEXCOORDS_PER_VERTEX,
158                 GLES20.GL_FLOAT,
159                 false,
160                 0,
161                 quadTexCoordTransformed);
162 
163         // Enable vertex arrays
164         GLES20.glEnableVertexAttribArray(quadPositionParam);
165         GLES20.glEnableVertexAttribArray(quadTexCoordParam);
166 
167         GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
168 
169         // Disable vertex arrays
170         GLES20.glDisableVertexAttribArray(quadPositionParam);
171         GLES20.glDisableVertexAttribArray(quadTexCoordParam);
172 
173         // Restore the depth state for further drawing.
174         GLES20.glDepthMask(true);
175         GLES20.glEnable(GLES20.GL_DEPTH_TEST);
176 
177         ShaderUtil.checkGLError(TAG, "Draw");
178     }
179 
180     private static final float[] QUAD_COORDS =
181             new float[]{
182                     -1.0f, -1.0f, 0.0f, -1.0f, +1.0f, 0.0f, +1.0f, -1.0f, 0.0f, +1.0f, +1.0f, 0.0f,
183             };
184 
185     private static final float[] QUAD_TEXCOORDS =
186             new float[]{
187                     0.0f, 1.0f,
188                     0.0f, 0.0f,
189                     1.0f, 1.0f,
190                     1.0f, 0.0f,
191             };
192 }
193