diff --git a/kraken/resources/KRResource+gltf.cpp b/kraken/resources/KRResource+gltf.cpp index b4030ef..d25e425 100644 --- a/kraken/resources/KRResource+gltf.cpp +++ b/kraken/resources/KRResource+gltf.cpp @@ -114,6 +114,99 @@ KRBundle* LoadGltf(KRContext& context, simdjson::ondemand::object& jsonRoot, std } } + struct SamplerInfo + { + KRMaterial::texture_wrap_type wrapS = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_REPEAT; + KRMaterial::texture_wrap_type wrapT = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_REPEAT; + KRMaterial::texture_mag_filter_type magFilter = KRMaterial::texture_mag_filter_type::KRMATERIAL_TEXTURE_MAG_LINEAR; + KRMaterial::texture_min_filter_type minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR; + }; + std::vector samplers; + simdjson::ondemand::array jsonSamplers; + if(tryJson(jsonRoot["samplers"].get_array().get(jsonSamplers))) { + for (auto jsonSampler : jsonSamplers) { + SamplerInfo& sampler = samplers.emplace_back(); + int jsonWrapS = 10497; // REPEAT + int jsonWrapT = 10497; // REPEAT + int jsonMinFilter = 9987; // LINEAR_MIPMAP_LINEAR + int jsonMagFilter = 9729; // LINEAR + tryJson(jsonSampler["wrapS"].get(jsonWrapS)); + tryJson(jsonSampler["wrapT"].get(jsonWrapT)); + tryJson(jsonSampler["minFilter"].get(jsonMinFilter)); + tryJson(jsonSampler["magFilter"].get(jsonMagFilter)); + + switch(jsonWrapS) + { + case 33071: // CLAMP_TO_EDGE + sampler.wrapS = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_CLAMP; + break; + case 10497: // REPEAT + sampler.wrapS = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_REPEAT; + break; + case 33648: // MIRRORED_REPEAT + sampler.wrapS = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_MIRROR_REPEAT; + break; + default: + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - GLTF: Sampler with unknown sampler wrap: %i", jsonWrapS); + break; + } + + switch(jsonWrapT) + { + case 33071: // CLAMP_TO_EDGE + sampler.wrapT = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_CLAMP; + break; + case 10497: // REPEAT + sampler.wrapT = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_REPEAT; + break; + case 33648: // MIRRORED_REPEAT + sampler.wrapT = KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_MIRROR_REPEAT; + break; + default: + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - GLTF: Sampler with unknown sampler wrap: %i", jsonWrapT); + break; + } + + switch(jsonMinFilter) + { + case 9728: // NEAREST + sampler.minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_NEAREST; + break; + case 9729: // LINEAR + sampler.minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR; + break; + case 9984: // NEAREST_MIPMAP_NEAREST + sampler.minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_NEAREST; + break; + case 9985: // LINEAR_MIPMAP_NEAREST + sampler.minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_NEAREST; + break; + case 9986: // NEAREST_MIPMAP_LINEAR + sampler.minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_LINEAR; + break; + case 9987: // LINEAR_MIPMAP_LINEAR + sampler.minFilter = KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR; + break; + default: + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - GLTF: Sampler with unknown minFilter: %i", jsonMinFilter); + break; + } + + switch(jsonMagFilter) + { + case 9728: // NEAREST + sampler.magFilter = KRMaterial::texture_mag_filter_type::KRMATERIAL_TEXTURE_MAG_NEAREST; + break; + case 9729: // LINEAR + sampler.magFilter = KRMaterial::texture_mag_filter_type::KRMATERIAL_TEXTURE_MAG_LINEAR; + break; + default: + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - GLTF: Sampler with unknown magFilter: %i", jsonMagFilter); + break; + } + } + } + struct TextureInfo { std::string name; @@ -122,6 +215,8 @@ KRBundle* LoadGltf(KRContext& context, simdjson::ondemand::object& jsonRoot, std hydra::Vector2 scale{ 1.f, 1.f }; hydra::Vector2 offset{ 0.f, 0.f }; float rotation{ 0.f }; + + SamplerInfo sampler; }; std::vector textures; simdjson::ondemand::array jsonTextures; @@ -142,7 +237,11 @@ KRBundle* LoadGltf(KRContext& context, simdjson::ondemand::object& jsonRoot, std int samplerIndex = -1; if (tryJson(jsonTexture["sampler"].get(samplerIndex))) { KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Kraken - GLTF: Sampler options not supported for texture: %s", texture.name.c_str()); - // TODO - Implement texture sampler options + if (samplerIndex < 0 || samplerIndex >= samplers.size()) { + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - GLTF: Could not load texture with a sampler index that is out of range: %s", texture.name.c_str()); + continue; + } + texture.sampler = samplers[samplerIndex]; } int imageIndex = -1; if (!tryJson(jsonTexture["source"].get(imageIndex))) { @@ -166,9 +265,6 @@ KRBundle* LoadGltf(KRContext& context, simdjson::ondemand::object& jsonRoot, std textureIndex++; } } - - simdjson::ondemand::array samplers; - tryJson(jsonRoot["samplers"].get_array().get(samplers)); KRBundle* bundle = new KRBundle(context, baseName); @@ -204,6 +300,10 @@ KRBundle* LoadGltf(KRContext& context, simdjson::ondemand::object& jsonRoot, std textureMap.scale = texture.scale; textureMap.offset = texture.offset; textureMap.rotation = texture.rotation; + textureMap.wrapS = texture.sampler.wrapS; + textureMap.wrapT = texture.sampler.wrapT; + textureMap.minFilter = texture.sampler.minFilter; + textureMap.magFilter = texture.sampler.magFilter; textureMap.texture.set(texture.texture); } } diff --git a/kraken/resources/material/KRMaterial.cpp b/kraken/resources/material/KRMaterial.cpp index cf8f64d..874ac5f 100755 --- a/kraken/resources/material/KRMaterial.cpp +++ b/kraken/resources/material/KRMaterial.cpp @@ -55,6 +55,60 @@ void tag_invoke(serialize_tag, builder_type& builder, const KRMaterial::TextureM builder.template append_key_value<"scale">(texture.scale); builder.append_comma(); builder.template append_key_value<"rotation">(texture.rotation); + builder.append_comma(); + switch(texture.wrapS) { + case KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_CLAMP: + builder.template append_key_value<"wrapS">("clamp"); + break; + case KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_REPEAT: + builder.template append_key_value<"wrapS">("repeat"); + break; + case KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_MIRROR_REPEAT: + builder.template append_key_value<"wrapS">("repeat_mirror"); + break; + } + builder.append_comma(); + switch(texture.wrapT) { + case KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_CLAMP: + builder.template append_key_value<"wrapT">("clamp"); + break; + case KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_REPEAT: + builder.template append_key_value<"wrapT">("repeat"); + break; + case KRMaterial::texture_wrap_type::KRMATERIAL_TEXTURE_MIRROR_REPEAT: + builder.template append_key_value<"wrapT">("repeat_mirror"); + break; + } + builder.append_comma(); + switch(texture.magFilter) { + case KRMaterial::texture_mag_filter_type::KRMATERIAL_TEXTURE_MAG_NEAREST: + builder.template append_key_value<"magFilter">("nearest"); + break; + case KRMaterial::texture_mag_filter_type::KRMATERIAL_TEXTURE_MAG_LINEAR: + builder.template append_key_value<"magFilter">("linear"); + break; + } + builder.append_comma(); + switch(texture.minFilter) { + case KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_NEAREST: + builder.template append_key_value<"minFilter">("nearest"); + break; + case KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR: + builder.template append_key_value<"minFilter">("linear"); + break; + case KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_NEAREST: + builder.template append_key_value<"minFilter">("nearest_mipmap_nearest"); + break; + case KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_NEAREST: + builder.template append_key_value<"minFilter">("linear_mipmap_nearest"); + break; + case KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_LINEAR: + builder.template append_key_value<"minFilter">("nearest_mipmap_linear"); + break; + case KRMaterial::texture_min_filter_type::KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR: + builder.template append_key_value<"minFilter">("linear_mipmap_linear"); + break; + } builder.end_object(); } @@ -86,6 +140,75 @@ simdjson::error_code KRMaterial::TextureMap::parse(simdjson::ondemand::value &va return error; } + std::string strWrapS; + std::string strWrapT; + std::string strMinFilter; + std::string strMagFilter; + + if ((error = obj["wrapS"].get(strWrapS))) { + return error; + } + + if (strWrapS == "clamp") { + wrapS = KRMATERIAL_TEXTURE_CLAMP; + } else if(strWrapS == "repeat") { + wrapS = KRMATERIAL_TEXTURE_REPEAT; + } else if(strWrapS == "repeat_mirror") { + wrapS = KRMATERIAL_TEXTURE_MIRROR_REPEAT; + } else { + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Unknown material texture wrap: %s.", strWrapS.c_str()); + wrapS = KRMATERIAL_TEXTURE_REPEAT; + } + + if ((error = obj["wrapT"].get(strWrapT))) { + return error; + } + + if (strWrapT == "clamp") { + wrapT = KRMATERIAL_TEXTURE_CLAMP; + } else if(strWrapT == "repeat") { + wrapT = KRMATERIAL_TEXTURE_REPEAT; + } else if(strWrapT == "repeat_mirror") { + wrapT = KRMATERIAL_TEXTURE_MIRROR_REPEAT; + } else { + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Unknown material texture wrap: %s.", strWrapT.c_str()); + wrapS = KRMATERIAL_TEXTURE_REPEAT; + } + + if ((error = obj["minFilter"].get(strMinFilter))) { + return error; + } + + if (strMinFilter == "nearest") { + minFilter = KRMATERIAL_TEXTURE_MIN_NEAREST; + } else if (strMinFilter =="linear") { + minFilter = KRMATERIAL_TEXTURE_MIN_LINEAR; + } else if (strMinFilter == "nearest_mipmap_nearest") { + minFilter = KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_NEAREST; + } else if (strMinFilter == "linear_mipmap_nearest") { + minFilter = KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_NEAREST; + } else if (strMinFilter == "nearest_mipmap_linear") { + minFilter = KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_LINEAR; + } else if (strMinFilter == "linear_mipmap_linear") { + minFilter = KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR; + } else { + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Unknown material texture min filter: %s.", strMinFilter.c_str()); + minFilter = KRMATERIAL_TEXTURE_MIN_LINEAR; + } + + if ((error = obj["magFilter"].get(strMagFilter))) { + return error; + } + + if (strMagFilter == "nearest") { + magFilter = KRMATERIAL_TEXTURE_MAG_NEAREST; + } else if (strMagFilter == "linear") { + magFilter = KRMATERIAL_TEXTURE_MAG_LINEAR; + } else { + KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Unknown material texture mag filter: %s.", strMagFilter.c_str()); + magFilter = KRMATERIAL_TEXTURE_MAG_LINEAR; + } + return simdjson::SUCCESS; } diff --git a/kraken/resources/material/KRMaterial.h b/kraken/resources/material/KRMaterial.h index 3eeaa92..e4bd9aa 100755 --- a/kraken/resources/material/KRMaterial.h +++ b/kraken/resources/material/KRMaterial.h @@ -69,6 +69,29 @@ public: KRMATERIAL_SHADING_MODEL_UNLIT, KRMATERIAL_SHADING_MODEL_PBR } shading_model_type; + + typedef enum + { + KRMATERIAL_TEXTURE_CLAMP, + KRMATERIAL_TEXTURE_REPEAT, + KRMATERIAL_TEXTURE_MIRROR_REPEAT + } texture_wrap_type; + + typedef enum + { + KRMATERIAL_TEXTURE_MAG_NEAREST, + KRMATERIAL_TEXTURE_MAG_LINEAR + } texture_mag_filter_type; + + typedef enum + { + KRMATERIAL_TEXTURE_MIN_NEAREST, + KRMATERIAL_TEXTURE_MIN_LINEAR, + KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_NEAREST, + KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_NEAREST, + KRMATERIAL_TEXTURE_MIN_NEAREST_MIPMAP_LINEAR, + KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR + } texture_min_filter_type; struct TextureMap { @@ -77,6 +100,11 @@ public: hydra::Vector2 scale{ 1.f, 1.f }; hydra::Vector2 offset{ 0.f, 0.f }; float rotation{ 0.f }; + + texture_wrap_type wrapS = KRMATERIAL_TEXTURE_REPEAT; + texture_wrap_type wrapT = KRMATERIAL_TEXTURE_REPEAT; + texture_mag_filter_type magFilter = KRMATERIAL_TEXTURE_MAG_LINEAR; + texture_min_filter_type minFilter = KRMATERIAL_TEXTURE_MIN_LINEAR_MIPMAP_LINEAR; TextureMap(KRTexture::texture_usage_t usage) : texture{ usage }