From 2bf0b3558fa8cde5f5fc789a36399c0cb5024899 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 25 Aug 2020 09:53:03 -0700 Subject: [PATCH] Add support for KHR_materials_specular --- README.md | 1 + cgltf.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ cgltf_write.h | 25 ++++++++++++++++++-- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1b61472..3b49d52 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ cgltf also supports some glTF extensions: - KHR_materials_clearcoat - KHR_materials_ior - KHR_materials_pbrSpecularGlossiness +- KHR_materials_specular - KHR_materials_transmission - KHR_materials_unlit - KHR_texture_transform diff --git a/cgltf.h b/cgltf.h index ec1c555..077cf36 100644 --- a/cgltf.h +++ b/cgltf.h @@ -408,6 +408,13 @@ typedef struct cgltf_ior cgltf_float ior; } cgltf_ior; +typedef struct cgltf_specular +{ + cgltf_texture_view specular_texture; + cgltf_float specular_color_factor[3]; + cgltf_float specular_factor; +} cgltf_specular; + typedef struct cgltf_material { char* name; @@ -416,10 +423,12 @@ typedef struct cgltf_material cgltf_bool has_clearcoat; cgltf_bool has_transmission; cgltf_bool has_ior; + cgltf_bool has_specular; cgltf_pbr_metallic_roughness pbr_metallic_roughness; cgltf_pbr_specular_glossiness pbr_specular_glossiness; cgltf_clearcoat clearcoat; cgltf_ior ior; + cgltf_specular specular; cgltf_transmission transmission; cgltf_texture_view normal_texture; cgltf_texture_view occlusion_texture; @@ -1661,6 +1670,10 @@ void cgltf_free(cgltf_data* data) cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions, data->materials[i].clearcoat.clearcoat_roughness_texture.extensions_count); cgltf_free_extensions(data, data->materials[i].clearcoat.clearcoat_normal_texture.extensions, data->materials[i].clearcoat.clearcoat_normal_texture.extensions_count); } + if(data->materials[i].has_specular) + { + cgltf_free_extensions(data, data->materials[i].specular.specular_texture.extensions, data->materials[i].specular.specular_texture.extensions_count); + } if(data->materials[i].has_transmission) { cgltf_free_extensions(data, data->materials[i].transmission.transmission_texture.extensions, data->materials[i].transmission.transmission_texture.extensions_count); @@ -3288,6 +3301,9 @@ static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* j int size = tokens[i].size; ++i; + // Default values + out_ior->ior = 1.5f; + for (int j = 0; j < size; ++j) { CGLTF_CHECK_KEY(tokens[i]); @@ -3312,6 +3328,48 @@ static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* j return i; } +static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + int size = tokens[i].size; + ++i; + + // Default values + out_specular->specular_factor = 1.0f; + cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f); + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0) + { + ++i; + out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0) + { + i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3); + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0) + { + i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture); + } + else + { + i = cgltf_skip_json(tokens, i+1); + } + + if (i < 0) + { + return i; + } + } + + return i; +} + static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -3638,6 +3696,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to out_material->has_ior = 1; i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior); } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0) + { + out_material->has_specular = 1; + i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular); + } else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0) { out_material->has_transmission = 1; @@ -5242,6 +5305,8 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count); CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count); } diff --git a/cgltf_write.h b/cgltf_write.h index cc4f8a2..2096a5b 100644 --- a/cgltf_write.h +++ b/cgltf_write.h @@ -76,7 +76,8 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si #define CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION (1 << 4) #define CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT (1 << 5) #define CGLTF_EXTENSION_FLAG_MATERIALS_IOR (1 << 6) -#define CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION (1 << 7) +#define CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR (1 << 7) +#define CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION (1 << 8) typedef struct { char* buffer; @@ -514,6 +515,11 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IOR; } + if (material->has_specular) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR; + } + if (material->has_pbr_metallic_roughness) { const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness; @@ -530,7 +536,7 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater cgltf_write_line(context, "}"); } - if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_transmission) + if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission) { cgltf_write_line(context, "\"extensions\": {"); if (material->has_clearcoat) @@ -551,6 +557,18 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater cgltf_write_floatprop(context, "ior", params->ior, 1.5f); cgltf_write_line(context, "}"); } + if (material->has_specular) + { + const cgltf_specular* params = &material->specular; + cgltf_write_line(context, "\"KHR_materials_specular\": {"); + CGLTF_WRITE_TEXTURE_INFO("specularTexture", params->specular_texture); + cgltf_write_floatprop(context, "specularFactor", params->specular_factor, 1.0f); + if (cgltf_check_floatarray(params->specular_color_factor, 3, 1.0f)) + { + cgltf_write_floatarrayprop(context, "specularColorFactor", params->specular_color_factor, 3); + } + cgltf_write_line(context, "}"); + } if (material->has_transmission) { const cgltf_transmission* params = &material->transmission; @@ -930,6 +948,9 @@ static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extens if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IOR) { cgltf_write_stritem(context, "KHR_materials_ior"); } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR) { + cgltf_write_stritem(context, "KHR_materials_specular"); + } if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION) { cgltf_write_stritem(context, "KHR_materials_transmission"); }