From fc0d587b40d12af30f0091c9d10f254caf9d0e4d Mon Sep 17 00:00:00 2001 From: magicwhale Date: Fri, 19 Oct 2018 11:11:57 -0700 Subject: [PATCH] Added support for more features in gltf_viewer sample --- samples/CMakeLists.txt | 9 +- samples/app/GltfMeshAssimp.cpp | 6 - samples/app/GltfMeshAssimp.h | 14 - samples/app/MeshAssimp.cpp | 522 ++++++++++++++----- samples/app/MeshAssimp.h | 21 +- samples/gltf_viewer.cpp | 107 +--- samples/materials/gltf2.mat | 39 +- samples/materials/gltf2DoubleSided.mat | 71 +++ samples/materials/gltf2DoubleSidedMasked.mat | 74 +++ samples/materials/gltf2DoubleSidedTrans.mat | 74 +++ samples/materials/gltf2DoubleSidedUnlit.mat | 62 +++ samples/materials/gltf2Masked.mat | 73 +++ samples/materials/gltf2Trans.mat | 73 +++ samples/materials/gltf2Unlit.mat | 61 +++ samples/sample_full_pbr.cpp | 27 +- 15 files changed, 947 insertions(+), 286 deletions(-) delete mode 100644 samples/app/GltfMeshAssimp.cpp delete mode 100644 samples/app/GltfMeshAssimp.h create mode 100644 samples/materials/gltf2DoubleSided.mat create mode 100644 samples/materials/gltf2DoubleSidedMasked.mat create mode 100644 samples/materials/gltf2DoubleSidedTrans.mat create mode 100644 samples/materials/gltf2DoubleSidedUnlit.mat create mode 100644 samples/materials/gltf2Masked.mat create mode 100644 samples/materials/gltf2Trans.mat create mode 100644 samples/materials/gltf2Unlit.mat diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 976d2c2796..9ca6805b04 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -12,6 +12,13 @@ set(MATERIAL_SRCS materials/aiDefaultTrans.mat materials/depthVisualizer.mat materials/gltf2.mat + materials/gltf2DoubleSided.mat + materials/gltf2DoubleSidedMasked.mat + materials/gltf2DoubleSidedTrans.mat + materials/gltf2DoubleSidedUnlit.mat + materials/gltf2Masked.mat + materials/gltf2Trans.mat + materials/gltf2Unlit.mat materials/groundShadow.mat materials/sandboxCloth.mat materials/sandboxLit.mat @@ -70,7 +77,7 @@ set(APP_SRCS app/IBL.cpp app/Image.cpp app/IcoSphere.cpp - app/Sphere.cpp gltf_viewer.cpp) + app/Sphere.cpp) if (APPLE) list(APPEND APP_SRCS app/NativeWindowHelperCocoa.mm) diff --git a/samples/app/GltfMeshAssimp.cpp b/samples/app/GltfMeshAssimp.cpp deleted file mode 100644 index 87a007ec68..0000000000 --- a/samples/app/GltfMeshAssimp.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// -// Created by Michael Wang on 10/8/18. -// - -#include "GltfMeshAssimp.h" - diff --git a/samples/app/GltfMeshAssimp.h b/samples/app/GltfMeshAssimp.h deleted file mode 100644 index aac8616269..0000000000 --- a/samples/app/GltfMeshAssimp.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// Created by Michael Wang on 10/8/18. -// - -#ifndef TNT_GLTFMESHASSIMP_H -#define TNT_GLTFMESHASSIMP_H -#include "MeshAssimp.h" - -class GltfMeshAssimp : public MeshAssimp { - -}; - - -#endif //TNT_GLTFMESHASSIMP_H diff --git a/samples/app/MeshAssimp.cpp b/samples/app/MeshAssimp.cpp index f286dabd51..d4f3001570 100644 --- a/samples/app/MeshAssimp.cpp +++ b/samples/app/MeshAssimp.cpp @@ -17,6 +17,7 @@ #include "MeshAssimp.h" #include +#include #include #include @@ -29,6 +30,8 @@ #include #include +#include +#include #include #include @@ -37,6 +40,8 @@ #include +#include + using namespace filament; using namespace filamat; @@ -55,7 +60,85 @@ static constexpr uint8_t GLTF2_PACKAGE[] = { #include "generated/material/gltf2.inc" }; +static constexpr uint8_t GLTF2_DS_PACKAGE[] = { + #include "generated/material/gltf2DoubleSided.inc" +}; + +static constexpr uint8_t GLTF2_TRANS_PACKAGE[] = { + #include "generated/material/gltf2Trans.inc" +}; + +static constexpr uint8_t GLTF2_DS_TRANS_PACKAGE[] = { + #include "generated/material/gltf2DoubleSidedTrans.inc" +}; + +static constexpr uint8_t GLTF2_MASKED_PACKAGE[] = { + #include "generated/material/gltf2Masked.inc" +}; + +static constexpr uint8_t GLTF2_DS_MASKED_PACKAGE[] = { + #include "generated/material/gltf2DoubleSidedMasked.inc" +}; + +static constexpr uint8_t GLTF2_UNLIT_PACKAGE[] = { + #include "generated/material/gltf2Unlit.inc" +}; + +static constexpr uint8_t GLTF2_DS_UNLIT_PACKAGE[] = { + #include "generated/material/gltf2DoubleSidedUnlit.inc" +}; + +Texture* MeshAssimp::createOneByOneTexture(uint32_t pixel) { + uint32_t *textureData = (uint32_t *) malloc(sizeof(uint32_t)); + *textureData = pixel; + + Texture *texturePtr = Texture::Builder() + .width(uint32_t(1)) + .height(uint32_t(1)) + .levels(0xff) + .format(driver::TextureFormat::RGB8) + .build(mEngine); + + Texture::PixelBufferDescriptor defaultNormalBuffer(textureData, + size_t(1 * 1 * 3), + Texture::Format::RGB, + Texture::Type::UBYTE, + (driver::BufferDescriptor::Callback) &free); + + texturePtr->setImage(mEngine, 0, std::move(defaultNormalBuffer)); + texturePtr->generateMipmaps(mEngine); + + return texturePtr; +} + MeshAssimp::MeshAssimp(Engine& engine) : mEngine(engine) { + //Initialize some things here + mDefaultMap = createOneByOneTexture(0xffffffff); + mDefaultNormalMap = createOneByOneTexture(0xffff8080); + mGltfMaterial = Material::Builder() + .package((void*) GLTF2_PACKAGE, sizeof(GLTF2_PACKAGE)) + .build(mEngine); + mGltfMaterialDS = Material::Builder() + .package((void*) GLTF2_DS_PACKAGE, sizeof(GLTF2_DS_PACKAGE)) + .build(mEngine); + mGltfMaterialTrans = Material::Builder() + .package((void*) GLTF2_TRANS_PACKAGE, sizeof(GLTF2_TRANS_PACKAGE)) + .build(mEngine); + mGltfMaterialDSTrans = Material::Builder() + .package((void*) GLTF2_DS_TRANS_PACKAGE, sizeof(GLTF2_DS_TRANS_PACKAGE)) + .build(mEngine); + mGltfMaterialMasked = Material::Builder() + .package((void*) GLTF2_MASKED_PACKAGE, sizeof(GLTF2_MASKED_PACKAGE)) + .build(mEngine); + mGltfMaterialDSMasked = Material::Builder() + .package((void*) GLTF2_DS_MASKED_PACKAGE, sizeof(GLTF2_DS_MASKED_PACKAGE)) + .build(mEngine); + mGltfMaterialUnlit = Material::Builder() + .package((void*) GLTF2_UNLIT_PACKAGE, sizeof(GLTF2_UNLIT_PACKAGE)) + .build(mEngine); + mGltfMaterialDSUnlit = Material::Builder() + .package((void*) GLTF2_DS_UNLIT_PACKAGE, sizeof(GLTF2_DS_UNLIT_PACKAGE)) + .build(mEngine); } MeshAssimp::~MeshAssimp() { @@ -64,8 +147,16 @@ MeshAssimp::~MeshAssimp() { mEngine.destroy(mDefaultColorMaterial); mEngine.destroy(mDefaultTransparentColorMaterial); mEngine.destroy(mGltfMaterial); + mEngine.destroy(mGltfMaterialDS); + mEngine.destroy(mGltfMaterialTrans); + mEngine.destroy(mGltfMaterialDSTrans); + mEngine.destroy(mGltfMaterialMasked); + mEngine.destroy(mGltfMaterialDSMasked); + mEngine.destroy(mGltfMaterialUnlit); + mEngine.destroy(mGltfMaterialDSUnlit); mEngine.destroy(mDefaultNormalMap); mEngine.destroy(mDefaultMap); + for (Entity renderable : mRenderables) { mEngine.destroy(renderable); } @@ -91,22 +182,37 @@ struct State { }; //TODO: Remove redundant method from sample_full_pbr -void loadTex(Engine* engine, const std::string& filePath, Texture** map, bool sRGB = true) { +static void loadTexture(Engine *engine, const std::string &filePath, Texture **map, bool sRGB, bool hasAlpha) { if (!filePath.empty()) { Path path(filePath); if (path.exists()) { int w, h, n; - unsigned char* data = stbi_load(path.getAbsolutePath().c_str(), &w, &h, &n, 3); + int numChannels = hasAlpha ? 4 : 3; + + driver::TextureFormat inputFormat; + if (sRGB) { + inputFormat = hasAlpha ? driver::TextureFormat::SRGB8_A8 : driver::TextureFormat::SRGB8; + } else { + inputFormat = hasAlpha ? driver::TextureFormat::RGBA8 : driver::TextureFormat::RGB8; + } + + Texture::Format outputFormat = hasAlpha ? Texture::Format::RGBA : Texture::Format::RGB; + + uint8_t *data = stbi_load(path.getAbsolutePath().c_str(), &w, &h, &n, numChannels); if (data != nullptr) { *map = Texture::Builder() .width(uint32_t(w)) .height(uint32_t(h)) .levels(0xff) - .format(sRGB ? driver::TextureFormat::SRGB8 : driver::TextureFormat::RGB8) + .format(inputFormat) .build(*engine); - Texture::PixelBufferDescriptor buffer(data, size_t(w * h * 3), - Texture::Format::RGB, Texture::Type::UBYTE, - (driver::BufferDescriptor::Callback) &stbi_image_free); + + Texture::PixelBufferDescriptor buffer(data, + size_t(w * h * numChannels), + outputFormat, + Texture::Type::UBYTE, + (driver::BufferDescriptor::Callback) &stbi_image_free); + (*map)->setImage(*engine, 0, std::move(buffer)); (*map)->generateMipmaps(*engine); } else { @@ -118,6 +224,128 @@ void loadTex(Engine* engine, const std::string& filePath, Texture** map, bool sR } } +void loadEmbeddedTexture(Engine *engine, aiTexture *embeddedTex, Texture **map, bool sRGB, bool hasAlpha) { + int w, h, n; + + int numChannels = hasAlpha ? 4 : 3; + + driver::TextureFormat inputFormat; + if (sRGB) { + inputFormat = hasAlpha ? driver::TextureFormat::SRGB8_A8 : driver::TextureFormat::SRGB8; + } else { + inputFormat = hasAlpha ? driver::TextureFormat::RGBA8 : driver::TextureFormat::RGB8; + } + + Texture::Format outputFormat = hasAlpha ? Texture::Format::RGBA : Texture::Format::RGB; + + uint8_t *data = stbi_load_from_memory((unsigned char *) embeddedTex->pcData, + embeddedTex->mWidth, &w, &h, &n, numChannels); + + *map = Texture::Builder() + .width(uint32_t(w)) + .height(uint32_t(h)) + .levels(0xff) + .format(inputFormat) + .build(*engine); + + Texture::PixelBufferDescriptor defaultBuffer(data, + size_t(w * h * numChannels), + outputFormat, + Texture::Type::UBYTE, + (driver::BufferDescriptor::Callback) &free); + + (*map)->setImage(*engine, 0, std::move(defaultBuffer)); + (*map)->generateMipmaps(*engine); +} + +// Takes a texture filename and returns the index of the embedded texture, -1 if the texture is not embedded +int getEmbeddedTextureId(const aiString& path) { + const char *pathStr = path.C_Str(); + if (path.length >= 2 && pathStr[0] == '*') { + for (int i; i < path.length; i++) { + if (!isdigit(pathStr[i])) + return -1; + } + return std::atoi(pathStr + 1); + } + return -1; +} + +TextureSampler::WrapMode aiToFilamentMapMode(aiTextureMapMode mapMode) { + switch(mapMode) { + case aiTextureMapMode_Clamp : + return TextureSampler::WrapMode::CLAMP_TO_EDGE; + case aiTextureMapMode_Mirror : + return TextureSampler::WrapMode::MIRRORED_REPEAT; + default: + return TextureSampler::WrapMode::REPEAT; + } +} + +// TODO: Change this to a member function (requires some alteration of cmakelsts.txt) +void setTextureFromPath(const aiScene *scene, + Engine *engine, + std::vector textures, + const aiString &texFile, + const std::string &materialName, + const std::string &texDir, + aiTextureMapMode *mapMode, + const char *parameterName, + std::map &outMaterials) { + TextureSampler sampler; + if (mapMode) { + sampler = TextureSampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, + TextureSampler::MagFilter::LINEAR, + aiToFilamentMapMode(mapMode[0]), + aiToFilamentMapMode(mapMode[1]), + aiToFilamentMapMode(mapMode[2])); + } else { + sampler = TextureSampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, + TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); + } + + Texture* textureMap = nullptr; + int embeddedId = getEmbeddedTextureId(texFile); + + //TODO: change this in refactor + bool isSRGB = strcmp(parameterName, "baseColorMap") == 0 || strcmp(parameterName, "emissiveMap") == 0; + bool hasAlpha = strcmp(parameterName, "baseColorMap") == 0; + + if (embeddedId != -1) { + loadEmbeddedTexture(engine, scene->mTextures[embeddedId], &textureMap, isSRGB, hasAlpha); + } else { + loadTexture(engine, texDir + texFile.C_Str(), &textureMap, isSRGB, hasAlpha); + } + + textures.push_back(textureMap); + + if (textureMap != nullptr) { + outMaterials[materialName]->setParameter( + parameterName, textureMap, sampler); + } +} + +float3 transformPoint(const float3 point, const mat4f transform) { + return (transform * float4(point, 1.0f)).xyz; +} + +template +Box computeTransformedAABB(VECTOR const* vertices, INDEX const* indices, size_t count, + const mat4f& transform) noexcept { + size_t stride = sizeof(VECTOR); + math::float3 bmin(std::numeric_limits::max()); + math::float3 bmax(std::numeric_limits::lowest()); + for (size_t i = 0; i < count; ++i) { + VECTOR const* p = reinterpret_cast( + (char const*)vertices + indices[i] * stride); + const math::float3 v(p->x, p->y, p->z); + float3 tv = transformPoint(v, transform); + bmin = min(bmin, tv); + bmax = max(bmax, tv); + } + return Box().set(bmin, bmax); +} + void MeshAssimp::addFromFile(const Path& path, std::map& materials, bool overrideMaterial) { @@ -134,43 +362,7 @@ void MeshAssimp::addFromFile(const Path& path, // "command buffer" lifetime, we wouldn't need to have to deal with freeing the // std::vectors here. - // Make default map for all textures except Normal - int defaultTexSize = 4; - unsigned char *defaultTexData = (unsigned char *) malloc(defaultTexSize*sizeof(unsigned char*)); - for (int i=0; i < defaultTexSize; i++){ - defaultTexData[i] = static_cast(255); - } - mDefaultMap = Texture::Builder() - .width(uint32_t(1)) - .height(uint32_t(1)) - .levels(0xff) - .format(driver::TextureFormat::SRGB8) - .build(mEngine); - Texture::PixelBufferDescriptor defaultBuffer(defaultTexData, size_t(1 * 1 * 3), - Texture::Format::RGB, Texture::Type::UBYTE - ,(driver::BufferDescriptor::Callback) &free); - mDefaultMap->setImage(mEngine, 0, std::move(defaultBuffer)); - mDefaultMap->generateMipmaps(mEngine); - - //Make default Normal Map - unsigned char *defaultNormalTexData = (unsigned char *) malloc(defaultTexSize*sizeof(unsigned char*)); - defaultNormalTexData[0] = static_cast(128); - defaultNormalTexData[1] = static_cast(128); - defaultNormalTexData[2] = static_cast(255); - defaultNormalTexData[3] = static_cast(0); - - mDefaultNormalMap = Texture::Builder() - .width(uint32_t(1)) - .height(uint32_t(1)) - .levels(0xff) - .format(driver::TextureFormat::SRGB8) - .build(mEngine); - Texture::PixelBufferDescriptor defaultNormalBuffer(defaultNormalTexData, size_t(1 * 1 * 3), - Texture::Format::RGB, Texture::Type::UBYTE - ,(driver::BufferDescriptor::Callback) &free); - mDefaultNormalMap->setImage(mEngine, 0, std::move(defaultNormalBuffer)); - mDefaultNormalMap->generateMipmaps(mEngine); - + //TODO: a lot of these method arguments should probably be class or global variables if (!setFromFile(path, indices, positions, tangents, texCoords, meshes, parents, materials)) { return; } @@ -226,13 +418,14 @@ void MeshAssimp::addFromFile(const Path& path, materials[AI_DEFAULT_MATERIAL_NAME] = mDefaultColorMaterial->createInstance(); } - - size_t startIndex = mRenderables.size(); mRenderables.resize(startIndex + meshes.size()); EntityManager::get().create(meshes.size(), mRenderables.data() + startIndex); + EntityManager::get().create(1, &rootEntity); TransformManager& tcm = mEngine.getTransformManager(); + //Add root instance + tcm.create(rootEntity, TransformManager::Instance{}, mat4f()); for (auto& mesh : meshes) { RenderableManager::Builder builder(mesh.parts.size()); @@ -245,15 +438,12 @@ void MeshAssimp::addFromFile(const Path& path, if (overrideMaterial) { builder.material(partIndex, materials[AI_DEFAULT_MATERIAL_NAME]); - } else { - auto pos = materials.find(part.material); if (pos != materials.end()) { builder.material(partIndex, pos->second); } else { - std::cout << "I don't think this should be running" << std::endl; MaterialInstance* colorMaterial; if (part.opacity < 1.0f) { colorMaterial = mDefaultTransparentColorMaterial->createInstance(); @@ -270,7 +460,6 @@ void MeshAssimp::addFromFile(const Path& path, materials[part.material] = colorMaterial; } } - partIndex++; } @@ -281,7 +470,7 @@ void MeshAssimp::addFromFile(const Path& path, } auto pindex = parents[meshIndex]; TransformManager::Instance parent((pindex < 0) ? - TransformManager::Instance{} : tcm.getInstance(mRenderables[pindex])); + tcm.getInstance(rootEntity) : tcm.getInstance(mRenderables[pindex])); tcm.create(entity, parent, mesh.transform); } } @@ -307,6 +496,8 @@ bool MeshAssimp::setFromFile(const Path& file, // normals and tangents aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace | + // UV Coordinates + aiProcess_GenUVCoords | // topology optimization aiProcess_FindInstances | aiProcess_OptimizeMeshes | @@ -317,10 +508,12 @@ bool MeshAssimp::setFromFile(const Path& file, // we only support triangles aiProcess_Triangulate); - if (!scene){ + scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace); + + if (!scene) { std::cout << "no scene" << std::endl; } - if (!scene->mRootNode){ + if (!scene->mRootNode) { std::cout << "no root node" << std::endl; } @@ -361,14 +554,13 @@ bool MeshAssimp::setFromFile(const Path& file, outMeshes.back().offset = outIndices.size(); outMeshes.back().transform = current; + mat4f parentTransform = parentIndex >= 0 ? outMeshes[parentIndex].accTransform : mat4f(); + outMeshes.back().accTransform = parentTransform * current; + // Bias and scale factor when storing tangent frames in normalized short4 const float bias = 1.0f / 32767.0f; const float factor = (float) (sqrt(1.0 - (double) bias * (double) bias)); - mGltfMaterial = Material::Builder() - .package((void*) GLTF2_PACKAGE, sizeof(GLTF2_PACKAGE)) - .build(mEngine); - for (size_t i = 0; i < node->mNumMeshes; i++) { aiMesh const* mesh = scene->mMeshes[node->mMeshes[i]]; @@ -387,9 +579,23 @@ bool MeshAssimp::setFromFile(const Path& file, size_t indicesOffset = outPositions.size(); for (size_t j = 0; j < numVertices; j++) { - quatf q = mat3f::packTangentFrame({tangents[j], bitangents[j], normals[j]}); + float3 normal = normals[j]; + float3 texCoord = texCoords ? texCoords[j] : float3{0.0}; + float3 tangent; + float3 bitangent; + + //If the tangent and bitangent don't exist, make arbitrary ones + if (!tangents) { + bitangent = norm(cross(normal, float3{1.0, 0.0, 0.0})); + tangent = norm(cross(normal, bitangent)); + } else { + tangent = tangents[j]; + bitangent = bitangents[j]; + } + + quatf q = mat3f::packTangentFrame({tangent, bitangent, normal}); outTangents.push_back(packSnorm16(q.xyzw)); - outTexCoords.emplace_back(texCoords[j].xy); + outTexCoords.emplace_back(texCoord.xy); outPositions.emplace_back(positions[j], 1.0_h); } @@ -408,38 +614,72 @@ bool MeshAssimp::setFromFile(const Path& file, uint32_t materialId = mesh->mMaterialIndex; aiMaterial const* material = scene->mMaterials[materialId]; - //Get filepaths for PBR textures - for (i=0; i < material->mNumProperties; i++) { - std::cout << material->mProperties[i]->mKey.C_Str() << std::endl; - } - - int texIndex = 0; aiString baseColorPath; aiString AOPath; aiString MRPath; aiString normalPath; aiString emissivePath; aiString name; - std::string materialName; + aiTextureMapMode mapMode[3]; + std::string materialName; if (material->Get(AI_MATKEY_NAME, name) != AI_SUCCESS) { - materialName = AI_DEFAULT_MATERIAL_NAME; + static int matCount = 0; + while (outMaterials.find("_mat_" + std::to_string(matCount)) != outMaterials.end()) { + matCount ++; + } + materialName = "_mat_" + std::to_string(matCount); } else { materialName = name.C_Str(); } - // TODO: Add support for non-image path values and binary gltf - - TextureSampler sampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, - TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); - sampler.setAnisotropy(8.0f); - std::string dirName = file.getParent(); - std::cout << "directory: " << dirName << std::endl; + TextureSampler defaultSampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, + TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); if (outMaterials.find(materialName) == outMaterials.end()) { - outMaterials[materialName] = mGltfMaterial->createInstance(); + bool materialIsDoubleSided = false; + material->Get("$mat.twosided", 0, 0, materialIsDoubleSided); + + bool materialIsUnlit = false; + material->Get("$mat.gltf.unlit", 0, 0, materialIsUnlit); + + aiString alphaMode; + + if (materialIsUnlit) { + if (materialIsDoubleSided){ + outMaterials[materialName] = mGltfMaterialDSUnlit->createInstance(); + } else { + outMaterials[materialName] = mGltfMaterialUnlit->createInstance(); + } + } else if (materialIsDoubleSided) { + material->Get("$mat.gltf.alphaMode", 0, 0, alphaMode); + + if (strcmp(alphaMode.C_Str(), "BLEND") == 0) { + outMaterials[materialName] = mGltfMaterialDSTrans->createInstance(); + } else if (strcmp(alphaMode.C_Str(), "MASK") == 0) { + outMaterials[materialName] = mGltfMaterialDSMasked->createInstance(); + float maskThreshold = 0.5; + material->Get("$mat.gltf.alphaCutoff", 0, 0, maskThreshold); + outMaterials[materialName]->setParameter("maskThreshold", maskThreshold); + } else { + outMaterials[materialName] = mGltfMaterialDS->createInstance(); + } + } else { + material->Get("$mat.gltf.alphaMode", 0, 0, alphaMode); + + if (strcmp(alphaMode.C_Str(), "BLEND") == 0) { + outMaterials[materialName] = mGltfMaterialTrans->createInstance(); + } else if (strcmp(alphaMode.C_Str(), "MASK") == 0) { + outMaterials[materialName] = mGltfMaterialMasked->createInstance(); + float maskThreshold = 0.5; + material->Get("$mat.gltf.alphaCutoff", 0, 0, maskThreshold); + outMaterials[materialName]->setParameter("maskThreshold", maskThreshold); + } else { + outMaterials[materialName] = mGltfMaterial->createInstance(); + } + } // Load property values for gltf files aiColor4D baseColorFactor; @@ -449,102 +689,65 @@ bool MeshAssimp::setFromFile(const Path& file, float metallicFactor = 1.0; float roughnessFactor = 1.0; -// if(material->Get("$mat.gltf.occlusionTexture.strength", 0, 0, occlusionStrength) == AI_SUCCESS){ -// std::cout << "hey" << std::endl; -// } + //TODO: is occlusion strength available on Assimp now? // Load texture images for gltf files - if (material->GetTexture(aiTextureType_DIFFUSE, 1, &baseColorPath) == AI_SUCCESS) { - Texture* baseColorMap = nullptr; - loadTex(&mEngine, dirName + baseColorPath.C_Str(), &baseColorMap); - mTextures.push_back(baseColorMap); - if (baseColorMap != nullptr) { - outMaterials[materialName]->setParameter( - "baseColorMap", baseColorMap, sampler); - } - std::cout << dirName + baseColorPath.C_Str() << std::endl; + if (material->GetTexture(aiTextureType_DIFFUSE, 1, &baseColorPath, nullptr, nullptr, + nullptr, nullptr, mapMode) == AI_SUCCESS) { + setTextureFromPath(scene, &mEngine, mTextures, baseColorPath, materialName, dirName, mapMode, "baseColorMap", outMaterials); } else { - if (mDefaultMap == nullptr){ - std::cout << "default mat is null" << std::endl; - } - outMaterials[materialName]->setParameter("baseColorMap", mDefaultMap, sampler); + outMaterials[materialName]->setParameter("baseColorMap", mDefaultMap, defaultSampler); } - if (material->GetTexture(aiTextureType_UNKNOWN, 0, &MRPath) == AI_SUCCESS) { - Texture* metallicRoughnessMap = nullptr; - loadTex(&mEngine, dirName + MRPath.C_Str(), &metallicRoughnessMap, false); - mTextures.push_back(metallicRoughnessMap); + if (material->GetTexture(aiTextureType_UNKNOWN, 0, &MRPath, nullptr, nullptr, + nullptr, nullptr, mapMode) == AI_SUCCESS) { + setTextureFromPath(scene, &mEngine, mTextures, MRPath, materialName, dirName, mapMode, "metallicRoughnessMap", outMaterials); - if (metallicRoughnessMap != nullptr) { - outMaterials[materialName]->setParameter( - "metallicRoughnessMap", metallicRoughnessMap, sampler); - } - std::cout << dirName + MRPath.C_Str() << std::endl; } else { - outMaterials[materialName]->setParameter("metallicRoughnessMap", mDefaultMap, sampler); + outMaterials[materialName]->setParameter("metallicRoughnessMap", mDefaultMap, defaultSampler); outMaterials[materialName]->setParameter("metallicFactor", mDefaultMetallic); outMaterials[materialName]->setParameter("roughnessFactor", mDefaultRoughness); } - if (material->GetTexture(aiTextureType_LIGHTMAP, 0, &AOPath) == AI_SUCCESS) { - Texture* aoMap = nullptr; - loadTex(&mEngine, dirName + AOPath.C_Str(), &aoMap, false); - mTextures.push_back(aoMap); + if (material->GetTexture(aiTextureType_LIGHTMAP, 0, &AOPath, nullptr, nullptr, + nullptr, nullptr, mapMode) == AI_SUCCESS) { + setTextureFromPath(scene, &mEngine, mTextures, AOPath, materialName, dirName, mapMode, "aoMap", outMaterials); - if (aoMap != nullptr) { - outMaterials[materialName]->setParameter( - "aoMap", aoMap, sampler); - } - std::cout << dirName + AOPath.C_Str() << std::endl; } else { - outMaterials[materialName]->setParameter("aoMap", mDefaultMap, sampler); + outMaterials[materialName]->setParameter("aoMap", mDefaultMap, defaultSampler); } - if (material->GetTexture(aiTextureType_NORMALS, 0, &normalPath) == AI_SUCCESS) { - Texture* normalMap = nullptr; - loadTex(&mEngine, dirName + normalPath.C_Str(), &normalMap, false); - mTextures.push_back(normalMap); - - if (normalMap != nullptr) { - outMaterials[materialName]->setParameter( - "normalMap", normalMap, sampler); - } - std::cout << dirName + normalPath.C_Str() << std::endl; + if (material->GetTexture(aiTextureType_NORMALS, 0, &normalPath, nullptr, nullptr, + nullptr, nullptr, mapMode) == AI_SUCCESS) { + setTextureFromPath(scene, &mEngine, mTextures, normalPath, materialName, dirName, mapMode, "normalMap", outMaterials); } else { - outMaterials[materialName]->setParameter("normalMap", mDefaultNormalMap, sampler); + outMaterials[materialName]->setParameter("normalMap", mDefaultNormalMap, defaultSampler); } - if (material->GetTexture(aiTextureType_EMISSIVE, 0, &emissivePath) == AI_SUCCESS) { - Texture* emissiveMap = nullptr; - loadTex(&mEngine, dirName + emissivePath.C_Str(), &emissiveMap, false); - mTextures.push_back(emissiveMap); + if (material->GetTexture(aiTextureType_EMISSIVE, 0, &emissivePath, nullptr, nullptr, + nullptr, nullptr, mapMode) == AI_SUCCESS) { + setTextureFromPath(scene, &mEngine, mTextures, emissivePath, materialName, dirName, mapMode, "emissiveMap", outMaterials); - if (emissiveMap != nullptr) { - outMaterials[materialName]->setParameter( - "emissiveMap", emissiveMap, sampler); - } - std::cout << dirName + emissivePath.C_Str() << std::endl; } else { - outMaterials[materialName]->setParameter("emissiveMap", mDefaultMap, sampler); + outMaterials[materialName]->setParameter("emissiveMap", mDefaultMap, defaultSampler); outMaterials[materialName]->setParameter("emissiveFactor", mDefaultEmissive); } //If the gltf has texture factors, override the default factor values - if(material->Get("$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, metallicFactor) == AI_SUCCESS){ + if(material->Get("$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, metallicFactor) == AI_SUCCESS) { outMaterials[materialName]->setParameter("metallicFactor", metallicFactor); } - if (material->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, roughnessFactor) == AI_SUCCESS){ + if (material->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, roughnessFactor) == AI_SUCCESS) { outMaterials[materialName]->setParameter("roughnessFactor", roughnessFactor); } - if(material->Get(AI_MATKEY_COLOR_EMISSIVE, emissiveFactor) == AI_SUCCESS){ + if(material->Get(AI_MATKEY_COLOR_EMISSIVE, emissiveFactor) == AI_SUCCESS) { emissiveFactorCast = *reinterpret_cast(&emissiveFactor); outMaterials[materialName]->setParameter("emissiveFactor", emissiveFactorCast); } - if(material->Get("$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0, baseColorFactor) == AI_SUCCESS){ + if(material->Get("$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0, baseColorFactor) == AI_SUCCESS) { baseColorFactorCast = *reinterpret_cast(&baseColorFactor); outMaterials[materialName]->setParameter("baseColorFactor", baseColorFactorCast); } - } aiColor3D color; @@ -600,8 +803,6 @@ bool MeshAssimp::setFromFile(const Path& file, parentIndex = static_cast(outMeshes.size()) - 1; deep++; depth = std::max(deep, depth); - // std::cout << depth << ": num children = " << node->mNumChildren - // << ", parent = " << parentIndex << std::endl; for (size_t i = 0, c = node->mNumChildren; i < c; i++) { processNode(node->mChildren[i], parentIndex); } @@ -626,16 +827,55 @@ bool MeshAssimp::setFromFile(const Path& file, std::cout << "Hierarchy depth = " << depth << std::endl; - // compute the aabb + // compute the aabb and find bounding box of entire model for (auto& mesh : outMeshes) { mesh.aabb = RenderableManager::computeAABB( outPositions.data(), outIndices.data() + mesh.offset, mesh.count); - } + Box transformedAabb = computeTransformedAABB( + outPositions.data(), + outIndices.data() + mesh.offset, + mesh.count, + mesh.accTransform); + + float3 aabbMin = transformedAabb.getMin(); + float3 aabbMax = transformedAabb.getMax(); + + if (!isinf(aabbMin.x) && !isinf(aabbMax.x)) { + if (minBound.x > maxBound.x) { + minBound.x = aabbMin.x; + maxBound.x = aabbMax.x; + } else { + minBound.x = fmin(minBound.x, aabbMin.x); + maxBound.x = fmax(maxBound.x, aabbMax.x); + } + } + + if (!isinf(aabbMin.y) && !isinf(aabbMax.y)) { + if (minBound.y > maxBound.y) { + minBound.y = aabbMin.y; + maxBound.y = aabbMax.y; + } else { + minBound.y = fmin(minBound.y, aabbMin.y); + maxBound.y = fmax(maxBound.y, aabbMax.y); + } + } + + if (!isinf(aabbMin.z) && !isinf(aabbMax.z)) { + if (minBound.z > maxBound.z) { + minBound.z = aabbMin.z; + maxBound.z = aabbMax.z; + } else { + minBound.z = fmin(minBound.z, aabbMin.z); + maxBound.z = fmax(maxBound.z, aabbMax.z); + } + } + } return true; } - return false; } + + diff --git a/samples/app/MeshAssimp.h b/samples/app/MeshAssimp.h index f8896bc23a..0ee01d492b 100644 --- a/samples/app/MeshAssimp.h +++ b/samples/app/MeshAssimp.h @@ -29,6 +29,7 @@ namespace filament { #include #include +#include #include #include #include @@ -40,6 +41,8 @@ namespace filament { #include #include #include +#include +#include class MeshAssimp { public: @@ -58,6 +61,11 @@ public: return mRenderables; } + //For use with normalizing coordinates + math::float3 minBound = math::float3(1.0f); + math::float3 maxBound = math::float3(-1.0f); + utils::Entity rootEntity; + private: struct Part { size_t offset; @@ -76,6 +84,7 @@ private: std::vector parts; filament::Box aabb; mat4f transform; + mat4f accTransform; }; bool setFromFile(const utils::Path& file, @@ -88,22 +97,28 @@ private: std::map& outMaterials ); - + filament::Texture* createOneByOneTexture(uint32_t textureData); filament::Engine& mEngine; filament::VertexBuffer* mVertexBuffer = nullptr; filament::IndexBuffer* mIndexBuffer = nullptr; filament::Material* mDefaultColorMaterial = nullptr; filament::Material* mDefaultTransparentColorMaterial = nullptr; - filament::Material* mGltfMaterial = nullptr; + filament::Material* mGltfMaterial = nullptr; // Single sided gltf material + filament::Material* mGltfMaterialDS = nullptr; // Double sided gltf material + filament::Material* mGltfMaterialTrans = nullptr; // Transparent gltf material + filament::Material* mGltfMaterialDSTrans = nullptr; // Double sided Transparent gltf material + filament::Material* mGltfMaterialMasked = nullptr; // Transparent gltf material + filament::Material* mGltfMaterialDSMasked = nullptr; // Double sided Transparent gltf material + filament::Material* mGltfMaterialUnlit = nullptr; + filament::Material* mGltfMaterialDSUnlit = nullptr; filament::Texture* mDefaultMap = nullptr; filament::Texture* mDefaultNormalMap = nullptr; float mDefaultMetallic = 0.0; float mDefaultRoughness = 0.4; filament::sRGBColor mDefaultEmissive = filament::sRGBColor({0.0f, 0.0f, 0.0f}); - std::vector mRenderables; std::vector mTextures; diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp index 791fb6599c..a09251e580 100644 --- a/samples/gltf_viewer.cpp +++ b/samples/gltf_viewer.cpp @@ -14,14 +14,9 @@ * limitations under the License. */ -#include -#include -#include -#include - -#include - -#include +#include "app/Config.h" +#include "app/FilamentApp.h" +#include "app/MeshAssimp.h" #include #include @@ -33,19 +28,21 @@ #include #include +#include +#include + #include #include #include -#include "app/Config.h" -#include "app/FilamentApp.h" -#include "app/MeshAssimp.h" +#include #include -#include - -#include +#include +#include +#include +#include using namespace math; using namespace filament; @@ -58,25 +55,14 @@ static std::map g_materialInstances; static std::unique_ptr g_meshSet; static const Material* g_material; static Entity g_light; -static Texture* g_metallicMap = nullptr; -static Texture* g_roughnessMap = nullptr; -static Texture* g_aoMap = nullptr; -static Texture* g_normalMap = nullptr; -static Texture* g_baseColorMap = nullptr; static Config g_config; -static struct PbrConfig { - std::string materialDir; - bool clearCoat = false; - bool anisotropy = false; -} g_pbrConfig; static void printUsage(char* name) { - std::string exec_name(Path(name).getName()); std::string usage( - "SAMPLE_PBR is an example of loading PBR assets with base color + packed metallic/roughness\n" + "gltf_viewer displays gltf models using the filament renderer\n" "Usage:\n" - " SAMPLE_PBR [options] \n" + " gltf_viewer [options] \n" "Options:\n" " --help, -h\n" " Prints this message\n\n" @@ -84,38 +70,16 @@ static void printUsage(char* name) { " Applies an IBL generated by cmgen's deploy option\n\n" " --split-view, -v\n" " Splits the window into 4 views\n\n" - " --scale=[number], -s [number]\n" - " Applies uniform scale\n\n" - " --material=, -m \n" - " Directory containing the textures named _*.png where * is:\n" - " - AO\n" - " - Color\n" - " - Metallic\n" - " - Normal\n" - " - Roughness\n" - "\n" - " --clear-coat, -c\n" - " Add a clear coat layer to the material\n\n" - " --anisotropy, -a\n" - " Enable anisotropy on the material\n\n" ); - const std::string from("SAMPLE_PBR"); - for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) { - usage.replace(pos, from.length(), exec_name); - } std::cout << usage; } static int handleCommandLineArgments(int argc, char* argv[], Config* config) { - static constexpr const char* OPTSTR = "hi:vs:m:ca"; + static constexpr const char* OPTSTR = "hi:v"; static const struct option OPTIONS[] = { { "help", no_argument, nullptr, 'h' }, { "ibl", required_argument, nullptr, 'i' }, { "split-view", no_argument, nullptr, 'v' }, - { "scale", required_argument, nullptr, 's' }, - { "material", required_argument, nullptr, 'm' }, - { "clear-coat", no_argument, nullptr, 'c' }, - { "anisotropy", no_argument, nullptr, 'a' }, { 0, 0, 0, 0 } // termination of the option list }; int opt; @@ -130,27 +94,9 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) { case 'i': config->iblDirectory = arg; break; - case 's': - try { - config->scale = std::stof(arg); - } catch (std::invalid_argument& e) { - // keep scale of 1.0 - } catch (std::out_of_range& e) { - // keep scale of 1.0 - } - break; case 'v': config->splitView = true; break; - case 'm': - g_pbrConfig.materialDir = arg; - break; - case 'c': - g_pbrConfig.clearCoat = true; - break; - case 'a': - g_pbrConfig.anisotropy = true; - break; } } @@ -164,11 +110,6 @@ static void cleanup(Engine* engine, View* view, Scene* scene) { } g_meshSet.reset(nullptr); engine->destroy(g_material); - engine->destroy(g_baseColorMap); - engine->destroy(g_metallicMap); - engine->destroy(g_roughnessMap); - engine->destroy(g_aoMap); - engine->destroy(g_normalMap); EntityManager& em = EntityManager::get(); engine->destroy(g_light); @@ -176,9 +117,6 @@ static void cleanup(Engine* engine, View* view, Scene* scene) { } static void setup(Engine* engine, View* view, Scene* scene) { - Path path(g_pbrConfig.materialDir); - std::string name(path.getName()); - g_meshSet = std::make_unique(*engine); for (auto& filename : g_filenames) { g_meshSet->addFromFile(filename, g_materialInstances, false); @@ -186,11 +124,21 @@ static void setup(Engine* engine, View* view, Scene* scene) { auto& rcm = engine->getRenderableManager(); auto& tcm = engine->getTransformManager(); + + // Compute the scale required to fit the model's bounding box into [-1, 1] + float maxExtent = 0; + maxExtent = std::max(g_meshSet->maxBound.x - g_meshSet->minBound.x, g_meshSet->maxBound.y - g_meshSet->minBound.y); + maxExtent = std::max(maxExtent, g_meshSet->maxBound.z - g_meshSet->minBound.z); + float scaleFactor = 2.0f / maxExtent; + + float3 center = -1 * (g_meshSet->maxBound + g_meshSet->minBound) / 2.0f; + center.z -= 4.0f / scaleFactor; + + auto rooti = tcm.getInstance(g_meshSet->rootEntity); + tcm.setTransform(rooti, mat4f::scale(float3(scaleFactor)) * mat4f::translate(center)); + for (auto renderable : g_meshSet->getRenderables()) { if (rcm.hasComponent(renderable)) { - auto ti = tcm.getInstance(renderable); - tcm.setTransform(ti, mat4f{ mat3f(g_config.scale), float3(0.0f, 0.0f, -4.0f) } * - tcm.getWorldTransform(ti)); scene->addEntity(renderable); } } @@ -221,7 +169,6 @@ int main(int argc, char* argv[]) { g_filenames.push_back(filename); } - g_config.title = "gltf_viewer"; FilamentApp& filamentApp = FilamentApp::get(); filamentApp.run(g_config, setup, cleanup); diff --git a/samples/materials/gltf2.mat b/samples/materials/gltf2.mat index e3125147cf..531fe32eae 100644 --- a/samples/materials/gltf2.mat +++ b/samples/materials/gltf2.mat @@ -53,33 +53,18 @@ material { } fragment { -// void material(inout MaterialInputs material) { -// material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; -// prepareMaterial(material); -// material.baseColor = texture(materialParams_baseColorMap, getUV0()); -// material.roughness = texture(materialParams_metallicRoughnessMap, getUV0()).g; -// material.metallic = texture(materialParams_metallicRoughnessMap, getUV0()).b; -// material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; -// } + void material(inout MaterialInputs material) { + material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; + material.normal.y = -material.normal.y; + prepareMaterial(material); -void material(inout MaterialInputs material) { - material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; - prepareMaterial(material); -// material.baseColor.rgb = float3(1.0, 0.75, 0.94); -// material.metallic = 0.0; -// material.roughness = 1.0; -// material.ambientOcclusion = 1.0; - material.baseColor = texture(materialParams_baseColorMap, getUV0()); - material.baseColor.r *= materialParams.baseColorFactor[0]; - material.baseColor.g *= materialParams.baseColorFactor[1]; - material.baseColor.b *= materialParams.baseColorFactor[2]; - material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; - material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; - material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; - material.emissive = texture(materialParams_emissiveMap, getUV0()); - material.emissive.r *= materialParams.emissiveFactor[0]; - material.emissive.g *= materialParams.emissiveFactor[1]; - material.emissive.b *= materialParams.emissiveFactor[2]; + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; -} + material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; + material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; + material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; + material.emissive = texture(materialParams_emissiveMap, getUV0()); + material.emissive.rgb *= materialParams.emissiveFactor.rgb; + } } \ No newline at end of file diff --git a/samples/materials/gltf2DoubleSided.mat b/samples/materials/gltf2DoubleSided.mat new file mode 100644 index 0000000000..a974508dad --- /dev/null +++ b/samples/materials/gltf2DoubleSided.mat @@ -0,0 +1,71 @@ +material { + name : Lit, + requires : [ + uv0 + ], + doubleSided : true, + shadingModel : lit, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; + material.normal.y = -material.normal.y; + prepareMaterial(material); + + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + + material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; + material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; + material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; + material.emissive = texture(materialParams_emissiveMap, getUV0()); + material.emissive.rgb *= materialParams.emissiveFactor.rgb; + } +} \ No newline at end of file diff --git a/samples/materials/gltf2DoubleSidedMasked.mat b/samples/materials/gltf2DoubleSidedMasked.mat new file mode 100644 index 0000000000..117117525f --- /dev/null +++ b/samples/materials/gltf2DoubleSidedMasked.mat @@ -0,0 +1,74 @@ +material { + name : Lit, + requires : [ + uv0 + ], + shadingModel : lit, + doubleSided : true, + blending : masked, + maskThreshold : 0.5, + transparency : default, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; + material.normal.y = -material.normal.y; + prepareMaterial(material); + + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + + material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; + material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; + material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; + material.emissive = texture(materialParams_emissiveMap, getUV0()); + material.emissive.rgb *= materialParams.emissiveFactor.rgb; + } +} \ No newline at end of file diff --git a/samples/materials/gltf2DoubleSidedTrans.mat b/samples/materials/gltf2DoubleSidedTrans.mat new file mode 100644 index 0000000000..8ab6932f1a --- /dev/null +++ b/samples/materials/gltf2DoubleSidedTrans.mat @@ -0,0 +1,74 @@ +material { + name : Lit, + requires : [ + uv0 + ], + shadingModel : lit, + doubleSided : true, + blending : transparent, + transparency : default, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; + material.normal.y = -material.normal.y; + prepareMaterial(material); + + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + material.baseColor.rgb *= material.baseColor.a; + + material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; + material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; + material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; + material.emissive = texture(materialParams_emissiveMap, getUV0()); + material.emissive.rgb *= materialParams.emissiveFactor.rgb; + } +} \ No newline at end of file diff --git a/samples/materials/gltf2DoubleSidedUnlit.mat b/samples/materials/gltf2DoubleSidedUnlit.mat new file mode 100644 index 0000000000..ba17ea3cbf --- /dev/null +++ b/samples/materials/gltf2DoubleSidedUnlit.mat @@ -0,0 +1,62 @@ +material { + name : Unlit, + requires : [ + uv0 + ], + doubleSided : true, + shadingModel : unlit, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + prepareMaterial(material); + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + } +} \ No newline at end of file diff --git a/samples/materials/gltf2Masked.mat b/samples/materials/gltf2Masked.mat new file mode 100644 index 0000000000..919e4e27c4 --- /dev/null +++ b/samples/materials/gltf2Masked.mat @@ -0,0 +1,73 @@ +material { + name : Lit, + requires : [ + uv0 + ], + shadingModel : lit, + blending : masked, + maskThreshold : 0.5, + transparency : default, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; + material.normal.y = -material.normal.y; + prepareMaterial(material); + + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + + material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; + material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; + material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; + material.emissive = texture(materialParams_emissiveMap, getUV0()); + material.emissive.rgb *= materialParams.emissiveFactor.rgb; + } +} \ No newline at end of file diff --git a/samples/materials/gltf2Trans.mat b/samples/materials/gltf2Trans.mat new file mode 100644 index 0000000000..46cea2573e --- /dev/null +++ b/samples/materials/gltf2Trans.mat @@ -0,0 +1,73 @@ +material { + name : Lit, + requires : [ + uv0 + ], + shadingModel : lit, + blending : transparent, + transparency : default, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + material.normal = texture(materialParams_normalMap, getUV0()).xyz * 2.0 - 1.0; + material.normal.y = -material.normal.y; + prepareMaterial(material); + + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + material.baseColor.rgb *= material.baseColor.a; + + material.roughness = materialParams.roughnessFactor * texture(materialParams_metallicRoughnessMap, getUV0()).g; + material.metallic = materialParams.metallicFactor * texture(materialParams_metallicRoughnessMap, getUV0()).b; + material.ambientOcclusion = texture(materialParams_aoMap, getUV0()).r; + material.emissive = texture(materialParams_emissiveMap, getUV0()); + material.emissive.rgb *= materialParams.emissiveFactor.rgb; + } +} \ No newline at end of file diff --git a/samples/materials/gltf2Unlit.mat b/samples/materials/gltf2Unlit.mat new file mode 100644 index 0000000000..87cfb7ba64 --- /dev/null +++ b/samples/materials/gltf2Unlit.mat @@ -0,0 +1,61 @@ +material { + name : Unlit, + requires : [ + uv0 + ], + shadingModel : unlit, + parameters : [ + { + type : sampler2d, + name : baseColorMap + }, + { + type : float4, + name : baseColorFactor + }, + { + type : sampler2d, + name : metallicRoughnessMap + }, + { + type : float, + name : metallicFactor + }, + { + type : float, + name : roughnessFactor + }, + { + type : sampler2d, + name : normalMap + }, + { + type : float, + name : normalScale + }, + { + type : sampler2d, + name : aoMap + }, + { + type : float, + name : aoStrength + }, + { + type : sampler2d, + name : emissiveMap + }, + { + type : float3, + name : emissiveFactor + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + prepareMaterial(material); + material.baseColor = texture(materialParams_baseColorMap, getUV0()); + material.baseColor.rgb *= materialParams.baseColorFactor.xyz; + } +} \ No newline at end of file diff --git a/samples/sample_full_pbr.cpp b/samples/sample_full_pbr.cpp index b0c94fe103..1a16c52c97 100644 --- a/samples/sample_full_pbr.cpp +++ b/samples/sample_full_pbr.cpp @@ -14,14 +14,9 @@ * limitations under the License. */ -#include -#include -#include -#include - -#include - -#include +#include "app/Config.h" +#include "app/FilamentApp.h" +#include "app/MeshAssimp.h" #include #include @@ -32,19 +27,23 @@ #include #include +#include + +#include +#include + #include #include #include -#include "app/Config.h" -#include "app/FilamentApp.h" -#include "app/MeshAssimp.h" +#include #include -#include - -#include +#include +#include +#include +#include using namespace math; using namespace filament;