|
|
@ -3377,9 +3377,9 @@ static unsigned char *DecodeBase64(char *input, int *size) |
|
|
|
} |
|
|
|
|
|
|
|
// Load texture from cgltf_image |
|
|
|
static Texture LoadTextureFromCgltfImage(cgltf_image *image, const char *texPath, Color tint) |
|
|
|
static Image LoadImageFromCgltfImage(cgltf_image *image, const char *texPath, Color tint) |
|
|
|
{ |
|
|
|
Texture texture = { 0 }; |
|
|
|
Image rimage = { 0 }; |
|
|
|
|
|
|
|
if (image->uri) |
|
|
|
{ |
|
|
@ -3406,22 +3406,18 @@ static Texture LoadTextureFromCgltfImage(cgltf_image *image, const char *texPath |
|
|
|
int w, h; |
|
|
|
unsigned char *raw = stbi_load_from_memory(data, size, &w, &h, NULL, 4); |
|
|
|
|
|
|
|
Image rimage = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); |
|
|
|
rimage = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); |
|
|
|
|
|
|
|
// TODO: Tint shouldn't be applied here! |
|
|
|
ImageColorTint(&rimage, tint); |
|
|
|
texture = LoadTextureFromImage(rimage); |
|
|
|
UnloadImage(rimage); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Image rimage = LoadImage(TextFormat("%s/%s", texPath, image->uri)); |
|
|
|
rimage = LoadImage(TextFormat("%s/%s", texPath, image->uri)); |
|
|
|
|
|
|
|
// TODO: Tint shouldn't be applied here! |
|
|
|
ImageColorTint(&rimage, tint); |
|
|
|
texture = LoadTextureFromImage(rimage); |
|
|
|
UnloadImage(rimage); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (image->buffer_view) |
|
|
@ -3440,41 +3436,36 @@ static Texture LoadTextureFromCgltfImage(cgltf_image *image, const char *texPath |
|
|
|
unsigned char *raw = stbi_load_from_memory(data, image->buffer_view->size, &w, &h, NULL, 4); |
|
|
|
free(data); |
|
|
|
|
|
|
|
Image rimage = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); |
|
|
|
rimage = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); |
|
|
|
free(raw); |
|
|
|
|
|
|
|
// TODO: Tint shouldn't be applied here! |
|
|
|
ImageColorTint(&rimage, tint); |
|
|
|
texture = LoadTextureFromImage(rimage); |
|
|
|
UnloadImage(rimage); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Image rimage = LoadImageEx(&tint, 1, 1); |
|
|
|
texture = LoadTextureFromImage(rimage); |
|
|
|
UnloadImage(rimage); |
|
|
|
rimage = LoadImageEx(&tint, 1, 1); |
|
|
|
} |
|
|
|
|
|
|
|
return texture; |
|
|
|
return rimage; |
|
|
|
} |
|
|
|
|
|
|
|
// Load glTF mesh data |
|
|
|
// LoadGLTF loads in model data from given filename, supporting both .gltf and .glb |
|
|
|
static Model LoadGLTF(const char *fileName) |
|
|
|
{ |
|
|
|
/*********************************************************************************** |
|
|
|
|
|
|
|
Function implemented by Wilhem Barbier (@wbrbr) |
|
|
|
Function implemented by Wilhem Barbier(@wbrbr), with modifications by Tyler Bezera(@gamerfiend) |
|
|
|
|
|
|
|
Features: |
|
|
|
- Supports .gltf and .glb files |
|
|
|
- Supports embedded (base64) or external textures |
|
|
|
- Loads the albedo/diffuse texture (other maps could be added) |
|
|
|
- Loads all raylib supported material textures, values and colors |
|
|
|
- Supports multiple mesh per model and multiple primitives per model |
|
|
|
|
|
|
|
Some restrictions (not exhaustive): |
|
|
|
- Triangle-only meshes |
|
|
|
- Not supported node hierarchies or transforms |
|
|
|
- Only loads the diffuse texture... but not too hard to support other maps (normal, roughness/metalness...) |
|
|
|
- Only supports unsigned short indices (no byte/unsigned int) |
|
|
|
- Only supports float for texture coordinates (no byte/unsigned short) |
|
|
|
|
|
|
@ -3547,44 +3538,62 @@ static Model LoadGLTF(const char *fileName) |
|
|
|
//Ensure material follows raylib support for PBR (metallic/roughness flow) |
|
|
|
if (data->materials[i].has_pbr_metallic_roughness) |
|
|
|
{ |
|
|
|
float roughness = data->materials[i].pbr_metallic_roughness.roughness_factor; |
|
|
|
float metallic = data->materials[i].pbr_metallic_roughness.metallic_factor; |
|
|
|
tint.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0] * 255); |
|
|
|
tint.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1] * 255); |
|
|
|
tint.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2] * 255); |
|
|
|
tint.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3] * 255); |
|
|
|
|
|
|
|
// NOTE: Material name not used for the moment |
|
|
|
//if (model.materials[i].name && data->materials[i].name) strcpy(model.materials[i].name, data->materials[i].name); |
|
|
|
|
|
|
|
// TODO: REview: shouldn't these be *255 ??? |
|
|
|
tint.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255); |
|
|
|
tint.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255); |
|
|
|
tint.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2]*255); |
|
|
|
tint.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3]*255); |
|
|
|
|
|
|
|
model.materials[i].maps[MAP_ROUGHNESS].color = tint; |
|
|
|
model.materials[i].maps[MAP_ALBEDO].color = tint; |
|
|
|
|
|
|
|
if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture) |
|
|
|
{ |
|
|
|
model.materials[i].maps[MAP_ALBEDO].texture = LoadTextureFromCgltfImage(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, texPath, tint); |
|
|
|
Image albedo = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, texPath, tint); |
|
|
|
model.materials[i].maps[MAP_ALBEDO].texture = LoadTextureFromImage(albedo); |
|
|
|
UnloadImage(albedo); |
|
|
|
} |
|
|
|
|
|
|
|
// NOTE: Tint isn't need for other textures.. pass null or clear? |
|
|
|
// Just set as white, multiplying by white has no effect |
|
|
|
//Set tint to white after it's been used by Albedo |
|
|
|
tint = WHITE; |
|
|
|
|
|
|
|
if (data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture) |
|
|
|
{ |
|
|
|
model.materials[i].maps[MAP_ROUGHNESS].texture = LoadTextureFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath, tint); |
|
|
|
Image metallicRoughness = LoadImageFromCgltfImage(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, texPath, tint); |
|
|
|
model.materials[i].maps[MAP_ROUGHNESS].texture = LoadTextureFromImage(metallicRoughness); |
|
|
|
|
|
|
|
float roughness = data->materials[i].pbr_metallic_roughness.roughness_factor; |
|
|
|
model.materials[i].maps[MAP_ROUGHNESS].value = roughness; |
|
|
|
|
|
|
|
float metallic = data->materials[i].pbr_metallic_roughness.metallic_factor; |
|
|
|
model.materials[i].maps[MAP_METALNESS].value = metallic; |
|
|
|
|
|
|
|
UnloadImage(metallicRoughness); |
|
|
|
} |
|
|
|
model.materials[i].maps[MAP_ROUGHNESS].value = roughness; |
|
|
|
model.materials[i].maps[MAP_METALNESS].value = metallic; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (data->materials[i].normal_texture.texture) |
|
|
|
{ |
|
|
|
model.materials[i].maps[MAP_NORMAL].texture = LoadTextureFromCgltfImage(data->materials[i].normal_texture.texture->image, texPath, tint); |
|
|
|
Image normalImage = LoadImageFromCgltfImage(data->materials[i].normal_texture.texture->image, texPath, tint); |
|
|
|
model.materials[i].maps[MAP_NORMAL].texture = LoadTextureFromImage(normalImage); |
|
|
|
UnloadImage(normalImage); |
|
|
|
} |
|
|
|
|
|
|
|
if (data->materials[i].occlusion_texture.texture) |
|
|
|
{ |
|
|
|
model.materials[i].maps[MAP_OCCLUSION].texture = LoadTextureFromCgltfImage(data->materials[i].occlusion_texture.texture->image, texPath, tint); |
|
|
|
Image occulsionImage = LoadImageFromCgltfImage(data->materials[i].occlusion_texture.texture->image, texPath, tint); |
|
|
|
model.materials[i].maps[MAP_OCCLUSION].texture = LoadTextureFromImage(occulsionImage); |
|
|
|
UnloadImage(occulsionImage); |
|
|
|
} |
|
|
|
|
|
|
|
if (data->materials[i].emissive_texture.texture) |
|
|
|
{ |
|
|
|
Image emissiveImage = LoadImageFromCgltfImage(data->materials[i].emissive_texture.texture->image, texPath, tint); |
|
|
|
model.materials[i].maps[MAP_EMISSION].texture = LoadTextureFromImage(emissiveImage); |
|
|
|
tint.r = (unsigned char)(data->materials[i].emissive_factor[0] * 255); |
|
|
|
tint.g = (unsigned char)(data->materials[i].emissive_factor[1] * 255); |
|
|
|
tint.b = (unsigned char)(data->materials[i].emissive_factor[2] * 255); |
|
|
|
model.materials[i].maps[MAP_EMISSION].color = tint; |
|
|
|
UnloadImage(emissiveImage); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|