X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Fpublic-api%2Floader%2Fmaterial-definition.cpp;h=52028bf026a2a2df149b98a88d79fdb0eb123bf5;hb=HEAD;hp=7f86add67b74e98fbb57c21f061df607a339bf64;hpb=b3d23c288c1957114e5eb85bbd3ada6584036eaa;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-scene3d/public-api/loader/material-definition.cpp b/dali-scene3d/public-api/loader/material-definition.cpp index 7f86add..b61005b 100644 --- a/dali-scene3d/public-api/loader/material-definition.cpp +++ b/dali-scene3d/public-api/loader/material-definition.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,17 @@ * */ -// INTERNAL INCLUDES -#include "dali-scene3d/public-api/loader/material-definition.h" +// CLASS HEADER +#include // EXTERNAL INCLUDES -#include "dali-toolkit/public-api/image-loader/sync-image-loader.h" +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include namespace Dali { @@ -29,6 +35,8 @@ namespace Scene3D { namespace Loader { +const Matrix3 TextureDefinition::DEFAULT_TRANSFORM = Matrix3::IDENTITY; + namespace { constexpr SamplerFlags::Type FILTER_MODES_FROM_DALI[]{ @@ -63,7 +71,55 @@ constexpr WrapMode::Type WRAP_MODES_TO_DALI[]{ WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT}; -const SamplerFlags::Type SINGLE_VALUE_SAMPLER = SamplerFlags::Encode(FilterMode::NEAREST, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE); +const SamplerFlags::Type GetSingleValueSampler() +{ + static const SamplerFlags::Type SINGLE_VALUE_SAMPLER = SamplerFlags::Encode(FilterMode::NEAREST, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE); + return SINGLE_VALUE_SAMPLER; +} + +static constexpr std::string_view EMBEDDED_DATA_PREFIX = "data:"; +static constexpr std::string_view EMBEDDED_DATA_IMAGE_MEDIA_TYPE = "image/"; +static constexpr std::string_view EMBEDDED_DATA_BASE64_ENCODING_TYPE = "base64,"; + +Dali::PixelData LoadImageResource(const std::string& resourcePath, + TextureDefinition& textureDefinition, + FittingMode::Type fittingMode, + bool orientationCorrection) +{ + Dali::PixelData pixelData; + if(!textureDefinition.mTextureBuffer.empty()) + { + Dali::Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromBuffer(textureDefinition.mTextureBuffer.data(), textureDefinition.mTextureBuffer.size(), textureDefinition.mMinImageDimensions, fittingMode, textureDefinition.mSamplingMode, orientationCorrection); + if(pixelBuffer) + { + pixelData = Devel::PixelBuffer::Convert(pixelBuffer); + } + } + else if(textureDefinition.mImageUri.find(EMBEDDED_DATA_PREFIX.data()) == 0 && textureDefinition.mImageUri.find(EMBEDDED_DATA_IMAGE_MEDIA_TYPE.data(), EMBEDDED_DATA_PREFIX.length()) == EMBEDDED_DATA_PREFIX.length()) + { + auto position = textureDefinition.mImageUri.find(EMBEDDED_DATA_BASE64_ENCODING_TYPE.data(), EMBEDDED_DATA_PREFIX.length() + EMBEDDED_DATA_IMAGE_MEDIA_TYPE.length()); + if(position != std::string::npos) + { + position += EMBEDDED_DATA_BASE64_ENCODING_TYPE.length(); + std::string_view data = std::string_view(textureDefinition.mImageUri).substr(position); + std::vector buffer; + Dali::Toolkit::DecodeBase64FromString(data, buffer); + uint32_t bufferSize = buffer.size(); + + Dali::Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromBuffer(reinterpret_cast(buffer.data()), bufferSize, textureDefinition.mMinImageDimensions, fittingMode, textureDefinition.mSamplingMode, orientationCorrection); + if(pixelBuffer) + { + pixelData = Dali::Devel::PixelBuffer::Convert(pixelBuffer, true); + } + } + } + else + { + textureDefinition.mDirectoryPath = resourcePath; + pixelData = Internal::ImageResourceLoader::GetCachedPixelData(resourcePath + textureDefinition.mImageUri, textureDefinition.mMinImageDimensions, fittingMode, textureDefinition.mSamplingMode, orientationCorrection); + } + return pixelData; +} } // namespace SamplerFlags::Type SamplerFlags::Encode(FilterMode::Type minFilter, FilterMode::Type magFilter, WrapMode::Type wrapS, WrapMode::Type wrapT) @@ -100,14 +156,36 @@ Sampler SamplerFlags::MakeSampler(Type flags) return sampler; } -TextureDefinition::TextureDefinition(const std::string& imageUri, SamplerFlags::Type samplerFlags) +TextureDefinition::TextureDefinition(const std::string& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode, Matrix3 transform) : mImageUri(imageUri), - mSamplerFlags(samplerFlags) + mSamplerFlags(samplerFlags), + mMinImageDimensions(minImageDimensions), + mSamplingMode(samplingMode), + mTransform(transform) +{ +} + +TextureDefinition::TextureDefinition(std::string&& imageUri, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode, Matrix3 transform) +: mImageUri(std::move(imageUri)), + mSamplerFlags(samplerFlags), + mMinImageDimensions(minImageDimensions), + mSamplingMode(samplingMode), + mTransform(transform) +{ +} + +TextureDefinition::TextureDefinition(std::vector&& textureBuffer, SamplerFlags::Type samplerFlags, ImageDimensions minImageDimensions, SamplingMode::Type samplingMode, Matrix3 transform) +: mImageUri(), + mSamplerFlags(samplerFlags), + mMinImageDimensions(minImageDimensions), + mSamplingMode(samplingMode), + mTransform(transform), + mTextureBuffer(std::move(textureBuffer)) { } MaterialDefinition::RawData -MaterialDefinition::LoadRaw(const std::string& imagesPath) const +MaterialDefinition::LoadRaw(const std::string& imagesPath) { RawData raw; @@ -122,7 +200,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const raw.mTextures.reserve(numBuffers); // Load textures - auto iTexture = mTextureStages.cbegin(); + auto iTexture = mTextureStages.begin(); auto checkStage = [&](uint32_t flags) { return iTexture != mTextureStages.end() && MaskMatch(iTexture->mSemantic, flags); }; @@ -130,26 +208,24 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const // Check for compulsory textures: Albedo, Metallic, Roughness, Normal if(checkStage(ALBEDO | METALLIC)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; if(checkStage(NORMAL | ROUGHNESS)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } else // single value normal-roughness { - const auto bufferSize = 4; - uint8_t* buffer = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff, 0xff}; // normal of (0, 0, 1), roughness of 1 - raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER}); + raw.mTextures.push_back({Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataZAxisAndAlphaRGBA(), GetSingleValueSampler()}); } } else { if(checkStage(ALBEDO)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } else if(mNeedAlbedoTexture) // single value albedo, albedo-alpha or albedo-metallic @@ -176,43 +252,37 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const buffer[0] = static_cast(mColor.r * 255.f); buffer[1] = static_cast(mColor.g * 255.f); buffer[2] = static_cast(mColor.b * 255.f); - raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, format, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER}); + raw.mTextures.push_back({Dali::Integration::NewPixelDataWithReleaseAfterUpload(buffer, bufferSize, 1, 1, 0, format, PixelData::DELETE_ARRAY), GetSingleValueSampler()}); } // If we have transparency, or an image based albedo map, we will have to continue with separate metallicRoughness + normal. const bool createMetallicRoughnessAndNormal = hasTransparency || std::distance(mTextureStages.begin(), iTexture) > 0; if(checkStage(METALLIC | ROUGHNESS)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } else if(createMetallicRoughnessAndNormal && mNeedMetallicRoughnessTexture) { // NOTE: we want to set both metallic and roughness to 1.0; dli uses the R & A channels, // glTF2 uses B & G, so we might as well just set all components to 1.0. - const auto bufferSize = 4; - uint8_t* buffer = new uint8_t[bufferSize]{0xff, 0xff, 0xff, 0xff}; - raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER}); + raw.mTextures.push_back({Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataWhiteRGBA(), GetSingleValueSampler()}); } if(checkStage(NORMAL)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } else if(mNeedNormalTexture) { if(createMetallicRoughnessAndNormal) { - const auto bufferSize = 3; - uint8_t* buffer = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff}; // normal of (0, 0, 1) - raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER}); + raw.mTextures.push_back({Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataZAxisRGB(), GetSingleValueSampler()}); } else // single-value normal-roughness { - const auto bufferSize = 4; - uint8_t* buffer = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff, 0xff}; // normal of (0, 0, 1), roughness of 1.0 - raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER}); + raw.mTextures.push_back({Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataZAxisAndAlphaRGBA(), GetSingleValueSampler()}); } } } @@ -220,31 +290,31 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const // Extra textures. if(checkStage(SUBSURFACE)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } if(checkStage(OCCLUSION)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } if(checkStage(EMISSIVE)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } if(checkStage(SPECULAR)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } if(checkStage(SPECULAR_COLOR)) { - raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags}); + raw.mTextures.push_back({LoadImageResource(imagesPath, iTexture->mTexture, FittingMode::DEFAULT, true), iTexture->mTexture.mSamplerFlags}); ++iTexture; } @@ -258,12 +328,11 @@ TextureSet MaterialDefinition::Load(const EnvironmentDefinition::Vector& environ uint32_t n = 0; for(auto& tData : raw.mTextures) { - auto& pixels = tData.mPixels; - auto texture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight()); - texture.Upload(tData.mPixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight()); - if(tData.mSamplerFlags & SamplerFlags::MIPMAP_MASK) + auto& pixels = tData.mPixels; + Texture texture; + if(pixels) { - texture.GenerateMipmaps(); + texture = Dali::Scene3D::Internal::ImageResourceLoader::GetCachedTexture(pixels, tData.mSamplerFlags & SamplerFlags::MIPMAP_MASK); } textureSet.SetTexture(n, texture); @@ -272,6 +341,11 @@ TextureSet MaterialDefinition::Load(const EnvironmentDefinition::Vector& environ ++n; } + if(mShadowAvailable) + { + textureSet.SetTexture(n++, Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyTextureWhiteRGB()); + } + // Assign textures to slots -- starting with 2D ones, then cubemaps, if any. if(mEnvironmentIdx < static_cast(environments.size())) { @@ -310,9 +384,7 @@ TextureSet MaterialDefinition::Load(const EnvironmentDefinition::Vector& environ bool MaterialDefinition::CheckTextures(uint32_t flags) const { - return std::find_if(mTextureStages.begin(), mTextureStages.end(), [flags](const TextureStage& ts) { - return MaskMatch(ts.mSemantic, flags); - }) != mTextureStages.end(); + return std::find_if(mTextureStages.begin(), mTextureStages.end(), [flags](const TextureStage& ts) { return MaskMatch(ts.mSemantic, flags); }) != mTextureStages.end(); } } // namespace Loader