Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix loading lightmaps from gltf / glb meshes #630

Merged
merged 3 commits into from
Sep 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions graphics/src/AssimpLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
*/

#include <cstddef>
#include <memory>
#include <queue>
#include <string>
#include <unordered_set>
#include <vector>

#include "gz/common/graphics/Types.hh"
#include "gz/common/AssimpLoader.hh"
Expand Down Expand Up @@ -462,22 +464,50 @@ MaterialPtr AssimpLoader::Implementation::CreateMaterial(
"Roughness"));
pbr.SetRoughnessMap(texName, texData);
}
// Load lightmap only if it is not a glb/glTF mesh that contains a
// MetallicRoughness texture
// It was found that lightmap field just stores the entire MetallicRoughness
// texture. Issues were also reported in assimp:
// https://github.com/assimp/assimp/issues/3120
// https://github.com/assimp/assimp/issues/4637
unsigned int uvIdx = 0;
ret = assimpMat->GetTexture(
aiTextureType_LIGHTMAP, 0, &texturePath, NULL, &uvIdx);
if (ret == AI_SUCCESS)
}

// The lightmap / ambient occlusion texture may be the same texture as the
// metallicRoughness texture but it can also be a separate texture using a
// different uv index. In the former case, we expect the occlusion
// data to be packed in the R channel of the metallicRoughness texture,
// so load the occlusion data in the same ways as we do in the
// SplitMetallicRoughnessMap function.
// In the latter case (separate texture), no extra processing is
// required.
unsigned int uvIdx = 0;
ret = assimpMat->GetTexture(
aiTextureType_LIGHTMAP, 0, &texturePath, NULL, &uvIdx);
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Lightmap"));
// Separate uv set so treat it as a separate texture
if (uvIdx > 0)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Lightmap"));
pbr.SetLightMap(texName, uvIdx, texData);
}
// else split the occlusion data from the metallicRoughness texture
else
{
// R channel contains the occlusion data
// Note we are still creating an RGBA texture which seems watesful
// but that's what gz-rendering expects
auto origRGBAData = texData->RGBAData();
std::vector<unsigned char> texRData(origRGBAData.size());
iche033 marked this conversation as resolved.
Show resolved Hide resolved
for (unsigned int i = 0; i < origRGBAData.size(); i+=4)
{
auto r = origRGBAData.at(i);
texRData[i] = r;
texRData[i + 1] = r;
texRData[i + 2] = r;
texRData[i + 3] = 255;
}
auto tex = std::make_shared<Image>();
iche033 marked this conversation as resolved.
Show resolved Hide resolved
tex->SetFromData(&texRData[0], texData->Width(), texData->Height(),
Image::RGBA_INT8);
pbr.SetLightMap(texName, uvIdx, tex);
}
}
#endif
ret = assimpMat->GetTexture(aiTextureType_NORMALS, 0, &texturePath);
Expand Down
Loading