Skip to content

Commit

Permalink
Implement support for KHR_materials_iridescence
Browse files Browse the repository at this point in the history
PR: KhronosGroup/glTF#2027

Note: the extension hasn't been merged to glTF yet but all the spec
corrections wrt schema have been made so the schema shouldn't change at
this point.
  • Loading branch information
zeux committed Apr 23, 2022
1 parent beac380 commit b6eb607
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 1 deletion.
86 changes: 86 additions & 0 deletions cgltf.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,16 @@ typedef struct cgltf_emissive_strength
cgltf_float emissive_strength;
} cgltf_emissive_strength;

typedef struct cgltf_iridescence
{
cgltf_float iridescence_factor;
cgltf_texture_view iridescence_texture;
cgltf_float iridescence_ior;
cgltf_float iridescence_thickness_min;
cgltf_float iridescence_thickness_max;
cgltf_texture_view iridescence_thickness_texture;
} cgltf_iridescence;

typedef struct cgltf_material
{
char* name;
Expand All @@ -491,6 +501,7 @@ typedef struct cgltf_material
cgltf_bool has_specular;
cgltf_bool has_sheen;
cgltf_bool has_emissive_strength;
cgltf_bool has_iridescence;
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
cgltf_pbr_specular_glossiness pbr_specular_glossiness;
cgltf_clearcoat clearcoat;
Expand All @@ -500,6 +511,7 @@ typedef struct cgltf_material
cgltf_transmission transmission;
cgltf_volume volume;
cgltf_emissive_strength emissive_strength;
cgltf_iridescence iridescence;
cgltf_texture_view normal_texture;
cgltf_texture_view occlusion_texture;
cgltf_texture_view emissive_texture;
Expand Down Expand Up @@ -1874,6 +1886,11 @@ void cgltf_free(cgltf_data* data)
cgltf_free_extensions(data, data->materials[i].sheen.sheen_color_texture.extensions, data->materials[i].sheen.sheen_color_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].sheen.sheen_roughness_texture.extensions, data->materials[i].sheen.sheen_roughness_texture.extensions_count);
}
if(data->materials[i].has_iridescence)
{
cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_texture.extensions, data->materials[i].iridescence.iridescence_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].iridescence.iridescence_thickness_texture.extensions, data->materials[i].iridescence.iridescence_thickness_texture.extensions_count);
}

cgltf_free_extensions(data, data->materials[i].normal_texture.extensions, data->materials[i].normal_texture.extensions_count);
cgltf_free_extensions(data, data->materials[i].occlusion_texture.extensions, data->materials[i].occlusion_texture.extensions_count);
Expand Down Expand Up @@ -3923,6 +3940,67 @@ static int cgltf_parse_json_emissive_strength(jsmntok_t const* tokens, int i, co
return i;
}

static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_iridescence* out_iridescence)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
int size = tokens[i].size;
++i;

// Default
out_iridescence->iridescence_ior = 1.3f;
out_iridescence->iridescence_thickness_min = 100.f;
out_iridescence->iridescence_thickness_max = 400.f;

for (int j = 0; j < size; ++j)
{
CGLTF_CHECK_KEY(tokens[i]);

if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceFactor") == 0)
{
++i;
out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceTexture") == 0)
{
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceIor") == 0)
{
++i;
out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMinimum") == 0)
{
++i;
out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMaximum") == 0)
{
++i;
out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessTexture") == 0)
{
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_texture);
}
else
{
i = cgltf_skip_json(tokens, i + 1);
}

if (i < 0)
{
return i;
}
}

return i;
}

static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
Expand Down Expand Up @@ -4306,6 +4384,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
out_material->has_emissive_strength = 1;
i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_iridescence") == 0)
{
out_material->has_iridescence = 1;
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
}
else
{
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
Expand Down Expand Up @@ -6157,6 +6240,9 @@ static int cgltf_fixup_pointers(cgltf_data* data)

CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);

CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
}

for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
Expand Down
23 changes: 22 additions & 1 deletion cgltf_write.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si
#define CGLTF_EXTENSION_FLAG_TEXTURE_BASISU (1 << 12)
#define CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH (1 << 13)
#define CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING (1 << 14)
#define CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE (1 << 15)

typedef struct {
char* buffer;
Expand Down Expand Up @@ -595,6 +596,11 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH;
}

if (material->has_iridescence)
{
context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE;
}

if (material->has_pbr_metallic_roughness)
{
const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness;
Expand All @@ -611,7 +617,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_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength)
if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence)
{
cgltf_write_line(context, "\"extensions\": {");
if (material->has_clearcoat)
Expand Down Expand Up @@ -710,6 +716,18 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
cgltf_write_floatprop(context, "emissiveStrength", params->emissive_strength, 1.f);
cgltf_write_line(context, "}");
}
if (material->has_iridescence)
{
cgltf_write_line(context, "\"KHR_materials_iridescence\": {");
const cgltf_iridescence* params = &material->iridescence;
cgltf_write_floatprop(context, "iridescenceFactor", params->iridescence_factor, 0.f);
CGLTF_WRITE_TEXTURE_INFO("iridescenceTexture", params->iridescence_texture);
cgltf_write_floatprop(context, "iridescenceIor", params->iridescence_ior, 1.3f);
cgltf_write_floatprop(context, "iridescenceThicknessMinimum", params->iridescence_thickness_min, 100.f);
cgltf_write_floatprop(context, "iridescenceThicknessMaximum", params->iridescence_thickness_max, 400.f);
CGLTF_WRITE_TEXTURE_INFO("iridescenceThicknessTexture", params->iridescence_thickness_texture);
cgltf_write_line(context, "}");
}
cgltf_write_line(context, "}");
}

Expand Down Expand Up @@ -1141,6 +1159,9 @@ static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extens
if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH) {
cgltf_write_stritem(context, "KHR_materials_emissive_strength");
}
if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE) {
cgltf_write_stritem(context, "KHR_materials_iridescence");
}
if (extension_flags & CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING) {
cgltf_write_stritem(context, "EXT_mesh_gpu_instancing");
}
Expand Down

0 comments on commit b6eb607

Please sign in to comment.