summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorshichengfeng <shichengfeng@google.com>2015-08-18 10:22:23 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-18 17:22:58 +0000
commit2b9538c0238061c4a4c1d33a710901708977ffc7 (patch)
treecd83af2c80ab78a52a58233ecda6a0685dc05730 /remoting
parent4d53661a33c0dcff4da2fab8ad49329c2d1055e9 (diff)
downloadchromium_src-2b9538c0238061c4a4c1d33a710901708977ffc7.zip
chromium_src-2b9538c0238061c4a4c1d33a710901708977ffc7.tar.gz
chromium_src-2b9538c0238061c4a4c1d33a710901708977ffc7.tar.bz2
Android Chromoting: Add skybox environment for the Cardboard desktop activity.
Surround the view environment with a skybox environment. Note: the skybox image could be replaced easily later. BUG = 516871 Review URL: https://codereview.chromium.org/1271333002 Cr-Commit-Position: refs/heads/master@{#343950}
Diffstat (limited to 'remoting')
-rw-r--r--remoting/android/java/src/org/chromium/chromoting/CardboardDesktopRenderer.java227
-rw-r--r--remoting/android/java/src/org/chromium/chromoting/ChromotingDownloadManager.java146
-rw-r--r--remoting/android/java/src/org/chromium/chromoting/TextureHelper.java57
3 files changed, 410 insertions, 20 deletions
diff --git a/remoting/android/java/src/org/chromium/chromoting/CardboardDesktopRenderer.java b/remoting/android/java/src/org/chromium/chromoting/CardboardDesktopRenderer.java
index 33aa5e8..5d5aabb 100644
--- a/remoting/android/java/src/org/chromium/chromoting/CardboardDesktopRenderer.java
+++ b/remoting/android/java/src/org/chromium/chromoting/CardboardDesktopRenderer.java
@@ -4,8 +4,9 @@
package org.chromium.chromoting;
-import android.content.Context;
+import android.app.Activity;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.opengl.GLES20;
import android.opengl.Matrix;
@@ -15,6 +16,7 @@ import com.google.vrtoolkit.cardboard.Eye;
import com.google.vrtoolkit.cardboard.HeadTransform;
import com.google.vrtoolkit.cardboard.Viewport;
+import org.chromium.base.Log;
import org.chromium.chromoting.jni.JniInterface;
import java.nio.ByteBuffer;
@@ -37,6 +39,7 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
private static final float DESKTOP_POSITION_X = 0.0f;
private static final float DESKTOP_POSITION_Y = 0.0f;
private static final float DESKTOP_POSITION_Z = -2.0f;
+ private static final float HALF_SKYBOX_SIZE = 100.0f;
// Allows user to click even when looking outside the desktop
// but within edge margin.
@@ -55,6 +58,43 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
1.0f, 0.0f
});
+ private static final FloatBuffer SKYBOX_POSITION_COORDINATES = makeFloatBuffer(new float[] {
+ -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (0) Top-left near
+ HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (1) Top-right near
+ -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (2) Bottom-left near
+ HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (3) Bottom-right near
+ -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (4) Top-left far
+ HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (5) Top-right far
+ -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (6) Bottom-left far
+ HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE // (7) Bottom-right far
+ });
+
+ private static final ByteBuffer SKYBOX_INDICES_BYTE_BUFFER = ByteBuffer.wrap(new byte[] {
+ // Front
+ 1, 3, 0,
+ 0, 3, 2,
+
+ // Back
+ 4, 6, 5,
+ 5, 6, 7,
+
+ // Left
+ 0, 2, 4,
+ 4, 2, 6,
+
+ // Right
+ 5, 7, 1,
+ 1, 7, 3,
+
+ // Top
+ 5, 1, 4,
+ 4, 1, 0,
+
+ // Bottom
+ 6, 2, 7,
+ 7, 2, 3
+ });
+
private static final String DESKTOP_VERTEX_SHADER =
"uniform mat4 u_CombinedMatrix;"
+ "attribute vec4 a_Position;"
@@ -87,12 +127,47 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
+ " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
+ "}";
- private final Context mActivityContext;
+ private static final String SKYBOX_VERTEX_SHADER =
+ "uniform mat4 u_CombinedMatrix;"
+ + "attribute vec3 a_Position;"
+ + "varying vec3 v_Position;"
+ + "void main() {"
+ + " v_Position = a_Position;"
+ // Make sure to convert from the right-handed coordinate system of the
+ // world to the left-handed coordinate system of the cube map, otherwise,
+ // our cube map will still work but everything will be flipped.
+ + " v_Position.z = -v_Position.z;"
+ + " gl_Position = u_CombinedMatrix * vec4(a_Position, 1.0);"
+ + " gl_Position = gl_Position.xyww;"
+ + "}";
- private float mHalfDesktopWidth;
+ private static final String SKYBOX_FRAGMENT_SHADER =
+ "precision mediump float;"
+ + "uniform samplerCube u_TextureUnit;"
+ + "varying vec3 v_Position;"
+ + "void main() {"
+ + " gl_FragColor = textureCube(u_TextureUnit, v_Position);"
+ + "}";
- // Flag to indicate whether reload the desktop texture or not.
- private boolean mReloadTexture;
+ private static final String ASSETS_URI_PREFIX =
+ "https://dl.google.com/chrome-remote-desktop/android-assets/";;
+
+ private static final String[] SKYBOX_IMAGE_URIS = new String[] {
+ "https://dl.google.com/chrome-remote-desktop/android-assets/room_left.png",
+ "https://dl.google.com/chrome-remote-desktop/android-assets/room_right.png",
+ "https://dl.google.com/chrome-remote-desktop/android-assets/room_bottom.png",
+ "https://dl.google.com/chrome-remote-desktop/android-assets/room_top.png",
+ "https://dl.google.com/chrome-remote-desktop/android-assets/room_back.png",
+ "https://dl.google.com/chrome-remote-desktop/android-assets/room_front.png"
+ };
+
+ private static final String[] SKYBOX_IMAGE_NAMES = new String[] {
+ "skybox_left", "skybox_right", "skybox_bottom", "skybox_top", "skybox_back", "skybox_front"
+ };
+
+ private final Activity mActivity;
+
+ private float mHalfDesktopWidth;
private float[] mCameraMatrix;
private float[] mViewMatrix;
@@ -103,6 +178,8 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
private float[] mDesktopCombinedMatrix;
private float[] mEyePointModelMatrix;
private float[] mEyePointCombinedMatrix;
+ private float[] mSkyboxModelMatrix;
+ private float[] mSkyboxCombinedMatrix;
// Direction that user is looking towards.
private float[] mForwardVector;
@@ -123,6 +200,16 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
private int mEyePointProgramHandle;
private int mEyePointPositionHandle;
private int mEyePointCombinedMatrixHandle;
+ private int mSkyboxVertexShaderHandle;
+ private int mSkyboxFragmentShaderHandle;
+ private int mSkyboxProgramHandle;
+ private int mSkyboxPositionHandle;
+ private int mSkyboxCombinedMatrixHandle;
+ private int mSkyboxTextureUnitHandle;
+ private int mSkyboxTextureDataHandle;
+
+ // Flag to indicate whether reload the desktop texture or not.
+ private boolean mReloadTexture;
/** Lock to allow multithreaded access to mReloadTexture. */
private Object mReloadTextureLock = new Object();
@@ -136,8 +223,17 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
private FloatBuffer mDesktopCoordinates;
- public CardboardDesktopRenderer(Context context) {
- mActivityContext = context;
+ // Flag to signal that the skybox images are fully decoded and should be loaded
+ // into the OpenGL textures.
+ private boolean mLoadSkyboxImagesTexture;
+
+ // Lock to allow multithreaded access to mLoadSkyboxImagesTexture.
+ private Object mLoadSkyboxImagesTextureLock = new Object();
+
+ private ChromotingDownloadManager mDownloadManager;
+
+ public CardboardDesktopRenderer(Activity activity) {
+ mActivity = activity;
mReloadTexture = false;
mCameraMatrix = new float[16];
@@ -147,11 +243,24 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
mDesktopCombinedMatrix = new float[16];
mEyePointModelMatrix = new float[16];
mEyePointCombinedMatrix = new float[16];
+ mSkyboxModelMatrix = new float[16];
+ mSkyboxCombinedMatrix = new float[16];
mForwardVector = new float[3];
mEyePositionVector = new float[3];
attachRedrawCallback();
+
+ mDownloadManager = new ChromotingDownloadManager(mActivity, SKYBOX_IMAGE_NAMES,
+ SKYBOX_IMAGE_URIS, new ChromotingDownloadManager.Callback() {
+ @Override
+ public void onBatchDownloadComplete() {
+ synchronized (mLoadSkyboxImagesTextureLock) {
+ mLoadSkyboxImagesTexture = true;
+ }
+ }
+ });
+ mDownloadManager.download();
}
// This can be called on any thread.
@@ -203,6 +312,23 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
mEyePointCombinedMatrixHandle =
GLES20.glGetUniformLocation(mEyePointProgramHandle, "u_CombinedMatrix");
+ // Set handlers for skybox drawing.
+ GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP);
+ mSkyboxVertexShaderHandle =
+ ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, SKYBOX_VERTEX_SHADER);
+ mSkyboxFragmentShaderHandle =
+ ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, SKYBOX_FRAGMENT_SHADER);
+ mSkyboxProgramHandle = ShaderHelper.createAndLinkProgram(mSkyboxVertexShaderHandle,
+ mSkyboxFragmentShaderHandle,
+ new String[] {"a_Position", "u_CombinedMatrix", "u_TextureUnit"});
+ mSkyboxPositionHandle =
+ GLES20.glGetAttribLocation(mSkyboxProgramHandle, "a_Position");
+ mSkyboxCombinedMatrixHandle =
+ GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_CombinedMatrix");
+ mSkyboxTextureUnitHandle =
+ GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_TextureUnit");
+ mSkyboxTextureDataHandle = TextureHelper.createTextureHandle();
+
// Position the eye at the origin.
float eyeX = 0.0f;
float eyeY = 0.0f;
@@ -232,6 +358,7 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
headTransform.getForwardVector(mForwardVector, 0);
getLookingPosition();
maybeLoadTexture(mTextureDataHandle);
+ maybeLoadCubeMapAndCleanImages(mSkyboxTextureDataHandle);
}
@Override
@@ -243,6 +370,7 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
mProjectionMatrix = eye.getPerspective(Z_NEAR, Z_FAR);
+ drawSkybox();
drawDesktop();
drawEyePoint();
}
@@ -253,7 +381,15 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
GLES20.glDeleteShader(mDesktopFragmentShaderHandle);
GLES20.glDeleteShader(mEyePointVertexShaderHandle);
GLES20.glDeleteShader(mEyePointFragmentShaderHandle);
- GLES20.glDeleteTextures(1, new int[]{mTextureDataHandle}, 0);
+ GLES20.glDeleteShader(mSkyboxVertexShaderHandle);
+ GLES20.glDeleteShader(mSkyboxFragmentShaderHandle);
+ GLES20.glDeleteTextures(1, new int[] {mTextureDataHandle}, 0);
+ GLES20.glDeleteTextures(1, new int[] {mSkyboxTextureDataHandle}, 0);
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mDownloadManager.close();
+ }
+ });
}
@Override
@@ -336,6 +472,28 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, totalPointNumber);
}
+ private void drawSkybox() {
+ GLES20.glUseProgram(mSkyboxProgramHandle);
+
+ Matrix.setIdentityM(mSkyboxModelMatrix, 0);
+ Matrix.multiplyMM(mSkyboxCombinedMatrix, 0, mViewMatrix, 0, mSkyboxModelMatrix, 0);
+ Matrix.multiplyMM(mSkyboxCombinedMatrix, 0, mProjectionMatrix,
+ 0, mSkyboxCombinedMatrix, 0);
+
+ GLES20.glUniformMatrix4fv(mSkyboxCombinedMatrixHandle, 1, false,
+ mSkyboxCombinedMatrix, 0);
+ GLES20.glVertexAttribPointer(mSkyboxPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT,
+ false, 0, SKYBOX_POSITION_COORDINATES);
+ GLES20.glEnableVertexAttribArray(mSkyboxPositionHandle);
+
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, mSkyboxTextureDataHandle);
+ GLES20.glUniform1i(mSkyboxTextureUnitHandle, 0);
+
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_BYTE,
+ SKYBOX_INDICES_BYTE_BUFFER);
+ }
+
/**
* Returns coordinates in units of pixels in the desktop bitmap.
* This can be called on any thread.
@@ -387,7 +545,7 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
}
}
- /*
+ /**
* Return true if user is looking at the space to the left of the dekstop.
* This method can be called on any thread.
*/
@@ -397,7 +555,7 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
}
}
- /*
+ /**
* Return true if user is looking at the space to the right of the dekstop.
* This method can be called on any thread.
*/
@@ -488,4 +646,53 @@ public class CardboardDesktopRenderer implements CardboardView.StereoRenderer {
});
}
}
+
+ /**
+ * Decode all skybox images to Bitmap files and return them.
+ * Only call this method when we have complete skybox images.
+ * @throws DecodeFileException if BitmapFactory fails to decode file.
+ */
+ private Bitmap[] decodeSkyboxImages() throws DecodeFileException {
+ Bitmap[] result = new Bitmap[SKYBOX_IMAGE_NAMES.length];
+ String fileDirectory = mDownloadManager.getDownloadDirectory();
+ for (int i = 0; i < SKYBOX_IMAGE_NAMES.length; i++) {
+ result[i] = BitmapFactory.decodeFile(fileDirectory + "/" + SKYBOX_IMAGE_NAMES[i]);
+ if (result[i] == null) {
+ throw new DecodeFileException();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Link the skybox images with given texture handle and clean images at the end.
+ * Only call this method when we have complete skybox images.
+ */
+ private void maybeLoadCubeMapAndCleanImages(int textureHandle) {
+ synchronized (mLoadSkyboxImagesTextureLock) {
+ if (!mLoadSkyboxImagesTexture) {
+ return;
+ }
+ mLoadSkyboxImagesTexture = false;
+ }
+
+ Bitmap[] images;
+ try {
+ images = decodeSkyboxImages();
+ } catch (DecodeFileException e) {
+ Log.i(TAG, "Failed to decode image files.");
+ return;
+ }
+
+ TextureHelper.linkCubeMap(textureHandle, images);
+ for (Bitmap image : images) {
+ image.recycle();
+ }
+ }
+
+ /**
+ * Exception when BitmapFactory fails to decode file.
+ */
+ private static class DecodeFileException extends Exception {
+ }
} \ No newline at end of file
diff --git a/remoting/android/java/src/org/chromium/chromoting/ChromotingDownloadManager.java b/remoting/android/java/src/org/chromium/chromoting/ChromotingDownloadManager.java
new file mode 100644
index 0000000..5d08f45
--- /dev/null
+++ b/remoting/android/java/src/org/chromium/chromoting/ChromotingDownloadManager.java
@@ -0,0 +1,146 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chromoting;
+
+import android.app.Activity;
+import android.app.DownloadManager;
+import android.app.DownloadManager.Query;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Class that manages download operation for Chromoting activity.
+ */
+public class ChromotingDownloadManager {
+ /**
+ * Callback for download manager. This will be executed on application's main thread.
+ */
+ public interface Callback {
+ /**
+ * Called when batch download is successfully finished.
+ */
+ public void onBatchDownloadComplete();
+ }
+
+ private Activity mActivity;
+ private BroadcastReceiver mDownloadReceiver;
+ private DownloadManager mDownloadManager;
+ private Set<Long> mUnfinishedDownloadIds;
+ private Callback mCallback;
+ private String[] mNames;
+ private String[] mUris;
+
+ public ChromotingDownloadManager(Activity activity, String[] names, String[] uris,
+ Callback callback) {
+ assert names.length == uris.length;
+
+ mActivity = activity;
+ mCallback = callback;
+ mDownloadManager =
+ (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
+ mNames = names.clone();
+ mUris = uris.clone();
+ mUnfinishedDownloadIds = new HashSet<Long>();
+ }
+
+ /**
+ * Download files according to given URIs and store them as given names.
+ */
+ public void download() {
+ for (int i = 0; i < mNames.length; i++) {
+ if (needToBeDownloaded(i)) {
+ DownloadManager.Request request =
+ new DownloadManager.Request(Uri.parse(mUris[i]));
+ request.setDestinationInExternalFilesDir(mActivity.getApplicationContext(),
+ Environment.DIRECTORY_DOWNLOADS, mNames[i]);
+ mUnfinishedDownloadIds.add(mDownloadManager.enqueue(request));
+ }
+ }
+
+ if (mUnfinishedDownloadIds.isEmpty()) {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mCallback.onBatchDownloadComplete();
+ }
+ });
+ } else {
+ mDownloadReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
+ Query query = new Query();
+ query.setFilterById(convertToArray(mUnfinishedDownloadIds));
+ query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
+ Cursor cursor = mDownloadManager.query(query);
+
+ // Delete finished download id from unfinished download id set.
+ for (int i = 0; i < cursor.getCount(); i++) {
+ cursor.moveToPosition(i);
+ int downloadIdIndex = cursor.getColumnIndex(DownloadManager.COLUMN_ID);
+ mUnfinishedDownloadIds.remove(cursor.getLong(downloadIdIndex));
+ }
+
+ if (mUnfinishedDownloadIds.isEmpty()) {
+ mCallback.onBatchDownloadComplete();
+ }
+ cursor.close();
+ }
+ }
+ };
+
+ mActivity.registerReceiver(mDownloadReceiver,
+ new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
+ }
+ }
+
+ /**
+ * Perform necessary operations to close the download manager.
+ */
+ public void close() {
+ if (!mUnfinishedDownloadIds.isEmpty()) {
+ mDownloadManager.remove(convertToArray(mUnfinishedDownloadIds));
+ }
+ if (mDownloadReceiver != null) {
+ mActivity.unregisterReceiver(mDownloadReceiver);
+ }
+ }
+
+ /**
+ * Check whether the file corresponding to the given index needs to be downloaded.
+ */
+ private boolean needToBeDownloaded(int index) {
+ return !new File(getDownloadDirectory() + "/" + mNames[index]).exists();
+ }
+
+ /**
+ * Get download directory path.
+ */
+ public String getDownloadDirectory() {
+ return mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString();
+ }
+
+ /**
+ * Convert a Set of Long to an array of long.
+ */
+ private long[] convertToArray(Set<Long> data) {
+ long[] result = new long[data.size()];
+ int index = 0;
+ for (long number : data) {
+ result[index] = number;
+ index++;
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/remoting/android/java/src/org/chromium/chromoting/TextureHelper.java b/remoting/android/java/src/org/chromium/chromoting/TextureHelper.java
index f5708c8..fb710eb 100644
--- a/remoting/android/java/src/org/chromium/chromoting/TextureHelper.java
+++ b/remoting/android/java/src/org/chromium/chromoting/TextureHelper.java
@@ -4,9 +4,25 @@
package org.chromium.chromoting;
+import static android.opengl.GLES20.GL_LINEAR;
+import static android.opengl.GLES20.GL_NEAREST;
+import static android.opengl.GLES20.GL_TEXTURE_2D;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+import static android.opengl.GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
+import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
+import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
+import static android.opengl.GLES20.glBindTexture;
+import static android.opengl.GLES20.glDeleteTextures;
+import static android.opengl.GLES20.glGenTextures;
+import static android.opengl.GLES20.glTexParameteri;
+import static android.opengl.GLUtils.texImage2D;
+
import android.graphics.Bitmap;
-import android.opengl.GLES20;
-import android.opengl.GLUtils;
/**
* Helper class for working with OpenGL textures.
@@ -18,7 +34,7 @@ public class TextureHelper {
*/
public static int createTextureHandle() {
int[] textureDataHandle = new int[1];
- GLES20.glGenTextures(1, textureDataHandle, 0);
+ glGenTextures(1, textureDataHandle, 0);
if (textureDataHandle[0] != 0) {
return textureDataHandle[0];
} else {
@@ -32,17 +48,38 @@ public class TextureHelper {
*/
public static void linkTexture(int textureDataHandle, Bitmap bitmap) {
// Delete previously attached texture.
- GLES20.glDeleteTextures(1, new int[]{textureDataHandle}, 0);
+ glDeleteTextures(1, new int[]{textureDataHandle}, 0);
// Bind to the texture in OpenGL.
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandle);
+ glBindTexture(GL_TEXTURE_2D, textureDataHandle);
- GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
- GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
- GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
- GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Load the bitmap into the bound texture.
- GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
+ texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
+ }
+
+ /**
+ * Link the cubemap images with a given texture handle.
+ */
+ public static void linkCubeMap(int textureDataHandle, Bitmap[] cubeBitmaps) {
+ glBindTexture(GL_TEXTURE_CUBE_MAP, textureDataHandle);
+
+ // Linear filtering for minification and magnification.
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // Link left, right, bottom, top, back and front image in order.
+ texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, cubeBitmaps[0], 0);
+ texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, cubeBitmaps[1], 0);
+
+ texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, cubeBitmaps[2], 0);
+ texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, cubeBitmaps[3], 0);
+
+ texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, cubeBitmaps[4], 0);
+ texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, cubeBitmaps[5], 0);
}
} \ No newline at end of file