aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/rendering/BackgroundRenderer.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/rendering/BackgroundRenderer.java')
-rw-r--r--platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/rendering/BackgroundRenderer.java190
1 files changed, 190 insertions, 0 deletions
diff --git a/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/rendering/BackgroundRenderer.java b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/rendering/BackgroundRenderer.java
new file mode 100644
index 0000000000..b6b5a859b8
--- /dev/null
+++ b/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/rendering/BackgroundRenderer.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.skar.examples.helloskar.rendering;
+
+import android.content.Context;
+import android.opengl.GLES11Ext;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+import com.google.ar.core.Frame;
+import com.google.ar.core.Session;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * This class renders the AR background from camera feed. It creates and hosts the texture given to
+ * ARCore to be filled with the camera image.
+ */
+public class BackgroundRenderer {
+ private static final String TAG = BackgroundRenderer.class.getSimpleName();
+
+ // Shader names.
+ private static final String VERTEX_SHADER_NAME = "shaders/screenquad.vert";
+ private static final String FRAGMENT_SHADER_NAME = "shaders/screenquad.frag";
+
+ private static final int COORDS_PER_VERTEX = 3;
+ private static final int TEXCOORDS_PER_VERTEX = 2;
+ private static final int FLOAT_SIZE = 4;
+
+ private FloatBuffer quadVertices;
+ private FloatBuffer quadTexCoord;
+ private FloatBuffer quadTexCoordTransformed;
+
+ private int quadProgram;
+
+ private int quadPositionParam;
+ private int quadTexCoordParam;
+ private int textureId = -1;
+
+ public BackgroundRenderer() {
+ }
+
+ public int getTextureId() {
+ return textureId;
+ }
+
+ /**
+ * Allocates and initializes OpenGL resources needed by the background renderer. Must be called on
+ * the OpenGL thread, typically in {@link GLSurfaceView.Renderer#onSurfaceCreated(GL10,
+ * EGLConfig)}.
+ *
+ * @param context Needed to access shader source.
+ */
+ public void createOnGlThread(Context context) throws IOException {
+ // Generate the background texture.
+ int[] textures = new int[1];
+ GLES20.glGenTextures(1, textures, 0);
+ textureId = textures[0];
+ int textureTarget = GLES11Ext.GL_TEXTURE_EXTERNAL_OES;
+ GLES20.glBindTexture(textureTarget, textureId);
+ GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
+ GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
+ GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
+ GLES20.glTexParameteri(textureTarget, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
+
+ int numVertices = 4;
+ if (numVertices != QUAD_COORDS.length / COORDS_PER_VERTEX) {
+ throw new RuntimeException("Unexpected number of vertices in BackgroundRenderer.");
+ }
+
+ ByteBuffer bbVertices = ByteBuffer.allocateDirect(QUAD_COORDS.length * FLOAT_SIZE);
+ bbVertices.order(ByteOrder.nativeOrder());
+ quadVertices = bbVertices.asFloatBuffer();
+ quadVertices.put(QUAD_COORDS);
+ quadVertices.position(0);
+
+ ByteBuffer bbTexCoords =
+ ByteBuffer.allocateDirect(numVertices * TEXCOORDS_PER_VERTEX * FLOAT_SIZE);
+ bbTexCoords.order(ByteOrder.nativeOrder());
+ quadTexCoord = bbTexCoords.asFloatBuffer();
+ quadTexCoord.put(QUAD_TEXCOORDS);
+ quadTexCoord.position(0);
+
+ ByteBuffer bbTexCoordsTransformed =
+ ByteBuffer.allocateDirect(numVertices * TEXCOORDS_PER_VERTEX * FLOAT_SIZE);
+ bbTexCoordsTransformed.order(ByteOrder.nativeOrder());
+ quadTexCoordTransformed = bbTexCoordsTransformed.asFloatBuffer();
+
+ int vertexShader =
+ ShaderUtil.loadGLShader(TAG, context, GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_NAME);
+ int fragmentShader =
+ ShaderUtil.loadGLShader(TAG, context, GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_NAME);
+
+ quadProgram = GLES20.glCreateProgram();
+ GLES20.glAttachShader(quadProgram, vertexShader);
+ GLES20.glAttachShader(quadProgram, fragmentShader);
+ GLES20.glLinkProgram(quadProgram);
+ GLES20.glUseProgram(quadProgram);
+
+ ShaderUtil.checkGLError(TAG, "Program creation");
+
+ quadPositionParam = GLES20.glGetAttribLocation(quadProgram, "a_Position");
+ quadTexCoordParam = GLES20.glGetAttribLocation(quadProgram, "a_TexCoord");
+
+ ShaderUtil.checkGLError(TAG, "Program parameters");
+ }
+
+ /**
+ * Draws the AR background image. The image will be drawn such that virtual content rendered with
+ * the matrices provided by {@link com.google.ar.core.Camera#getViewMatrix(float[], int)} and
+ * {@link com.google.ar.core.Camera#getProjectionMatrix(float[], int, float, float)} will
+ * accurately follow static physical objects. This must be called <b>before</b> drawing virtual
+ * content.
+ *
+ * @param frame The last {@code Frame} returned by {@link Session#update()}.
+ */
+ public void draw(Frame frame) {
+ // If display rotation changed (also includes view size change), we need to re-query the uv
+ // coordinates for the screen rect, as they may have changed as well.
+ if (frame.hasDisplayGeometryChanged()) {
+ frame.transformDisplayUvCoords(quadTexCoord, quadTexCoordTransformed);
+ }
+
+ // No need to test or write depth, the screen quad has arbitrary depth, and is expected
+ // to be drawn first.
+ GLES20.glDisable(GLES20.GL_DEPTH_TEST);
+ GLES20.glDepthMask(false);
+
+ GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
+
+ GLES20.glUseProgram(quadProgram);
+
+ // Set the vertex positions.
+ GLES20.glVertexAttribPointer(
+ quadPositionParam, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadVertices);
+
+ // Set the texture coordinates.
+ GLES20.glVertexAttribPointer(
+ quadTexCoordParam,
+ TEXCOORDS_PER_VERTEX,
+ GLES20.GL_FLOAT,
+ false,
+ 0,
+ quadTexCoordTransformed);
+
+ // Enable vertex arrays
+ GLES20.glEnableVertexAttribArray(quadPositionParam);
+ GLES20.glEnableVertexAttribArray(quadTexCoordParam);
+
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+
+ // Disable vertex arrays
+ GLES20.glDisableVertexAttribArray(quadPositionParam);
+ GLES20.glDisableVertexAttribArray(quadTexCoordParam);
+
+ // Restore the depth state for further drawing.
+ GLES20.glDepthMask(true);
+ GLES20.glEnable(GLES20.GL_DEPTH_TEST);
+
+ ShaderUtil.checkGLError(TAG, "Draw");
+ }
+
+ private static final float[] QUAD_COORDS =
+ new float[]{
+ -1.0f, -1.0f, 0.0f, -1.0f, +1.0f, 0.0f, +1.0f, -1.0f, 0.0f, +1.0f, +1.0f, 0.0f,
+ };
+
+ private static final float[] QUAD_TEXCOORDS =
+ new float[]{
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ };
+}