gltfio: prep step for allowing zero-instance assets
AssetLoader now loads assets in two passes: - Pass 1 creates VertexBuffer objects, MorphTargetBuffer objects, etc. - Pass 2 creates entities, renderables, etc (only if numInstances > 0) This feature will help us integrate gltfio with an internal library at Google.
This commit is contained in:
+176
-82
@@ -218,21 +218,36 @@ struct FAssetLoader : public AssetLoader {
|
||||
}
|
||||
|
||||
private:
|
||||
void createAsset(const cgltf_data* srcAsset, size_t numInstances);
|
||||
FFilamentInstance* createInstance(FFilamentAsset* primary, const cgltf_data* srcAsset);
|
||||
// Methods used during the first traveral (creation of VertexBuffer, IndexBuffer, etc)
|
||||
void createRootAsset(const cgltf_data* srcAsset);
|
||||
void recursePrimitives(const cgltf_data* srcAsset, const cgltf_node* rootNode);
|
||||
void createPrimitives(const cgltf_data* srcAsset, const cgltf_node* node, const char* name);
|
||||
bool createPrimitive(const cgltf_primitive* inPrim, Primitive* outPrim, const char* name);
|
||||
|
||||
// Methods used during subsequent traverals (creation of entities, renderables, etc)
|
||||
void createInstances(const cgltf_data* srcAsset, size_t numInstances);
|
||||
FFilamentInstance* createInstance(const cgltf_data* srcAsset);
|
||||
void recurseEntities(const cgltf_data* srcAsset, const cgltf_node* node, SceneMask scenes,
|
||||
Entity parent, FFilamentInstance* instance);
|
||||
void createRenderable(const cgltf_data* srcAsset, const cgltf_node* node, Entity entity,
|
||||
const char* name);
|
||||
bool createPrimitive(const cgltf_primitive* inPrim, Primitive* outPrim, const UvMap& uvmap,
|
||||
const char* name, MaterialInstance* mi);
|
||||
void createLight(const cgltf_light* light, Entity entity);
|
||||
void createCamera(const cgltf_camera* camera, Entity entity);
|
||||
MaterialInstance* createMaterialInstance(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor);
|
||||
void addTextureBinding(MaterialInstance* materialInstance, const char* parameterName,
|
||||
const cgltf_texture* srcTexture, bool srgb);
|
||||
void createMaterialVariants(const cgltf_data* srcAsset, const cgltf_mesh* mesh, Entity entity,
|
||||
FFilamentInstance* instance);
|
||||
|
||||
// Utility methods that work with MaterialProvider.
|
||||
Material* getMaterial(const cgltf_data* srcAsset, const cgltf_material* inputMat, UvMap* uvmap,
|
||||
bool vertexColor);
|
||||
MaterialInstance* createMaterialInstance(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor);
|
||||
MaterialKey getMaterialKey(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor,
|
||||
cgltf_texture_view* baseColorTexture,
|
||||
cgltf_texture_view* metallicRoughnessTexture) const;
|
||||
|
||||
public:
|
||||
EntityManager& mEntityManager;
|
||||
RenderableManager& mRenderableManager;
|
||||
@@ -251,7 +266,7 @@ public:
|
||||
MaterialInstanceCache mMaterialInstanceCache;
|
||||
|
||||
// Weak reference to the largest dummy buffer so far in the current loading phase.
|
||||
BufferObject* mDummyBufferObject;
|
||||
BufferObject* mDummyBufferObject = nullptr;
|
||||
};
|
||||
|
||||
FILAMENT_UPCAST(AssetLoader)
|
||||
@@ -295,11 +310,25 @@ FFilamentAsset* FAssetLoader::createInstancedAsset(const uint8_t* bytes, uint32_
|
||||
slog.e << "Unable to parse glTF file." << io::endl;
|
||||
return nullptr;
|
||||
}
|
||||
createAsset(sourceAsset, numInstances);
|
||||
if (mAsset) {
|
||||
glbdata.swap(mAsset->mSourceAsset->glbData);
|
||||
std::copy_n(mAsset->mInstances.data(), numInstances, instances);
|
||||
|
||||
createRootAsset(sourceAsset);
|
||||
if (mError) {
|
||||
delete mAsset;
|
||||
mAsset = nullptr;
|
||||
mError = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
createInstances(sourceAsset, numInstances);
|
||||
if (mError) {
|
||||
delete mAsset;
|
||||
mAsset = nullptr;
|
||||
mError = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glbdata.swap(mAsset->mSourceAsset->glbData);
|
||||
std::copy_n(mAsset->mInstances.data(), numInstances, instances);
|
||||
return mAsset;
|
||||
}
|
||||
|
||||
@@ -316,7 +345,7 @@ FilamentInstance* FAssetLoader::createInstance(FFilamentAsset* primary) {
|
||||
|
||||
mMaterialInstanceCache = MaterialInstanceCache(srcAsset);
|
||||
|
||||
FFilamentInstance* instance = createInstance(primary, srcAsset);
|
||||
FFilamentInstance* instance = createInstance(srcAsset);
|
||||
|
||||
if (primary->mAnimator) {
|
||||
primary->mAnimator->addInstance(instance);
|
||||
@@ -326,7 +355,7 @@ FilamentInstance* FAssetLoader::createInstance(FFilamentAsset* primary) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances) {
|
||||
void FAssetLoader::createRootAsset(const cgltf_data* srcAsset) {
|
||||
SYSTRACE_CALL();
|
||||
#if !GLTFIO_DRACO_SUPPORTED
|
||||
for (cgltf_size i = 0; i < srcAsset->extensions_required_count; i++) {
|
||||
@@ -339,7 +368,6 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
|
||||
#endif
|
||||
|
||||
mAsset = new FFilamentAsset(&mEngine, mNameManager, &mEntityManager, &mNodeManager, srcAsset);
|
||||
mDummyBufferObject = nullptr;
|
||||
|
||||
mMaterialInstanceCache = MaterialInstanceCache(srcAsset);
|
||||
|
||||
@@ -391,25 +419,10 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
|
||||
}
|
||||
}
|
||||
|
||||
mAsset->mRenderableCount = 0;
|
||||
|
||||
// Create a separate entity hierarchy for each instance. Note that MeshCache (vertex
|
||||
// buffers and index buffers) and MaterialInstanceCache (materials and textures) help avoid
|
||||
// needless duplication of resources.
|
||||
for (size_t index = 0; index < numInstances; ++index) {
|
||||
if (createInstance(mAsset, srcAsset) == nullptr) {
|
||||
mError = true;
|
||||
break;
|
||||
}
|
||||
for (const auto& [node, sceneMask] : mRootNodes) {
|
||||
recursePrimitives(srcAsset, node);
|
||||
}
|
||||
|
||||
// Sort the entities so that the renderable ones come first. This allows us to expose
|
||||
// a "renderables only" pointer without storing a separate list.
|
||||
const auto& rm = mEngine.getRenderableManager();
|
||||
std::partition(mAsset->mEntities.begin(), mAsset->mEntities.end(), [&rm](Entity a) {
|
||||
return rm.hasComponent(a);
|
||||
});
|
||||
|
||||
// Find every unique resource URI and store a pointer to any of the cgltf-owned cstrings
|
||||
// that match the URI. These strings get freed during releaseSourceData().
|
||||
tsl::robin_set<std::string_view> resourceUris;
|
||||
@@ -428,6 +441,40 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
|
||||
for (std::string_view uri : resourceUris) {
|
||||
mAsset->mResourceUris.push_back(uri.data());
|
||||
}
|
||||
}
|
||||
|
||||
void FAssetLoader::recursePrimitives(const cgltf_data* srcAsset, const cgltf_node* node) {
|
||||
const char* name = getNodeName(node, mDefaultNodeName);
|
||||
name = name ? name : "node";
|
||||
|
||||
if (node->mesh) {
|
||||
createPrimitives(srcAsset, node, name);
|
||||
}
|
||||
|
||||
for (cgltf_size i = 0, len = node->children_count; i < len; ++i) {
|
||||
recursePrimitives(srcAsset, node->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FAssetLoader::createInstances(const cgltf_data* srcAsset, size_t numInstances) {
|
||||
mAsset->mRenderableCount = 0;
|
||||
|
||||
// Create a separate entity hierarchy for each instance. Note that MeshCache (vertex
|
||||
// buffers and index buffers) and MaterialInstanceCache (materials and textures) help avoid
|
||||
// needless duplication of resources.
|
||||
for (size_t index = 0; index < numInstances; ++index) {
|
||||
if (createInstance(srcAsset) == nullptr) {
|
||||
mError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the entities so that the renderable ones come first. This allows us to expose
|
||||
// a "renderables only" pointer without storing a separate list.
|
||||
const auto& rm = mEngine.getRenderableManager();
|
||||
std::partition(mAsset->mEntities.begin(), mAsset->mEntities.end(), [&rm](Entity a) {
|
||||
return rm.hasComponent(a);
|
||||
});
|
||||
|
||||
if (mError) {
|
||||
destroyAsset(mAsset);
|
||||
@@ -436,16 +483,15 @@ void FAssetLoader::createAsset(const cgltf_data* srcAsset, size_t numInstances)
|
||||
}
|
||||
}
|
||||
|
||||
FFilamentInstance* FAssetLoader::createInstance(FFilamentAsset* primary,
|
||||
const cgltf_data* srcAsset) {
|
||||
auto rootTransform = mTransformManager.getInstance(primary->mRoot);
|
||||
FFilamentInstance* FAssetLoader::createInstance(const cgltf_data* srcAsset) {
|
||||
auto rootTransform = mTransformManager.getInstance(mAsset->mRoot);
|
||||
Entity instanceRoot = mEntityManager.create();
|
||||
mTransformManager.create(instanceRoot, rootTransform);
|
||||
|
||||
// Create an instance object, which is a just a lightweight wrapper around a vector of
|
||||
// entities and an animator. The creation of animator is triggered from ResourceLoader
|
||||
// because it could require external bin data.
|
||||
FFilamentInstance* instance = new FFilamentInstance(instanceRoot, primary);
|
||||
FFilamentInstance* instance = new FFilamentInstance(instanceRoot, mAsset);
|
||||
|
||||
// Check if the asset has variants.
|
||||
instance->variants.reserve(srcAsset->variants_count);
|
||||
@@ -458,12 +504,12 @@ FFilamentInstance* FAssetLoader::createInstance(FFilamentAsset* primary,
|
||||
recurseEntities(srcAsset, pair.first, pair.second, instanceRoot, instance);
|
||||
}
|
||||
|
||||
importSkins(primary, instance, srcAsset);
|
||||
importSkins(mAsset, instance, srcAsset);
|
||||
|
||||
// This needs to stay near the end of the method to allow detection of the first instance.
|
||||
primary->mInstances.push_back(instance);
|
||||
mAsset->mInstances.push_back(instance);
|
||||
|
||||
instance->boundingBox = primary->mBoundingBox;
|
||||
instance->boundingBox = mAsset->mBoundingBox;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -523,11 +569,6 @@ void FAssetLoader::recurseEntities(const cgltf_data* srcAsset, const cgltf_node*
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: refactor loading into 2 passes: the first pass creates all objects that are shared
|
||||
// amongst instances (VertexBuffer, IndexBuffer, etc) while the second pass creates the
|
||||
// lightweight ECS stuff (Renderables, Transformables) for each instance. This will allow
|
||||
// users to create assets with zero instances, which is a feature request from Google.
|
||||
|
||||
if (node->light && mAsset->mInstances.empty()) {
|
||||
createLight(node->light, entity);
|
||||
}
|
||||
@@ -541,6 +582,31 @@ void FAssetLoader::recurseEntities(const cgltf_data* srcAsset, const cgltf_node*
|
||||
}
|
||||
}
|
||||
|
||||
void FAssetLoader::createPrimitives(const cgltf_data* srcAsset, const cgltf_node* node,
|
||||
const char* name) {
|
||||
const cgltf_mesh* mesh = node->mesh;
|
||||
assert_invariant(mesh != nullptr);
|
||||
|
||||
// If the mesh is already loaded, obtain the list of Filament VertexBuffer / IndexBuffer objects
|
||||
// that were already generated (one for each primitive), otherwise allocate a new list of
|
||||
// pointers for the primitives.
|
||||
FixedCapacityVector<Primitive>& prims = mAsset->mMeshCache[mesh - srcAsset->meshes];
|
||||
if (prims.empty()) {
|
||||
prims.reserve(mesh->primitives_count);
|
||||
prims.resize(mesh->primitives_count);
|
||||
}
|
||||
for (cgltf_size index = 0, n = mesh->primitives_count; index < n; ++index) {
|
||||
Primitive& outputPrim = prims[index];
|
||||
const cgltf_primitive& inputPrim = mesh->primitives[index];
|
||||
|
||||
// Create a Filament VertexBuffer and IndexBuffer for this prim if we haven't already.
|
||||
if (!outputPrim.vertices && !createPrimitive(&inputPrim, &outputPrim, name)) {
|
||||
mError = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FAssetLoader::createRenderable(const cgltf_data* srcAsset, const cgltf_node* node,
|
||||
Entity entity, const char* name) {
|
||||
const cgltf_mesh* mesh = node->mesh;
|
||||
@@ -550,22 +616,19 @@ void FAssetLoader::createRenderable(const cgltf_data* srcAsset, const cgltf_node
|
||||
mat4f worldTransform = mTransformManager.getWorldTransform(thisTransform);
|
||||
|
||||
const cgltf_size primitiveCount = mesh->primitives_count;
|
||||
RenderableManager::Builder builder(primitiveCount);
|
||||
|
||||
// If the mesh is already loaded, obtain the list of Filament VertexBuffer / IndexBuffer objects
|
||||
// that were already generated (one for each primitive), otherwise allocate a new list of
|
||||
// pointers for the primitives.
|
||||
// that were already generated (one for each primitive).
|
||||
FixedCapacityVector<Primitive>& prims = mAsset->mMeshCache[mesh - srcAsset->meshes];
|
||||
if (prims.empty()) {
|
||||
prims = FixedCapacityVector<Primitive>(primitiveCount, Primitive {});
|
||||
}
|
||||
assert_invariant(prims.size() == primitiveCount);
|
||||
Primitive* outputPrim = prims.data();
|
||||
const cgltf_primitive* inputPrim = &mesh->primitives[0];
|
||||
|
||||
Aabb aabb;
|
||||
|
||||
// glTF spec says that all primitives MUST have the same number of morph targets in the same order.
|
||||
// glTF spec says that all primitives must have the same number of morph targets.
|
||||
const cgltf_size numMorphTargets = inputPrim ? inputPrim->targets_count : 0;
|
||||
RenderableManager::Builder builder(primitiveCount);
|
||||
builder.morphing(numMorphTargets);
|
||||
|
||||
// For each prim, create a Filament VertexBuffer, IndexBuffer, and MaterialInstance.
|
||||
@@ -589,6 +652,7 @@ void FAssetLoader::createRenderable(const cgltf_data* srcAsset, const cgltf_node
|
||||
bool hasVertexColor = primitiveHasVertexColor(inputPrim);
|
||||
MaterialInstance* mi = createMaterialInstance(srcAsset, inputPrim->material, &uvmap,
|
||||
hasVertexColor);
|
||||
assert_invariant(mi);
|
||||
if (!mi) {
|
||||
mError = true;
|
||||
continue;
|
||||
@@ -597,11 +661,7 @@ void FAssetLoader::createRenderable(const cgltf_data* srcAsset, const cgltf_node
|
||||
mAsset->mDependencyGraph.addEdge(entity, mi);
|
||||
builder.material(index, mi);
|
||||
|
||||
// Create a Filament VertexBuffer and IndexBuffer for this prim if we haven't already.
|
||||
if (!outputPrim->vertices && !createPrimitive(inputPrim, outputPrim, uvmap, name, mi)) {
|
||||
mError = true;
|
||||
continue;
|
||||
}
|
||||
assert_invariant(outputPrim->vertices);
|
||||
|
||||
// Expand the object-space bounding box.
|
||||
aabb.min = min(outputPrim->aabb.min, aabb.min);
|
||||
@@ -699,8 +759,15 @@ void FAssetLoader::createMaterialVariants(const cgltf_data* srcAsset, const cglt
|
||||
}
|
||||
|
||||
bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* outPrim,
|
||||
const UvMap& uvmap, const char* name, MaterialInstance* mi) {
|
||||
outPrim->uvmap = uvmap;
|
||||
const char* name) {
|
||||
Material* material = getMaterial(mAsset->mSourceAsset->hierarchy,
|
||||
inPrim->material, &outPrim->uvmap, primitiveHasVertexColor(inPrim));
|
||||
AttributeBitset requiredAttributes = material->getRequiredAttributes();
|
||||
|
||||
// TODO: populate a mapping of Texture Index => [MaterialInstance, const char*] slots.
|
||||
// By creating this mapping during the "recursePrimitives" phase, we will can allow
|
||||
// zero-instance assets to exist. This will be useful for "preloading", which is a feature
|
||||
// request from Google.
|
||||
|
||||
// Create a little lambda that appends to the asset's vertex buffer slots.
|
||||
auto slots = &mAsset->mBufferSlots;
|
||||
@@ -798,7 +865,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
|
||||
utils::slog.e << "Too many texture coordinate sets in " << name << utils::io::endl;
|
||||
continue;
|
||||
}
|
||||
UvSet uvset = uvmap[index];
|
||||
UvSet uvset = outPrim->uvmap[index];
|
||||
switch (uvset) {
|
||||
case UV0:
|
||||
semantic = VertexAttribute::UV0;
|
||||
@@ -811,7 +878,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
|
||||
case UNUSED:
|
||||
// If we have a free slot, then include this unused UV set in the VertexBuffer.
|
||||
// This allows clients to swap the glTF material with a custom material.
|
||||
if (!hasUv0 && getNumUvSets(uvmap) == 0) {
|
||||
if (!hasUv0 && getNumUvSets(outPrim->uvmap) == 0) {
|
||||
semantic = VertexAttribute::UV0;
|
||||
hasUv0 = true;
|
||||
break;
|
||||
@@ -853,8 +920,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
|
||||
}
|
||||
|
||||
// If the model is lit but does not have normals, we'll need to generate flat normals.
|
||||
auto const* const material = mi->getMaterial();
|
||||
if (material->getRequiredAttributes().test(VertexAttribute::TANGENTS) && !hasNormals) {
|
||||
if (requiredAttributes.test(VertexAttribute::TANGENTS) && !hasNormals) {
|
||||
vbb.attribute(VertexAttribute::TANGENTS, slot, VertexBuffer::AttributeType::SHORT4);
|
||||
vbb.normalized(VertexAttribute::TANGENTS);
|
||||
cgltf_attribute_type atype = cgltf_attribute_type_normal;
|
||||
@@ -933,7 +999,7 @@ bool FAssetLoader::createPrimitive(const cgltf_primitive* inPrim, Primitive* out
|
||||
vbb.normalized(VertexAttribute::COLOR);
|
||||
}
|
||||
|
||||
int numUvSets = getNumUvSets(uvmap);
|
||||
int numUvSets = getNumUvSets(outPrim->uvmap);
|
||||
if (!hasUv0 && numUvSets > 0) {
|
||||
needsDummyData = true;
|
||||
vbb.attribute(VertexAttribute::UV0, slot, VertexBuffer::AttributeType::USHORT2);
|
||||
@@ -1079,21 +1145,17 @@ void FAssetLoader::createCamera(const cgltf_camera* camera, Entity entity) {
|
||||
mAsset->mCameraEntities.push_back(entity);
|
||||
}
|
||||
|
||||
MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor) {
|
||||
MaterialInstanceCache::Entry* const cacheEntry =
|
||||
mMaterialInstanceCache.getEntry(&inputMat, vertexColor);
|
||||
if (cacheEntry->instance) {
|
||||
*uvmap = cacheEntry->uvmap;
|
||||
return cacheEntry->instance;
|
||||
}
|
||||
|
||||
MaterialKey FAssetLoader::getMaterialKey(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor,
|
||||
cgltf_texture_view* baseColorTexture, cgltf_texture_view* metallicRoughnessTexture) const {
|
||||
auto mrConfig = inputMat->pbr_metallic_roughness;
|
||||
auto sgConfig = inputMat->pbr_specular_glossiness;
|
||||
auto ccConfig = inputMat->clearcoat;
|
||||
auto trConfig = inputMat->transmission;
|
||||
auto shConfig = inputMat->sheen;
|
||||
auto vlConfig = inputMat->volume;
|
||||
*baseColorTexture = mrConfig.base_color_texture;
|
||||
*metallicRoughnessTexture = mrConfig.metallic_roughness_texture;
|
||||
|
||||
bool hasTextureTransforms =
|
||||
sgConfig.diffuse_texture.has_transform ||
|
||||
@@ -1110,19 +1172,16 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsse
|
||||
shConfig.sheen_roughness_texture.has_transform ||
|
||||
trConfig.transmission_texture.has_transform;
|
||||
|
||||
cgltf_texture_view baseColorTexture = mrConfig.base_color_texture;
|
||||
cgltf_texture_view metallicRoughnessTexture = mrConfig.metallic_roughness_texture;
|
||||
|
||||
MaterialKey matkey {
|
||||
.doubleSided = !!inputMat->double_sided,
|
||||
.unlit = !!inputMat->unlit,
|
||||
.hasVertexColors = vertexColor,
|
||||
.hasBaseColorTexture = baseColorTexture.texture != nullptr,
|
||||
.hasBaseColorTexture = baseColorTexture->texture != nullptr,
|
||||
.hasNormalTexture = inputMat->normal_texture.texture != nullptr,
|
||||
.hasOcclusionTexture = inputMat->occlusion_texture.texture != nullptr,
|
||||
.hasEmissiveTexture = inputMat->emissive_texture.texture != nullptr,
|
||||
.enableDiagnostics = mDiagnosticsEnabled,
|
||||
.baseColorUV = (uint8_t) baseColorTexture.texcoord,
|
||||
.baseColorUV = (uint8_t) baseColorTexture->texcoord,
|
||||
.hasClearCoatTexture = ccConfig.clearcoat_texture.texture != nullptr,
|
||||
.clearCoatUV = (uint8_t) ccConfig.clearcoat_texture.texcoord,
|
||||
.hasClearCoatRoughnessTexture = ccConfig.clearcoat_roughness_texture.texture != nullptr,
|
||||
@@ -1151,18 +1210,18 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsse
|
||||
if (inputMat->has_pbr_specular_glossiness) {
|
||||
matkey.useSpecularGlossiness = true;
|
||||
if (sgConfig.diffuse_texture.texture) {
|
||||
baseColorTexture = sgConfig.diffuse_texture;
|
||||
*baseColorTexture = sgConfig.diffuse_texture;
|
||||
matkey.hasBaseColorTexture = true;
|
||||
matkey.baseColorUV = (uint8_t) baseColorTexture.texcoord;
|
||||
matkey.baseColorUV = (uint8_t) baseColorTexture->texcoord;
|
||||
}
|
||||
if (sgConfig.specular_glossiness_texture.texture) {
|
||||
metallicRoughnessTexture = sgConfig.specular_glossiness_texture;
|
||||
*metallicRoughnessTexture = sgConfig.specular_glossiness_texture;
|
||||
matkey.hasSpecularGlossinessTexture = true;
|
||||
matkey.specularGlossinessUV = (uint8_t) metallicRoughnessTexture.texcoord;
|
||||
matkey.specularGlossinessUV = (uint8_t) metallicRoughnessTexture->texcoord;
|
||||
}
|
||||
} else {
|
||||
matkey.hasMetallicRoughnessTexture = metallicRoughnessTexture.texture != nullptr;
|
||||
matkey.metallicRoughnessUV = (uint8_t) metallicRoughnessTexture.texcoord;
|
||||
matkey.hasMetallicRoughnessTexture = metallicRoughnessTexture->texture != nullptr;
|
||||
matkey.metallicRoughnessUV = (uint8_t) metallicRoughnessTexture->texcoord;
|
||||
}
|
||||
|
||||
switch (inputMat->alpha_mode) {
|
||||
@@ -1179,6 +1238,34 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsse
|
||||
break;
|
||||
}
|
||||
|
||||
return matkey;
|
||||
}
|
||||
|
||||
Material* FAssetLoader::getMaterial(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor) {
|
||||
cgltf_texture_view baseColorTexture;
|
||||
cgltf_texture_view metallicRoughnessTexture;
|
||||
MaterialKey matkey = getMaterialKey(srcAsset, inputMat, uvmap, vertexColor,
|
||||
&baseColorTexture, &metallicRoughnessTexture);
|
||||
Material* material = mMaterials.getMaterial(&matkey, uvmap, inputMat->name);
|
||||
assert_invariant(material);
|
||||
return material;
|
||||
}
|
||||
|
||||
MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsset,
|
||||
const cgltf_material* inputMat, UvMap* uvmap, bool vertexColor) {
|
||||
MaterialInstanceCache::Entry* const cacheEntry =
|
||||
mMaterialInstanceCache.getEntry(&inputMat, vertexColor);
|
||||
if (cacheEntry->instance) {
|
||||
*uvmap = cacheEntry->uvmap;
|
||||
return cacheEntry->instance;
|
||||
}
|
||||
|
||||
cgltf_texture_view baseColorTexture;
|
||||
cgltf_texture_view metallicRoughnessTexture;
|
||||
MaterialKey matkey = getMaterialKey(srcAsset, inputMat, uvmap, vertexColor, &baseColorTexture,
|
||||
&metallicRoughnessTexture);
|
||||
|
||||
// Check if this material has an extras string.
|
||||
CString extras;
|
||||
const cgltf_size extras_size = inputMat->extras.end_offset - inputMat->extras.start_offset;
|
||||
@@ -1197,6 +1284,13 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsse
|
||||
|
||||
mAsset->mMaterialInstances.push_back(mi);
|
||||
|
||||
auto mrConfig = inputMat->pbr_metallic_roughness;
|
||||
auto sgConfig = inputMat->pbr_specular_glossiness;
|
||||
auto ccConfig = inputMat->clearcoat;
|
||||
auto trConfig = inputMat->transmission;
|
||||
auto shConfig = inputMat->sheen;
|
||||
auto vlConfig = inputMat->volume;
|
||||
|
||||
// Check the material blending mode, not the cgltf blending mode, because the provider
|
||||
// might have selected an alternative blend mode (e.g. to support transmission).
|
||||
if (mi->getMaterial()->getBlendingMode() == filament::BlendingMode::MASKED) {
|
||||
|
||||
Reference in New Issue
Block a user