mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 07:12:40 +02:00
Merge pull request #13186 from SamGondelman/etc2comp
Android: Local texture compression using Etc2Comp
This commit is contained in:
commit
c145c0c1b8
8 changed files with 296 additions and 68 deletions
|
@ -66,19 +66,19 @@ ext {
|
|||
def baseFolder = new File(HIFI_ANDROID_PRECOMPILED)
|
||||
def appDir = new File(projectDir, 'app')
|
||||
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
|
||||
def baseUrl = ''
|
||||
def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
|
||||
|
||||
def qtFile='https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
|
||||
def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
|
||||
def qtChecksum='04599670ccca84bd2b15f6915568eb2d'
|
||||
def qtVersionId='PeoqzN31n.YvLfs9JE2SgHgZ4.IaKAlt'
|
||||
def qtVersionId='8QbCma4ryEPgBYn_8kgYgB10IvNx9I1W'
|
||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||
qtFile = 'https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_osx_armv8-libcpp_openssl.tgz'
|
||||
qtFile = 'qt-5.9.3_osx_armv8-libcpp_openssl.tgz'
|
||||
qtChecksum='4b02de9d67d6bfb202355a808d2d9c59'
|
||||
qtVersionId='HygCmtMLPYioyil0DfXckGVzhw2SXZA9'
|
||||
qtVersionId='2gfgoYCggJGyXxKiazaPGsMs1Gn9j4og'
|
||||
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
qtFile = 'https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_win_armv8-libcpp_openssl.tgz'
|
||||
qtFile = 'qt-5.9.3_win_armv8-libcpp_openssl.tgz'
|
||||
qtChecksum='c3e25db64002d0f43cf565e0ef708911'
|
||||
qtVersionId='HeVObSVLCBoc7yY7He1oBMvPIH0VkClT'
|
||||
qtVersionId='xKIteC6HO0xrmcWeMmhQcmKyPEsnUrcZ'
|
||||
}
|
||||
|
||||
def packages = [
|
||||
|
@ -88,79 +88,84 @@ def packages = [
|
|||
checksum: qtChecksum,
|
||||
],
|
||||
bullet: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/bullet-2.88_armv8-libcpp.tgz',
|
||||
file: 'bullet-2.88_armv8-libcpp.tgz',
|
||||
versionId: 'S8YaoED0Cl8sSb8fSV7Q2G1lQJSNDxqg',
|
||||
checksum: '81642779ccb110f8c7338e8739ac38a0',
|
||||
],
|
||||
draco: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/draco_armv8-libcpp.tgz',
|
||||
versionId: 'cA3tVJSmkvb1naA3l6D_Jv2Noh.4yc4m',
|
||||
file: 'draco_armv8-libcpp.tgz',
|
||||
versionId: '3.B.uBj31kWlgND3_R2xwQzT_TP6Dz_8',
|
||||
checksum: '617a80d213a5ec69fbfa21a1f2f738cd',
|
||||
],
|
||||
glad: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/glad_armv8-libcpp.zip',
|
||||
versionId: 'Q9szthzeye8fFyAA.cY26Lgn2B8kezEE',
|
||||
file: 'glad_armv8-libcpp.zip',
|
||||
versionId: 'r5Zran.JSCtvrrB6Q4KaqfIoALPw3lYY',
|
||||
checksum: 'a8ee8584cf1ccd34766c7ddd9d5e5449',
|
||||
],
|
||||
glm: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/glm-0.9.8.5-patched.tgz',
|
||||
file: 'glm-0.9.8.5-patched.tgz',
|
||||
versionId: 'cskfMoJrFlAeqI3WPxemyO_Cxt7rT9EJ',
|
||||
checksum: '067b5fe16b220b5b1a1039ba51b062ae',
|
||||
],
|
||||
gvr: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/gvrsdk_v1.101.0.tgz',
|
||||
versionId: 'UTberAIFraEfF9IVjoV66u1DTPTopgeY',
|
||||
file: 'gvrsdk_v1.101.0.tgz',
|
||||
versionId: 'nqBV_j81Uc31rC7bKIrlya_Hah4v3y5r',
|
||||
checksum: '57fd02baa069176ba18597a29b6b4fc7',
|
||||
],
|
||||
nvtt: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/nvtt_armv8-libcpp.zip',
|
||||
versionId: 'vLqrqThvpq4gp75BHMAqO6HhfTXaa0An',
|
||||
file: 'nvtt_armv8-libcpp.zip',
|
||||
versionId: 'lmkBVR5t4UF1UUwMwEirnk9H_8Nt90IO',
|
||||
checksum: 'eb46d0b683e66987190ed124aabf8910',
|
||||
sharedLibFolder: 'lib',
|
||||
includeLibs: ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so'],
|
||||
],
|
||||
openssl: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/openssl-1.1.0g_armv8.tgz',
|
||||
versionId: 'DmahmSGFS4ltpHyTdyQvv35WOeUOiib9',
|
||||
file: 'openssl-1.1.0g_armv8.tgz',
|
||||
versionId: 'AiiPjmgUZTgNj7YV1EEx2lL47aDvvvAW',
|
||||
checksum: 'cabb681fbccd79594f65fcc266e02f32',
|
||||
],
|
||||
polyvox: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/polyvox_armv8-libcpp.tgz',
|
||||
versionId: 'LDJtzMTvdm4SAc2KYg8Cg6uwWk4Vq3e3',
|
||||
checksum: '349ad5b72aaf2749ca95d847e60c5314',
|
||||
file: 'polyvox_armv8-libcpp.tgz',
|
||||
versionId: 'A2kbKiNhpIenGq23bKRRzg7IMAI5BI92',
|
||||
checksum: 'dba88b3a098747af4bb169e9eb9af57e',
|
||||
sharedLibFolder: 'lib',
|
||||
includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'],
|
||||
],
|
||||
tbb: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/tbb-2018_U1_armv8_libcpp.tgz',
|
||||
versionId: 'YZliDD8.Menh1IVXKEuLPeO3xAjJ1UdF',
|
||||
file: 'tbb-2018_U1_armv8_libcpp.tgz',
|
||||
versionId: 'mrRbWnv4O4evcM1quRH43RJqimlRtaKB',
|
||||
checksum: '20768f298f53b195e71b414b0ae240c4',
|
||||
sharedLibFolder: 'lib/release',
|
||||
includeLibs: ['libtbb.so', 'libtbbmalloc.so'],
|
||||
],
|
||||
hifiAC: [
|
||||
file: 'https://hifi-public.s3.amazonaws.com/austin/android/libplugins_libhifiCodec.zip',
|
||||
versionId: 'mzKhsRCgVmloqq5bvE.0IwYK1NjGQc_G',
|
||||
file: 'libplugins_libhifiCodec.zip',
|
||||
versionId: 'i31pW.qNbvFOXRxbyiJUxg3sphaFNmZU',
|
||||
checksum: '9412a8e12c88a4096c1fc843bb9fe52d',
|
||||
sharedLibFolder: '',
|
||||
includeLibs: ['libplugins_libhifiCodec.so']
|
||||
],
|
||||
etc2comp: [
|
||||
file: 'etc2comp-patched-armv8-libcpp.tgz',
|
||||
versionId: 'bHhGECRAQR1vkpshBcK6ByNc1BQIM8gU',
|
||||
checksum: '14b02795d774457a33bbc60e00a786bc'
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
def scribeLocalFile='scribe' + EXEC_SUFFIX
|
||||
|
||||
def scribeFile='https://hifi-public.s3.amazonaws.com/austin/android/scribe_linux_x86_64'
|
||||
def scribeFile='scribe_linux_x86_64'
|
||||
def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6'
|
||||
def scribeVersion='wgpf4dB2Ltzg4Lb2jJ4nPFsHoDkmK_OO'
|
||||
def scribeVersion='u_iTrJDaE95i2abTPXOpPZckGBIim53G'
|
||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||
scribeFile = 'https://hifi-public.s3.amazonaws.com/austin/android/scribe_osx_x86_64'
|
||||
scribeFile = 'scribe_osx_x86_64'
|
||||
scribeChecksum='72db9d32d4e1e50add755570ac5eb749'
|
||||
scribeVersion='o_NbPrktzEYtBkQf3Tn7zc1nZWzM52w6'
|
||||
scribeVersion='DAW0DmnjCRib4MD8x93bgc2Z2MpPojZC'
|
||||
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
scribeFile = 'https://hifi-public.s3.amazonaws.com/austin/android/scribe_win32_x86_64.exe'
|
||||
scribeFile = 'scribe_win32_x86_64.exe'
|
||||
scribeChecksum='678e43d290c90fda670c6fefe038a06d'
|
||||
scribeVersion='GCCJxlmd2irvNOFWfZR0U1UCLHndHQrC'
|
||||
scribeVersion='PuullrA_bPlO9kXZRt8rLe536X1UI.m7'
|
||||
}
|
||||
|
||||
def options = [
|
||||
|
@ -361,6 +366,7 @@ task verifyOpenSSL(type: Verify) { def p = packages['openssl']; src new File(bas
|
|||
task verifyPolyvox(type: Verify) { def p = packages['polyvox']; src new File(baseFolder, p['file']); checksum p['checksum'] }
|
||||
task verifyTBB(type: Verify) { def p = packages['tbb']; src new File(baseFolder, p['file']); checksum p['checksum'] }
|
||||
task verifyHifiAC(type: Verify) { def p = packages['hifiAC']; src new File(baseFolder, p['file']); checksum p['checksum'] }
|
||||
task verifyEtc2Comp(type: Verify) { def p = packages['etc2comp']; src new File(baseFolder, p['file']); checksum p['checksum'] }
|
||||
|
||||
task verifyDependencyDownloads(dependsOn: downloadDependencies) { }
|
||||
verifyDependencyDownloads.dependsOn verifyQt
|
||||
|
@ -371,6 +377,7 @@ verifyDependencyDownloads.dependsOn verifyOpenSSL
|
|||
verifyDependencyDownloads.dependsOn verifyPolyvox
|
||||
verifyDependencyDownloads.dependsOn verifyTBB
|
||||
verifyDependencyDownloads.dependsOn verifyHifiAC
|
||||
verifyDependencyDownloads.dependsOn verifyEtc2Comp
|
||||
|
||||
task extractDependencies(dependsOn: verifyDependencyDownloads) {
|
||||
doLast {
|
||||
|
@ -608,4 +615,4 @@ task testElf (dependsOn: 'externalNativeBuildDebug') {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
55
cmake/externals/etc2comp/CMakeLists.txt
vendored
Normal file
55
cmake/externals/etc2comp/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
set(EXTERNAL_NAME etc2comp)
|
||||
|
||||
if (ANDROID)
|
||||
set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19")
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
set(EXTRA_CMAKE_FLAGS -DCMAKE_CXX_FLAGS=-stdlib=libc++ -DCMAKE_EXE_LINKER_FLAGS=-stdlib=libc++)
|
||||
endif ()
|
||||
|
||||
include(ExternalProject)
|
||||
# We use a patched version of etc2comp that properly generates all the necessary mips
|
||||
# See https://github.com/google/etc2comp/pull/29
|
||||
# We also use part of https://github.com/google/etc2comp/pull/1, which fixes a bug
|
||||
# that would override CMAKE_CXX_FLAGS
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/etc2comp-patched.zip
|
||||
URL_MD5 4c96153eb179acbe619e3d99d3330595
|
||||
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} ${EXTRA_CMAKE_FLAGS}
|
||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp debug library")
|
||||
|
||||
# use generator expression to ensure the correct library is found when building different configurations in VS
|
||||
set(_LIB_FOLDER "$<$<CONFIG:RelWithDebInfo>:build/EtcLib/RelWithDebInfo>")
|
||||
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<CONFIG:MinSizeRel>:build/EtcLib/MinSizeRel>")
|
||||
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<OR:$<CONFIG:Release>,$<CONFIG:Debug>>:build/EtcLib/Release>")
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp release library")
|
||||
elseif (APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/libEtcLib.a CACHE FILEPATH "Path to EtcLib debug library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/Release/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
|
||||
else ()
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to EtcLib debug library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
|
||||
endif ()
|
||||
|
||||
set(ETC_INCLUDE_DIR ${SOURCE_DIR}/EtcLib/Etc CACHE FILEPATH "Path to Etc2Comp/Etc include directory")
|
||||
set(ETCCODEC_INCLUDE_DIR ${SOURCE_DIR}/EtcLib/EtcCodec CACHE FILEPATH "Path to Etc2Comp/EtcCodec include directory")
|
||||
# ETC2COMP_INCLUDE_DIRS will be set later by FindEtc2Comp
|
22
cmake/macros/TargetEtc2Comp.cmake
Normal file
22
cmake/macros/TargetEtc2Comp.cmake
Normal file
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Copyright 2018 High Fidelity, Inc.
|
||||
# Created by Sam Gondelman on 5/2/2018
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_ETC2COMP)
|
||||
if (ANDROID)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/etc2comp)
|
||||
set(ETC2COMP_INCLUDE_DIRS "${INSTALL_DIR}/include/Etc" "${INSTALL_DIR}/include/EtcCodec")
|
||||
set(ETC2COMP_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libEtcLib.a)
|
||||
set(ETC2COMP_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libEtcLib.a)
|
||||
select_library_configurations(ETC2COMP)
|
||||
else()
|
||||
add_dependency_external_projects(etc2comp)
|
||||
find_package(Etc2Comp REQUIRED)
|
||||
endif()
|
||||
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${ETC2COMP_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${ETC2COMP_LIBRARIES})
|
||||
endmacro()
|
37
cmake/modules/FindEtc2Comp.cmake
Normal file
37
cmake/modules/FindEtc2Comp.cmake
Normal file
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# FindEtc2Comp.cmake
|
||||
#
|
||||
# Try to find the Etc2Comp compression library.
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# ETC2COMP_FOUND - system found Etc2Comp
|
||||
# ETC2COMP_INCLUDE_DIRS - the Etc2Comp include directory
|
||||
# ETC2COMP_LIBRARIES - link to this to use Etc2Comp
|
||||
#
|
||||
# Created on 5/2/2018 by Sam Gondelman
|
||||
# Copyright 2018 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("etc2comp")
|
||||
|
||||
find_path(ETC_INCLUDE_DIR NAMES Etc.h HINTS ${ETC2COMP_SEARCH_DIRS})
|
||||
find_path(ETCCODEC_INCLUDE_DIR NAMES EtcBlock4x4.h HINTS ${ETC2COMP_SEARCH_DIRS})
|
||||
set(ETC2COMP_INCLUDE_DIRS "${ETC_INCLUDE_DIR}" "${ETCCODEC_INCLUDE_DIR}")
|
||||
|
||||
find_library(ETC2COMP_LIBRARY_DEBUG NAMES ETC2COMP ETC2COMP_LIB PATH_SUFFIXES EtcLib/Debug HINTS ${ETC2COMP_SEARCH_DIRS})
|
||||
find_library(ETC2COMP_LIBRARY_RELEASE NAMES ETC2COMP ETC2COMP_LIB PATH_SUFFIXES EtcLib/Release EtcLib HINTS ${ETC2COMP_SEARCH_DIRS})
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(ETC2COMP)
|
||||
|
||||
set(ETC2COMP_LIBRARIES ${ETC2COMP_LIBRARY})
|
||||
|
||||
find_package_handle_standard_args(ETC2COMP "Could NOT find ETC2COMP, try to set the path to ETC2COMP root folder in the system variable ETC2COMP_ROOT_DIR or create a directory etc2comp in HIFI_LIB_DIR and paste the necessary files there"
|
||||
ETC2COMP_INCLUDE_DIRS ETC2COMP_LIBRARIES)
|
||||
|
||||
mark_as_advanced(ETC2COMP_INCLUDE_DIRS ETC2COMP_LIBRARIES ETC2COMP_SEARCH_DIRS)
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -352,7 +352,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
|||
if (!Texture::evalKTXFormat(mipFormat, texelFormat, header)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Set Dimensions
|
||||
uint32_t numFaces = 1;
|
||||
switch (texture.getType()) {
|
||||
|
|
|
@ -2,3 +2,4 @@ set(TARGET_NAME image)
|
|||
setup_hifi_library()
|
||||
link_hifi_libraries(shared gpu)
|
||||
target_nvtt()
|
||||
target_etc2comp()
|
||||
|
|
|
@ -31,8 +31,17 @@ using namespace gpu;
|
|||
#define CPU_MIPMAPS 1
|
||||
#include <nvtt/nvtt.h>
|
||||
|
||||
#ifdef USE_GLES
|
||||
#include <Etc.h>
|
||||
#include <EtcFilter.h>
|
||||
#endif
|
||||
|
||||
static const glm::uvec2 SPARSE_PAGE_SIZE(128);
|
||||
#ifdef Q_OS_ANDROID
|
||||
static const glm::uvec2 MAX_TEXTURE_SIZE(2048);
|
||||
#else
|
||||
static const glm::uvec2 MAX_TEXTURE_SIZE(4096);
|
||||
#endif
|
||||
bool DEV_DECIMATE_TEXTURES = false;
|
||||
std::atomic<size_t> DECIMATED_TEXTURE_COUNT{ 0 };
|
||||
std::atomic<size_t> RECTIFIED_TEXTURE_COUNT{ 0 };
|
||||
|
@ -75,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) {
|
||||
|
@ -548,13 +563,15 @@ 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);
|
||||
}
|
||||
|
||||
const int width = localCopy.width(), height = localCopy.height();
|
||||
const void* data = static_cast<const void*>(localCopy.constBits());
|
||||
auto mipFormat = texture->getStoredMipFormat();
|
||||
|
||||
#ifndef USE_GLES
|
||||
const void* data = static_cast<const void*>(localCopy.constBits());
|
||||
nvtt::TextureType textureType = nvtt::TextureType_2D;
|
||||
nvtt::InputFormat inputFormat = nvtt::InputFormat_BGRA_8UB;
|
||||
nvtt::WrapMode wrapMode = nvtt::WrapMode_Mirror;
|
||||
|
@ -584,8 +601,6 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
|
|||
nvtt::CompressionOptions compressionOptions;
|
||||
compressionOptions.setQuality(nvtt::Quality_Production);
|
||||
|
||||
// TODO: gles: generate ETC mips instead?
|
||||
auto mipFormat = texture->getStoredMipFormat();
|
||||
if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGB) {
|
||||
compressionOptions.setFormat(nvtt::Format_BC1);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_MASK) {
|
||||
|
@ -669,21 +684,94 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
|
|||
nvtt::Compressor compressor;
|
||||
compressor.setTaskDispatcher(&dispatcher);
|
||||
compressor.process(inputOptions, compressionOptions, outputOptions);
|
||||
|
||||
#else
|
||||
int numMips = 1 + (int)log2(std::max(width, height));
|
||||
Etc::RawImage *mipMaps = new Etc::RawImage[numMips];
|
||||
Etc::Image::Format etcFormat = Etc::Image::Format::DEFAULT;
|
||||
|
||||
if (mipFormat == gpu::Element::COLOR_COMPRESSED_ETC2_RGB) {
|
||||
etcFormat = Etc::Image::Format::RGB8;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_ETC2_SRGB) {
|
||||
etcFormat = Etc::Image::Format::SRGB8;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA) {
|
||||
etcFormat = Etc::Image::Format::RGB8A1;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA) {
|
||||
etcFormat = Etc::Image::Format::SRGB8A1;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_ETC2_RGBA) {
|
||||
etcFormat = Etc::Image::Format::RGBA8;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_ETC2_SRGBA) {
|
||||
etcFormat = Etc::Image::Format::SRGBA8;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_EAC_RED) {
|
||||
etcFormat = Etc::Image::Format::R11;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_EAC_RED_SIGNED) {
|
||||
etcFormat = Etc::Image::Format::SIGNED_R11;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_EAC_XY) {
|
||||
etcFormat = Etc::Image::Format::RG11;
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_EAC_XY_SIGNED) {
|
||||
etcFormat = Etc::Image::Format::SIGNED_RG11;
|
||||
} else {
|
||||
qCWarning(imagelogging) << "Unknown mip format";
|
||||
Q_UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
const Etc::ErrorMetric errorMetric = Etc::ErrorMetric::RGBA;
|
||||
const float effort = 1.0f;
|
||||
const int numEncodeThreads = 4;
|
||||
int encodingTime;
|
||||
const float MAX_COLOR = 255.0f;
|
||||
|
||||
std::vector<vec4> floatData;
|
||||
floatData.resize(width * height);
|
||||
for (int y = 0; y < height; y++) {
|
||||
QRgb *line = (QRgb *) localCopy.scanLine(y);
|
||||
for (int x = 0; x < width; x++) {
|
||||
QRgb &pixel = line[x];
|
||||
floatData[x + y * width] = vec4(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)) / MAX_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
// free up the memory afterward to avoid bloating the heap
|
||||
localCopy = QImage(); // QImage doesn't have a clear function, so override it with an empty one.
|
||||
|
||||
Etc::EncodeMipmaps(
|
||||
(float *)floatData.data(), width, height,
|
||||
etcFormat, errorMetric, effort,
|
||||
numEncodeThreads, numEncodeThreads,
|
||||
numMips, Etc::FILTER_WRAP_NONE,
|
||||
mipMaps, &encodingTime
|
||||
);
|
||||
|
||||
for (int i = 0; i < numMips; i++) {
|
||||
if (mipMaps[i].paucEncodingBits.get()) {
|
||||
if (face >= 0) {
|
||||
texture->assignStoredMipFace(i, face, mipMaps[i].uiEncodingBitsBytes, static_cast<const gpu::Byte*>(mipMaps[i].paucEncodingBits.get()));
|
||||
} else {
|
||||
texture->assignStoredMip(i, mipMaps[i].uiEncodingBitsBytes, static_cast<const gpu::Byte*>(mipMaps[i].paucEncodingBits.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] mipMaps;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void generateMips(gpu::Texture* texture, QImage&& image, const std::atomic<bool>& abortProcessing = false, int face = -1) {
|
||||
#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
|
||||
|
@ -738,7 +826,6 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
|
|||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isColorTexturesCompressionEnabled()) {
|
||||
#ifndef USE_GLES
|
||||
if (validAlpha) {
|
||||
// NOTE: This disables BC1a compression because it was producing odd artifacts on text textures
|
||||
// for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts).
|
||||
|
@ -746,22 +833,15 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
|
|||
} else {
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGB;
|
||||
}
|
||||
#else
|
||||
if (validAlpha) {
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGBA;
|
||||
} else {
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGB;
|
||||
}
|
||||
#endif
|
||||
formatMip = formatGPU;
|
||||
} else {
|
||||
#ifdef USE_GLES
|
||||
// GLES does not support GL_BGRA
|
||||
formatMip = gpu::Element::COLOR_SRGBA_32;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGBA;
|
||||
formatMip = formatGPU;
|
||||
#else
|
||||
formatGPU = gpu::Element::COLOR_SRGBA_32;
|
||||
formatMip = gpu::Element::COLOR_SBGRA_32;
|
||||
#endif
|
||||
formatGPU = gpu::Element::COLOR_SRGBA_32;
|
||||
}
|
||||
|
||||
if (isStrict) {
|
||||
|
@ -876,16 +956,18 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
|
|||
|
||||
gpu::TexturePointer theTexture = nullptr;
|
||||
if ((image.width() > 0) && (image.height() > 0)) {
|
||||
gpu::Element formatMip = gpu::Element::VEC2NU8_XY;
|
||||
gpu::Element formatGPU = gpu::Element::VEC2NU8_XY;
|
||||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isNormalTexturesCompressionEnabled()) {
|
||||
#ifndef USE_GLES
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY;
|
||||
#else
|
||||
} else {
|
||||
#ifdef USE_GLES
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_XY;
|
||||
#else
|
||||
formatGPU = gpu::Element::VEC2NU8_XY;
|
||||
#endif
|
||||
formatMip = formatGPU;
|
||||
}
|
||||
formatMip = formatGPU;
|
||||
|
||||
theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR));
|
||||
theTexture->setSource(srcImageName);
|
||||
|
@ -917,16 +999,15 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr
|
|||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isGrayscaleTexturesCompressionEnabled()) {
|
||||
#ifndef USE_GLES
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
|
||||
#else
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_RED;
|
||||
#endif
|
||||
formatMip = formatGPU;
|
||||
} else {
|
||||
formatMip = gpu::Element::COLOR_R_8;
|
||||
#ifdef USE_GLES
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_RED;
|
||||
#else
|
||||
formatGPU = gpu::Element::COLOR_R_8;
|
||||
#endif
|
||||
}
|
||||
formatMip = formatGPU;
|
||||
|
||||
theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR));
|
||||
theTexture->setSource(srcImageName);
|
||||
|
@ -1283,19 +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()) {
|
||||
// TODO: gles: pick HDR ETC format
|
||||
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
|
||||
|
@ -1342,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());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue