diff --git a/src/models.c b/src/models.c index 2462190d..774d426f 100644 --- a/src/models.c +++ b/src/models.c @@ -2385,8 +2385,15 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota for (int i = 0; i < model.meshCount; i++) { - model.materials[model.meshMaterial[i]].maps[MAP_DIFFUSE].color = tint; + Color c = model.materials[model.meshMaterial[i]].maps[MAP_DIFFUSE].color; + Color s = c; + c.r = ((c.r/255) * (tint.r/255)) * 255; + c.g = ((c.g/255) * (tint.g/255)) * 255; + c.b = ((c.b/255) * (tint.b/255)) * 255; + c.a = ((c.a/255) * (tint.a/255)) * 255; + model.materials[model.meshMaterial[i]].maps[MAP_DIFFUSE].color = c; rlDrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform); + model.materials[model.meshMaterial[i]].maps[MAP_DIFFUSE].color = s; } } @@ -3344,6 +3351,92 @@ static unsigned char *DecodeBase64(char *input, int *size) return buf; } +//static Texture LoadTextureFromCGLTFTextureView(cgltf_texture_view* view, Color tint, char* texPath) +static Texture LoadTextureFromCGLTFTextureView(cgltf_image* image, Color tint, const char* texPath) +{ + Texture texture = {0}; + //cgltf_image *image = view->texture->image; + + if (image->uri) + { + if ((strlen(image->uri) > 5) && + (image->uri[0] == 'd') && + (image->uri[1] == 'a') && + (image->uri[2] == 't') && + (image->uri[3] == 'a') && + (image->uri[4] == ':')) + { + // Data URI + // Format: data:;base64, + + // Find the comma + int i = 0; + while ((image->uri[i] != ',') && (image->uri[i] != 0)) + i++; + + if (image->uri[i] == 0) + TraceLog(LOG_WARNING, "Invalid data URI"); + else + { + int size; + unsigned char *data = DecodeBase64(image->uri + i + 1, &size); + + int w, h; + unsigned char *raw = stbi_load_from_memory(data, size, &w, &h, NULL, 4); + + Image rimage = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); + ImageColorTint(&rimage, tint); + texture = LoadTextureFromImage(rimage); + UnloadImage(rimage); + } + } + else + { + char *textureName = image->uri; + char *texturePath = RL_MALLOC(strlen(texPath) + strlen(textureName) + 2); + strcpy(texturePath, texPath); + strcat(texturePath, "/"); + strcat(texturePath, textureName); + + Image rimage = LoadImage(texturePath); + ImageColorTint(&rimage, tint); + texture = LoadTextureFromImage(rimage); + UnloadImage(rimage); + RL_FREE(texturePath); + } + } + else if (image->buffer_view) + { + unsigned char *data = RL_MALLOC(image->buffer_view->size); + int n = image->buffer_view->offset; + int stride = image->buffer_view->stride ? image->buffer_view->stride : 1; + + for (int i = 0; i < image->buffer_view->size; i++) + { + data[i] = ((unsigned char *)image->buffer_view->buffer->data)[n]; + n += stride; + } + + int w, h; + unsigned char *raw = stbi_load_from_memory(data, image->buffer_view->size, &w, &h, NULL, 4); + + Image rimage = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); + ImageColorTint(&rimage, tint); + texture = LoadTextureFromImage(rimage); + UnloadImage(rimage); + free(raw); + free(data); + } + else + { + Image rimage = LoadImageEx(&tint, 1, 1); + texture = LoadTextureFromImage(rimage); + UnloadImage(rimage); + } + + return texture; +} + // Load glTF mesh data static Model LoadGLTF(const char *fileName) { @@ -3426,106 +3519,49 @@ static Model LoadGLTF(const char *fileName) for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); + //For each material for (int i = 0; i < model.materialCount - 1; i++) { - Color tint = WHITE; - Texture2D texture = { 0 }; + model.materials[i] = LoadMaterialDefault(); + Color tint = (Color){ 255, 255, 255, 255 }; const char *texPath = GetDirectoryPath(fileName); - if (data->materials[i].has_pbr_metallic_roughness) - { - tint.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255.99f); - tint.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255.99f); - tint.b = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[2]*255.99f); - tint.a = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[3]*255.99f); - } - else - { - tint.r = 1.0f; - tint.g = 1.0f; - tint.b = 1.0f; - tint.a = 1.0f; - } + //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; - if (data->materials[i].has_pbr_metallic_roughness) - { - cgltf_image *img = data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image; - - if (img->uri) - { - if ((strlen(img->uri) > 5) && - (img->uri[0] == 'd') && - (img->uri[1] == 'a') && - (img->uri[2] == 't') && - (img->uri[3] == 'a') && - (img->uri[4] == ':')) - { - // Data URI - // Format: data:;base64, - - // Find the comma - int i = 0; - while ((img->uri[i] != ',') && (img->uri[i] != 0)) i++; - - if (img->uri[i] == 0) TraceLog(LOG_WARNING, "[%s] Invalid data URI", fileName); - else - { - int size; - unsigned char *data = DecodeBase64(img->uri + i + 1, &size); - - int w, h; - unsigned char *raw = stbi_load_from_memory(data, size, &w, &h, NULL, 4); - - Image image = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); - ImageColorTint(&image, tint); - texture = LoadTextureFromImage(image); - UnloadImage(image); - } - } - else - { - char *textureName = img->uri; - char *texturePath = RL_MALLOC(strlen(texPath) + strlen(textureName) + 2); - strcpy(texturePath, texPath); - strcat(texturePath, "/"); - strcat(texturePath, textureName); - - Image image = LoadImage(texturePath); - ImageColorTint(&image, tint); - texture = LoadTextureFromImage(image); - UnloadImage(image); - RL_FREE(texturePath); - } - } - else if (img->buffer_view) - { - unsigned char *data = RL_MALLOC(img->buffer_view->size); - int n = img->buffer_view->offset; - int stride = img->buffer_view->stride ? img->buffer_view->stride : 1; - - for (int i = 0; i < img->buffer_view->size; i++) - { - data[i] = ((unsigned char *)img->buffer_view->buffer->data)[n]; - n += stride; - } - - int w, h; - unsigned char *raw = stbi_load_from_memory(data, img->buffer_view->size, &w, &h, NULL, 4); - - Image image = LoadImagePro(raw, w, h, UNCOMPRESSED_R8G8B8A8); - ImageColorTint(&image, tint); - texture = LoadTextureFromImage(image); - UnloadImage(image); - } - else - { - Image image = LoadImageEx(&tint, 1, 1); - texture = LoadTextureFromImage(image); - UnloadImage(image); + if (model.materials[i].name && data->materials[i].name) { + strcpy(model.materials[i].name, data->materials[i].name); } - model.materials[i] = LoadMaterialDefault(); - model.materials[i].maps[MAP_DIFFUSE].texture = texture; + // 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; + + if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture) { + model.materials[i].maps[MAP_ALBEDO].texture = LoadTextureFromCGLTFTextureView(data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image, tint, texPath); + } + + //tint isn't need for other textures.. pass null or clear? (try full white because of mixing (multiplying * white has no effect)) + tint = (Color){ 255, 255, 255, 255 }; + + if (data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture) { + model.materials[i].maps[MAP_ROUGHNESS].texture = LoadTextureFromCGLTFTextureView(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture->image, tint, texPath); + } + 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 = LoadTextureFromCGLTFTextureView(data->materials[i].normal_texture.texture->image, tint, texPath); + } + if (data->materials[i].occlusion_texture.texture) { + model.materials[i].maps[MAP_OCCLUSION].texture = LoadTextureFromCGLTFTextureView(data->materials[i].occlusion_texture.texture->image, tint, texPath); + } } } diff --git a/src/raylib.h b/src/raylib.h index 11587e2e..80786b69 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -106,7 +106,7 @@ #ifndef RL_FREE #define RL_FREE(p) free(p) #endif - + // NOTE: MSC C++ compiler does not support compound literals (C99 feature) // Plain structures in C++ (without constructors) can be initialized from { } initializers. #if defined(__cplusplus) @@ -336,6 +336,7 @@ typedef struct MaterialMap { // Material type (generic) typedef struct Material { + char* name; // Material name Shader shader; // Material shader MaterialMap *maps; // Material maps array (MAX_MATERIAL_MAPS) float *params; // Material generic parameters (if required) @@ -1406,7 +1407,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level) RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) - + //------------------------------------------------------------------------------------ // Network (Module: network) //------------------------------------------------------------------------------------