mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-09-23 18:23:16 +08:00
Support KTX texture of R8G8B8 format in basic
example.
This commit is contained in:
parent
006ab90c67
commit
c7bf800075
@ -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,7 +157,24 @@ 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;
|
||||||
|
GLenum type = GL_UNSIGNED_BYTE;
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
|
||||||
if (image.component == 1) {
|
if (image.component == 1) {
|
||||||
format = GL_RED;
|
format = GL_RED;
|
||||||
@ -138,22 +182,28 @@ std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
|
|||||||
format = GL_RG;
|
format = GL_RG;
|
||||||
} else if (image.component == 3) {
|
} else if (image.component == 3) {
|
||||||
format = GL_RGB;
|
format = GL_RGB;
|
||||||
|
} else if (image.component == 4) {
|
||||||
|
format = GL_RGBA;
|
||||||
} else {
|
} else {
|
||||||
// ???
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum type = GL_UNSIGNED_BYTE;
|
|
||||||
if (image.bits == 8) {
|
if (image.bits == 8) {
|
||||||
// ok
|
// ok
|
||||||
} else if (image.bits == 16) {
|
} else if (image.bits == 16) {
|
||||||
type = GL_UNSIGNED_SHORT;
|
type = GL_UNSIGNED_SHORT;
|
||||||
} else {
|
} else {
|
||||||
// ???
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0,
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image.width, image.height, 0,
|
||||||
format, type, &image.image.at(0));
|
format, type, &image.image.at(0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return vbos;
|
return vbos;
|
||||||
}
|
}
|
||||||
|
BIN
models/Cube-KTX/Cube.bin
Normal file
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
193
models/Cube-KTX/Cube.gltf
Normal 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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
models/Cube-KTX/Cube_BaseColor.ktx
Normal file
BIN
models/Cube-KTX/Cube_BaseColor.ktx
Normal file
Binary file not shown.
BIN
models/Cube-KTX/Cube_MetallicRoughness.ktx
Normal file
BIN
models/Cube-KTX/Cube_MetallicRoughness.ktx
Normal file
Binary file not shown.
12
models/Cube-KTX/README.md
Normal file
12
models/Cube-KTX/README.md
Normal 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
|
||||||
|
|
53
tiny_gltf.h
53
tiny_gltf.h
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user