mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +02:00
Add prototype KTX manipulation tool
This commit is contained in:
parent
4eb77b1970
commit
d0be19ab41
3 changed files with 226 additions and 0 deletions
|
@ -12,6 +12,9 @@ if (BUILD_TOOLS)
|
|||
add_subdirectory(ice-client)
|
||||
set_target_properties(ice-client PROPERTIES FOLDER "Tools")
|
||||
|
||||
add_subdirectory(ktx-tool)
|
||||
set_target_properties(ktx-tool PROPERTIES FOLDER "Tools")
|
||||
|
||||
add_subdirectory(ac-client)
|
||||
set_target_properties(ac-client PROPERTIES FOLDER "Tools")
|
||||
|
||||
|
|
14
tools/ktx-tool/CMakeLists.txt
Normal file
14
tools/ktx-tool/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
set(TARGET_NAME ktx-tool)
|
||||
|
||||
setup_hifi_project(Quick Gui Concurrent)
|
||||
|
||||
link_hifi_libraries(shared networking image gl gpu ktx)
|
||||
|
||||
target_gli()
|
||||
|
||||
setup_memory_debugger()
|
||||
|
||||
if (WIN32)
|
||||
package_libraries_for_deployment()
|
||||
endif()
|
||||
|
209
tools/ktx-tool/src/main.cpp
Normal file
209
tools/ktx-tool/src/main.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <gli/gli.hpp>
|
||||
#include <gli/convert.hpp>
|
||||
#include <gli/generate_mipmaps.hpp>
|
||||
#include <gli/load.hpp>
|
||||
#include <gli/save.hpp>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
#include <QtCore/QResource>
|
||||
|
||||
#include <QtGui/QResizeEvent>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
#include <gl/Config.h>
|
||||
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Stream.h>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <PathUtils.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <PerfStat.h>
|
||||
#include <PathUtils.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/Texture.h>
|
||||
|
||||
#include <ktx/KTX.h>
|
||||
|
||||
|
||||
|
||||
|
||||
void stripKtxKeyValues(const std::string& sourceFile, const std::string& destFile) {
|
||||
auto sourceStorage = std::make_shared<storage::FileStorage>(sourceFile.c_str());
|
||||
auto ktx = ktx::KTX::create(sourceStorage);
|
||||
auto newStorageSize = ktx::KTX::evalStorageSize(ktx->_header, ktx->_images);
|
||||
storage::FileStorage::create(destFile.c_str(), newStorageSize, nullptr);
|
||||
storage::FileStorage destStorage(destFile.c_str());
|
||||
auto writtenSize = ktx::KTX::write(destStorage.mutableData(), newStorageSize, ktx->_header, ktx->_images);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const QDir SOURCE_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin" };
|
||||
const QDir DEST_FOLDER{ PathUtils::projectRootPath() + "/interface/resources/meshes/mannequin/+gles" };
|
||||
const gli::gl GL(gli::gl::PROFILE_GL33);
|
||||
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||
#ifdef Q_OS_WIN
|
||||
OutputDebugStringA(message.toStdString().c_str());
|
||||
OutputDebugStringA("\n");
|
||||
#endif
|
||||
std::cout << message.toStdString() << std::endl;
|
||||
}
|
||||
|
||||
static inline glm::uvec2 evalMipDimension(uint32_t mipLevel, const glm::uvec2& dims) {
|
||||
return glm::uvec2{
|
||||
std::max(dims.x >> mipLevel, 1U),
|
||||
std::max(dims.y >> mipLevel, 1U),
|
||||
};
|
||||
}
|
||||
|
||||
void processKtxFile(const QFileInfo& inputFileInfo) {
|
||||
const QString inputFileName = inputFileInfo.absoluteFilePath();
|
||||
const QString compressedFileName = DEST_FOLDER.absoluteFilePath(inputFileInfo.fileName());
|
||||
const QString finalFilename = compressedFileName + ".new.ktx";
|
||||
if (QFileInfo(finalFilename).exists()) {
|
||||
return;
|
||||
}
|
||||
qDebug() << inputFileName;
|
||||
qDebug() << compressedFileName;
|
||||
auto uncomrpessedKtx = ktx::KTX::create(std::make_shared<storage::FileStorage>(compressedFileName));
|
||||
if (!uncomrpessedKtx) {
|
||||
throw std::runtime_error("Unable to load texture using hifi::ktx");
|
||||
}
|
||||
|
||||
auto compressedKtx = ktx::KTX::create(std::make_shared<storage::FileStorage>(inputFileName));
|
||||
if (!compressedKtx) {
|
||||
throw std::runtime_error("Unable to load texture using hifi::ktx");
|
||||
}
|
||||
|
||||
|
||||
auto outputKtx = ktx::KTX::create(uncomrpessedKtx->getHeader(), uncomrpessedKtx->_images, compressedKtx->_keyValues);
|
||||
auto outputStorage = outputKtx->getStorage();
|
||||
|
||||
storage::FileStorage::create(finalFilename, outputStorage->size(), outputStorage->data());
|
||||
#if 0
|
||||
const auto& header = inputKtx->getHeader();
|
||||
|
||||
|
||||
detexTexture **input_textures;
|
||||
int nu_levels;
|
||||
if (!detexLoadTextureFileWithMipmaps(inputFileName.toStdString().c_str(), 32, &input_textures, &nu_levels)) {
|
||||
return;
|
||||
//throw std::runtime_error(detexGetErrorMessage());
|
||||
}
|
||||
|
||||
switch (header.glInternalFormat) {
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
outputHeader.glFormat = GL_RGBA;
|
||||
outputHeader.glInternalFormat = GL_RGBA8;
|
||||
break;
|
||||
|
||||
case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
|
||||
outputHeader.glFormat = GL_RG;
|
||||
outputHeader.glInternalFormat = GL_RG8;
|
||||
qWarning() << "Unsupported";
|
||||
return;
|
||||
break;
|
||||
|
||||
case GL_COMPRESSED_RED_RGTC1_EXT:
|
||||
outputHeader.glFormat = GL_RED;
|
||||
outputHeader.glInternalFormat = GL_R8;
|
||||
qWarning() << "Unsupported";
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
qWarning() << "Unsupported";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto outputKtx = ktx::KTX::createBare(outputHeader, ktx->_keyValues);
|
||||
auto outputDescriptor = outputKtx->toDescriptor();
|
||||
auto outputStorage = outputKtx->getStorage();
|
||||
auto outputPointer = outputStorage->mutableData();
|
||||
auto outputSize = outputStorage->size();
|
||||
|
||||
glm::uvec2 dimensions{ header.pixelWidth, header.pixelHeight };
|
||||
for (uint16_t mip = 0; mip < header.numberOfMipmapLevels; ++mip) {
|
||||
auto mipDimensions = evalMipDimension(mip, dimensions);
|
||||
|
||||
for (uint8_t face = 0; face < header.numberOfFaces; ++face) {
|
||||
auto faceSize = outputDescriptor.getMipFaceTexelsSize(mip, face);
|
||||
auto faceOffset = outputDescriptor.getMipFaceTexelsOffset(mip, face);
|
||||
assert(faceOffset + faceSize <= outputSize);
|
||||
auto mipFace = ktx->getMipFaceTexelsData(mip, face);
|
||||
auto outputMipFace = outputKtx->getMipFaceTexelsData();
|
||||
if (header.glInternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
|
||||
BlockDecompressImageDXT5(mipDimensions.x, mipDimensions.y, mipFace->data(), (unsigned long*)(outputPointer + faceOffset));
|
||||
} else if (header.glInternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT) {
|
||||
BlockDecompressImageDXT1(mipDimensions.x, mipDimensions.y, mipFace->data(), (unsigned long*)(outputPointer + faceOffset));
|
||||
} else {
|
||||
qWarning() << "Unsupported";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
storage::FileStorage::create(outputFileName, outputStorage->size(), outputStorage->data());
|
||||
#endif
|
||||
//if (gliTexture.empty()) {
|
||||
// throw std::runtime_error("Unable to load texture using GLI");
|
||||
//}
|
||||
//gli::texture2d gliTextureConverted = gli::convert(gliTexture, gli::FORMAT_RGBA8_UNORM_PACK8);
|
||||
}
|
||||
|
||||
void scanDir(const QDir& dir) {
|
||||
|
||||
auto entries = dir.entryInfoList();
|
||||
for (const auto& entry : entries) {
|
||||
if (entry.isDir()) {
|
||||
scanDir(QDir(entry.absoluteFilePath()));
|
||||
} else {
|
||||
qDebug() << entry.absoluteFilePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
qInstallMessageHandler(messageHandler);
|
||||
{
|
||||
QDir destFolder(DEST_FOLDER);
|
||||
if (!destFolder.exists() && !destFolder.mkpath(".")) {
|
||||
throw std::runtime_error("failed to create output directory");
|
||||
}
|
||||
for (const auto ktxFile : SOURCE_FOLDER.entryInfoList(QStringList() << "*.ktx")) {
|
||||
processKtxFile(ktxFile);
|
||||
}
|
||||
qDebug() << "Done";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue