Support KTX texture of R8G8B8 format in basic example.

This commit is contained in:
Syoyo Fujita 2019-07-05 16:19:34 +09:00
parent 006ab90c67
commit c7bf800075
7 changed files with 313 additions and 33 deletions

View File

@ -14,6 +14,7 @@
#endif #endif
// Inlude tinyktx.h before tiny_gltf.h // Inlude tinyktx.h before tiny_gltf.h
// to get TKTX_*** definitions
#define TINYKTX_IMPLEMENTATION #define TINYKTX_IMPLEMENTATION
#include "../../tinyktx.h" #include "../../tinyktx.h"
@ -27,6 +28,8 @@
#define TINYGLTF_NOEXCEPTION #define TINYGLTF_NOEXCEPTION
#define JSON_NOEXCEPTION #define JSON_NOEXCEPTION
#define TINYGLTF_ENABLE_KTX #define TINYGLTF_ENABLE_KTX
// tinyktx.h is already included above,
// so let tiny_gltf.h know do not include tinyktx.h anymore
#define TINYGLTF_NO_INCLUDE_TINY_KTX #define TINYGLTF_NO_INCLUDE_TINY_KTX
#include "../../tiny_gltf.h" #include "../../tiny_gltf.h"
@ -56,6 +59,30 @@ bool loadModel(tinygltf::Model &model, const char *filename) {
return res; return res;
} }
static bool GetOpenGLFormatFromKTX(int ktx_fmt, GLint *internal_format, GLenum *format, GLenum *type) {
#if defined(TINYGLTF_ENABLE_KTX)
bool ret = true;
std::cout << "fmt = " << ktx_fmt << ", rgb8 fmt = " << TKTX_R8G8B8_UNORM << "\n";
if (ktx_fmt == TKTX_R8G8B8_UNORM) {
(*internal_format) = GL_RGB;
(*format) = GL_RGB;
(*type) = GL_UNSIGNED_BYTE;
} else {
// TODO(syoyo): Support more KTX formats.
ret = false;
}
return ret;
#else
(void)fmt;
(void)internal_format;
(void)internal_format;
return false;
#endif
}
std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos, std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
tinygltf::Model &model, tinygltf::Mesh &mesh) { tinygltf::Model &model, tinygltf::Mesh &mesh) {
for (size_t i = 0; i < model.bufferViews.size(); ++i) { for (size_t i = 0; i < model.bufferViews.size(); ++i) {
@ -114,7 +141,7 @@ std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
accessor.normalized ? GL_TRUE : GL_FALSE, accessor.normalized ? GL_TRUE : GL_FALSE,
byteStride, BUFFER_OFFSET(accessor.byteOffset)); byteStride, BUFFER_OFFSET(accessor.byteOffset));
} else } else
std::cout << "vaa missing: " << attrib.first << std::endl; std::cout << "Unsupported vertex attribute: " << attrib.first << std::endl;
} }
GLuint texid; GLuint texid;
@ -130,29 +157,52 @@ std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLint internal_format = GL_RGBA;
GLenum format = GL_RGBA; GLenum format = GL_RGBA;
if (image.component == 1) {
format = GL_RED;
} else if (image.component == 2) {
format = GL_RG;
} else if (image.component == 3) {
format = GL_RGB;
} else {
// ???
}
GLenum type = GL_UNSIGNED_BYTE; GLenum type = GL_UNSIGNED_BYTE;
if (image.bits == 8) {
// ok bool valid = false;
} else if (image.bits == 16) {
type = GL_UNSIGNED_SHORT; // KTX extension
if (image.extras.Has("ktx_format")) {
valid = GetOpenGLFormatFromKTX(image.extras.Get("ktx_format").Get<int>(), &internal_format, &format, &type);
if (valid) {
std::cout << "ktx_format: " << image.extras.Get("ktx_format").Get<int>() << std::endl;
std::cout << "ktx image size: " << image.width << ", " << image.height << std::endl;
}
} else { } else {
// ???
if (image.component == 1) {
format = GL_RED;
} else if (image.component == 2) {
format = GL_RG;
} else if (image.component == 3) {
format = GL_RGB;
} else if (image.component == 4) {
format = GL_RGBA;
} else {
valid = false;
}
if (image.bits == 8) {
// ok
} else if (image.bits == 16) {
type = GL_UNSIGNED_SHORT;
} else {
valid = false;
}
} }
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, if (valid) {
format, type, &image.image.at(0));
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image.width, image.height, 0,
format, type, &image.image.at(0));
}
} }
return vbos; return vbos;

BIN
models/Cube-KTX/Cube.bin Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

193
models/Cube-KTX/Cube.gltf Normal file
View File

@ -0,0 +1,193 @@
{
"accessors" : [
{
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5123,
"count" : 36,
"max" : [
35
],
"min" : [
0
],
"type" : "SCALAR"
},
{
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 36,
"max" : [
1.000000,
1.000000,
1.000001
],
"min" : [
-1.000000,
-1.000000,
-1.000000
],
"type" : "VEC3"
},
{
"bufferView" : 2,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 36,
"max" : [
1.000000,
1.000000,
1.000000
],
"min" : [
-1.000000,
-1.000000,
-1.000000
],
"type" : "VEC3"
},
{
"bufferView" : 3,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 36,
"max" : [
1.000000,
-0.000000,
-0.000000,
1.000000
],
"min" : [
0.000000,
-0.000000,
-1.000000,
-1.000000
],
"type" : "VEC4"
},
{
"bufferView" : 4,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 36,
"max" : [
1.000000,
1.000000
],
"min" : [
-1.000000,
-1.000000
],
"type" : "VEC2"
}
],
"asset" : {
"generator" : "VKTS glTF 2.0 exporter",
"version" : "2.0"
},
"bufferViews" : [
{
"buffer" : 0,
"byteLength" : 72,
"byteOffset" : 0,
"target" : 34963
},
{
"buffer" : 0,
"byteLength" : 432,
"byteOffset" : 72,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 432,
"byteOffset" : 504,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 576,
"byteOffset" : 936,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 288,
"byteOffset" : 1512,
"target" : 34962
}
],
"buffers" : [
{
"byteLength" : 1800,
"uri" : "Cube.bin"
}
],
"images" : [
{
"uri" : "Cube_BaseColor.ktx"
},
{
"uri" : "Cube_MetallicRoughness.ktx"
}
],
"materials" : [
{
"name" : "Cube",
"pbrMetallicRoughness" : {
"baseColorTexture" : {
"index" : 0
},
"metallicRoughnessTexture" : {
"index" : 1
}
}
}
],
"meshes" : [
{
"name" : "Cube",
"primitives" : [
{
"attributes" : {
"NORMAL" : 2,
"POSITION" : 1,
"TANGENT" : 3,
"TEXCOORD_0" : 4
},
"indices" : 0,
"material" : 0,
"mode" : 4
}
]
}
],
"nodes" : [
{
"mesh" : 0,
"name" : "Cube"
}
],
"samplers" : [
{}
],
"scene" : 0,
"scenes" : [
{
"nodes" : [
0
]
}
],
"textures" : [
{
"sampler" : 0,
"source" : 0
},
{
"sampler" : 0,
"source" : 1
}
]
}

Binary file not shown.

Binary file not shown.

12
models/Cube-KTX/README.md Normal file
View File

@ -0,0 +1,12 @@
License: Donated by Norbert Nopper for glTF testing.
https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Cube
----
Converted .png to .ktx image by Syoyo Fujita.
.png -> .ppm using image magic(resize with 25% to reduce file size)
.ppm -> .ktx using `toktx` in KTX-Software https://github.com/KhronosGroup/KTX-Software

View File

@ -1808,6 +1808,7 @@ static void tinyktxCallbackError(void *user, char const *msg) {
static void *tinyktxCallbackAlloc(void *user, size_t size) { static void *tinyktxCallbackAlloc(void *user, size_t size) {
(void)user; (void)user;
//std::cerr << "Alloc : " << std::to_string(size) << "\n";
return malloc(size); return malloc(size);
}; };
@ -1819,7 +1820,7 @@ static void tinyktxCallbackFree(void *user, void *data) {
static size_t tinyktxCallbackRead(void *user, void* data, size_t size) { static size_t tinyktxCallbackRead(void *user, void* data, size_t size) {
SimpleVFile *ss = reinterpret_cast<SimpleVFile *>(user); SimpleVFile *ss = reinterpret_cast<SimpleVFile *>(user);
if ((ss->pos + size) >= ss->len) { if ((ss->pos + size) > ss->len) {
if (ss->err) { if (ss->err) {
std::stringstream msg; std::stringstream msg;
msg << "KTX read: Invalid data length. pos = " << ss->pos << ", len = " << ss->len << ", requested size to read = " << size << "\n"; msg << "KTX read: Invalid data length. pos = " << ss->pos << ", len = " << ss->len << ", requested size to read = " << size << "\n";
@ -1830,6 +1831,9 @@ static size_t tinyktxCallbackRead(void *user, void* data, size_t size) {
memcpy(data, ss->data + ss->pos, size); memcpy(data, ss->data + ss->pos, size);
// Advance pos
ss->pos += size;
return size; return size;
}; };
@ -1871,7 +1875,7 @@ bool LoadImageDataKTX(Image *image, const int image_idx, std::string *err,
&tinyktxCallbackError, &tinyktxCallbackError,
&tinyktxCallbackAlloc, &tinyktxCallbackAlloc,
&tinyktxCallbackFree, &tinyktxCallbackFree,
tinyktxCallbackRead, &tinyktxCallbackRead,
&tinyktxCallbackSeek, &tinyktxCallbackSeek,
&tinyktxCallbackTell &tinyktxCallbackTell
}; };
@ -1920,6 +1924,12 @@ bool LoadImageDataKTX(Image *image, const int image_idx, std::string *err,
return false; return false;
} }
const void *src_ptr = TinyKtx_ImageRawData(ctx, miplevel);
if (src_ptr == nullptr) {
TinyKtx_DestroyContext(ctx);
return false;
}
image->image.resize(byte_count); image->image.resize(byte_count);
memcpy(image->image.data(), TinyKtx_ImageRawData(ctx, miplevel), byte_count); memcpy(image->image.data(), TinyKtx_ImageRawData(ctx, miplevel), byte_count);
@ -1952,34 +1962,49 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
bool ret = false; bool ret = false;
std::string stb_err;
std::string stb_warn;
#if !defined(TINYGLTF_NO_STB_IMAGE)
// Try to load images using stb_image(png, gif, bmp, tga, ...)
ret = tinygltf::LoadImageDataSTB(image, image_idx, &stb_err, &stb_warn, req_width, req_height,
bytes, size, user_data);
if (ret) {
return true;
}
#endif
std::string ktx_err;
std::string ktx_warn;
#if defined(TINYGLTF_ENABLE_KTX) #if defined(TINYGLTF_ENABLE_KTX)
// Try KTX image // Try KTX image
ret = tinygltf::LoadImageDataKTX(image, image_idx, err, warn, req_width, req_height, ret = tinygltf::LoadImageDataKTX(image, image_idx, &ktx_err, &ktx_warn, req_width, req_height,
bytes, size, user_data); bytes, size, user_data);
if (ret) { if (ret) {
if (warn) {
(*warn) = ktx_warn;
}
return true; return true;
} }
#endif #endif
#if defined(TINYGLTF_NO_STB_IMAGE) if (err) {
// Try to load images using stb_image(png, gif, bmp, tga, ...) (*err) = stb_err + ktx_err;
ret = tinygltf::LoadImageDataSTB(image, image_idx, err, warn, req_width, req_height,
bytes, size, user_data);
if (ret) {
return true;
} }
#endif if (warn) {
(*warn) = stb_warn + ktx_warn;
}
(void)image; (void)image;
(void)image_idx; (void)image_idx;
(void)err;
(void)warn;
(void)req_width; (void)req_width;
(void)req_height; (void)req_height;
(void)bytes; (void)bytes;