diff --git a/android/build.gradle b/android/build.gradle
index 71d48e28d4..c771c776b5 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -14,7 +14,7 @@ buildscript {
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.1.0'
+        classpath 'com.android.tools.build:gradle:3.0.1'
     }
 }
 
@@ -126,8 +126,8 @@ def packages = [
     ],
     polyvox: [
         file: 'polyvox_armv8-libcpp.tgz',
-        versionId: 'UmHp.EOFiepdXnv2YxwNXNO3J6nVsBkE',
-        checksum: '5c918288741ee754c16aeb12bb46b9e1',
+        versionId: 'A2kbKiNhpIenGq23bKRRzg7IMAI5BI92',
+        checksum: 'dba88b3a098747af4bb169e9eb9af57e',
         sharedLibFolder: 'lib',
         includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'],
     ],
diff --git a/cmake/macros/TargetEtc2Comp.cmake b/cmake/macros/TargetEtc2Comp.cmake
index 8dfae175a9..44152a58d2 100644
--- a/cmake/macros/TargetEtc2Comp.cmake
+++ b/cmake/macros/TargetEtc2Comp.cmake
@@ -14,7 +14,7 @@ macro(TARGET_ETC2COMP)
         select_library_configurations(ETC2COMP)
     else()
         add_dependency_external_projects(etc2comp)
-        find_package(ETC2COMP REQUIRED)
+        find_package(Etc2Comp REQUIRED)
     endif()
 
     target_include_directories(${TARGET_NAME} PRIVATE ${ETC2COMP_INCLUDE_DIRS})
diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp
index ed9505766b..a92243f808 100755
--- a/libraries/gpu/src/gpu/Texture.cpp
+++ b/libraries/gpu/src/gpu/Texture.cpp
@@ -684,9 +684,9 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
 
     PROFILE_RANGE(render_gpu, "sphericalHarmonicsFromTexture");
 
+#ifndef USE_GLES
     auto mipFormat = cubeTexture.getStoredMipFormat();
     std::function<glm::vec3(uint32)> unpackFunc;
-
     switch (mipFormat.getSemantic()) {
         case gpu::R11G11B10:
             unpackFunc = glm::unpackF2x11_1x10;
@@ -698,6 +698,7 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
             assert(false);
             break;
     }
+#endif
 
     const uint sqOrder = order*order;
 
@@ -732,7 +733,11 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
     for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
         PROFILE_RANGE(render_gpu, "ProcessFace");
 
+#ifndef USE_GLES
         auto data = reinterpret_cast<const uint32*>( cubeTexture.accessStoredMipFace(0, face)->readData() );
+#else
+        auto data = cubeTexture.accessStoredMipFace(0, face)->readData();
+#endif
         if (data == nullptr) {
             continue;
         }
@@ -816,8 +821,15 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
                 glm::vec3 color{ 0.0f, 0.0f, 0.0f };
                 for (int i = 0; i < stride; ++i) {
                     for (int j = 0; j < stride; ++j) {
+#ifndef USE_GLES
                         int k = (int)(x + i - halfStride + (y + j - halfStride) * width);
                         color += unpackFunc(data[k]);
+#else
+                        const int NUM_COMPONENTS_PER_PIXEL = 4;
+                        int k = NUM_COMPONENTS_PER_PIXEL * (int)(x + i - halfStride + (y + j - halfStride) * width);
+                        // BGRA -> RGBA
+                        color += glm::pow(glm::vec3(data[k + 2], data[k + 1], data[k]) / 255.0f, glm::vec3(2.2f));
+#endif
                     }
                 }
 
diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp
index 2fc22b4eac..63a4725f64 100644
--- a/libraries/image/src/image/Image.cpp
+++ b/libraries/image/src/image/Image.cpp
@@ -84,7 +84,13 @@ const QStringList getSupportedFormats() {
     return stringFormats;
 }
 
+
+// On GLES, we don't use HDR skyboxes
+#ifndef USE_GLES
 QImage::Format QIMAGE_HDR_FORMAT = QImage::Format_RGB30;
+#else
+QImage::Format QIMAGE_HDR_FORMAT = QImage::Format_RGB32;
+#endif
 
 TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) {
     switch (type) {
@@ -557,7 +563,7 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
     // https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f18-for-consume-parameters-pass-by-x-and-stdmove-the-parameter
     QImage localCopy = std::move(image);
 
-    if (localCopy.format() != QImage::Format_ARGB32) {
+    if (localCopy.format() != QImage::Format_ARGB32 && localCopy.format() != QIMAGE_HDR_FORMAT) {
         localCopy = localCopy.convertToFormat(QImage::Format_ARGB32);
     }
 
@@ -757,11 +763,15 @@ void generateMips(gpu::Texture* texture, QImage&& image, const std::atomic<bool>
 #if CPU_MIPMAPS
     PROFILE_RANGE(resource_parse, "generateMips");
 
+#ifndef USE_GLES
     if (image.format() == QIMAGE_HDR_FORMAT) {
         generateHDRMips(texture, std::move(image), abortProcessing, face);
     } else  {
         generateLDRMips(texture, std::move(image), abortProcessing, face);
     }
+#else
+    generateLDRMips(texture, std::move(image), abortProcessing, face);
+#endif
 #else
     texture->setAutoGenerateMips(true);
 #endif
@@ -1354,18 +1364,25 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI
     QImage image = processSourceImage(std::move(localCopy), true);
 
     if (image.format() != QIMAGE_HDR_FORMAT) {
+#ifndef USE_GLES
         image = convertToHDRFormat(std::move(image), HDR_FORMAT);
+#else
+        image = image.convertToFormat(QImage::Format_RGB32);
+#endif
     }
 
     gpu::Element formatMip;
     gpu::Element formatGPU;
     if (isCubeTexturesCompressionEnabled()) {
-        formatMip = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
         formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
     } else {
-        formatMip = HDR_FORMAT;
+#ifdef USE_GLES
+        formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGB;
+#else
         formatGPU = HDR_FORMAT;
+#endif
     }
+    formatMip = formatGPU;
 
     // Find the layout of the cubemap in the 2D image
     // Use the original image size since processSourceImage may have altered the size / aspect ratio
@@ -1412,9 +1429,16 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI
         // Generate irradiance while we are at it
         if (generateIrradiance) {
             PROFILE_RANGE(resource_parse, "generateIrradiance");
-            auto irradianceTexture = gpu::Texture::createCube(HDR_FORMAT, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
+            gpu::Element irradianceFormat;
+            // TODO: we could locally compress the irradiance texture on Android, but we don't need to
+#ifndef USE_GLES
+            irradianceFormat = HDR_FORMAT;
+#else
+            irradianceFormat = gpu::Element::COLOR_SRGBA_32;
+#endif
+            auto irradianceTexture = gpu::Texture::createCube(irradianceFormat, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
             irradianceTexture->setSource(srcImageName);
-            irradianceTexture->setStoredMipFormat(HDR_FORMAT);
+            irradianceTexture->setStoredMipFormat(irradianceFormat);
             for (uint8 face = 0; face < faces.size(); ++face) {
                 irradianceTexture->assignStoredMipFace(0, face, faces[face].byteCount(), faces[face].constBits());
             }