Added support for more features in gltf_viewer sample
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
//
|
||||
// Created by Michael Wang on 10/8/18.
|
||||
//
|
||||
|
||||
#include "GltfMeshAssimp.h"
|
||||
|
||||
@@ -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
|
||||
+381
-141
@@ -17,6 +17,7 @@
|
||||
#include "MeshAssimp.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <array>
|
||||
|
||||
#include <filament/Color.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
@@ -29,6 +30,8 @@
|
||||
#include <filament/TransformManager.h>
|
||||
|
||||
#include <math/norm.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/TVecHelpers.h>
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/postprocess.h>
|
||||
@@ -37,6 +40,8 @@
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
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<filament::Texture*> textures,
|
||||
const aiString &texFile,
|
||||
const std::string &materialName,
|
||||
const std::string &texDir,
|
||||
aiTextureMapMode *mapMode,
|
||||
const char *parameterName,
|
||||
std::map<std::string, MaterialInstance *> &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<typename VECTOR, typename INDEX>
|
||||
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<float>::max());
|
||||
math::float3 bmax(std::numeric_limits<float>::lowest());
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
VECTOR const* p = reinterpret_cast<VECTOR const*>(
|
||||
(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<std::string, MaterialInstance*>& 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<unsigned char>(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<unsigned char>(128);
|
||||
defaultNormalTexData[1] = static_cast<unsigned char>(128);
|
||||
defaultNormalTexData[2] = static_cast<unsigned char>(255);
|
||||
defaultNormalTexData[3] = static_cast<unsigned char>(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<sRGBColor*>(&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<sRGBColorA*>(&baseColorFactor);
|
||||
outMaterials[materialName]->setParameter("baseColorFactor", baseColorFactorCast);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
aiColor3D color;
|
||||
@@ -600,8 +803,6 @@ bool MeshAssimp::setFromFile(const Path& file,
|
||||
parentIndex = static_cast<int>(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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace filament {
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/quat.h>
|
||||
#include <math/vec3.h>
|
||||
@@ -40,6 +41,8 @@ namespace filament {
|
||||
#include <filament/Color.h>
|
||||
#include <filament/Box.h>
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/TextureSampler.h>
|
||||
#include <filament/TransformManager.h>
|
||||
|
||||
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<Part> parts;
|
||||
filament::Box aabb;
|
||||
mat4f transform;
|
||||
mat4f accTransform;
|
||||
};
|
||||
|
||||
bool setFromFile(const utils::Path& file,
|
||||
@@ -88,22 +97,28 @@ private:
|
||||
std::map<std::string, filament::MaterialInstance*>& 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<utils::Entity> mRenderables;
|
||||
|
||||
std::vector<filament::Texture*> mTextures;
|
||||
|
||||
+27
-80
@@ -14,14 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <utils/Path.h>
|
||||
#include "app/Config.h"
|
||||
#include "app/FilamentApp.h"
|
||||
#include "app/MeshAssimp.h"
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/LightManager.h>
|
||||
@@ -33,19 +28,21 @@
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/IndirectLight.h>
|
||||
|
||||
#include <utils/Path.h>
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include "app/Config.h"
|
||||
#include "app/FilamentApp.h"
|
||||
#include "app/MeshAssimp.h"
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace math;
|
||||
using namespace filament;
|
||||
@@ -58,25 +55,14 @@ static std::map<std::string, MaterialInstance*> g_materialInstances;
|
||||
static std::unique_ptr<MeshAssimp> 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] <OBJ/FBX/COLLADA>\n"
|
||||
" gltf_viewer [options] <gltf/glb>\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=<path>, -m <path>\n"
|
||||
" Directory containing the textures named <DIR_NAME>_*.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<MeshAssimp>(*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);
|
||||
|
||||
|
||||
+12
-27
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+13
-14
@@ -14,14 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <utils/Path.h>
|
||||
#include "app/Config.h"
|
||||
#include "app/FilamentApp.h"
|
||||
#include "app/MeshAssimp.h"
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/LightManager.h>
|
||||
@@ -32,19 +27,23 @@
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Texture.h>
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
|
||||
#include <utils/Path.h>
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include "app/Config.h"
|
||||
#include "app/FilamentApp.h"
|
||||
#include "app/MeshAssimp.h"
|
||||
#include <getopt/getopt.h>
|
||||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace math;
|
||||
using namespace filament;
|
||||
|
||||
Reference in New Issue
Block a user