summaryrefslogtreecommitdiff
path: root/indra/newview/gltf
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2024-05-29 16:56:39 -0500
committerGitHub <noreply@github.com>2024-05-29 16:56:39 -0500
commit15fd13f83036ff781160957a21bb2d59771044bc (patch)
tree984601482bc6d7384796123bce39b7e50074ec5a /indra/newview/gltf
parent2d0fe5ca7bf3bda62bf10a37a65f5859e6d1b095 (diff)
#1530 Increase joint limit for GLTF Assets (#1582)
* Migrate GLTF scene rendering to its own shaders * Add support for ambient occlusion map separate from metallic roughness map (or absent) * Use UBO's for GLTF joints * Better error handling of downloading GLTF assets
Diffstat (limited to 'indra/newview/gltf')
-rw-r--r--indra/newview/gltf/accessor.cpp8
-rw-r--r--indra/newview/gltf/animation.cpp66
-rw-r--r--indra/newview/gltf/asset.cpp229
-rw-r--r--indra/newview/gltf/asset.h12
-rw-r--r--indra/newview/gltf/common.h16
5 files changed, 101 insertions, 230 deletions
diff --git a/indra/newview/gltf/accessor.cpp b/indra/newview/gltf/accessor.cpp
index 0619c617e2..5f4e3ca3a8 100644
--- a/indra/newview/gltf/accessor.cpp
+++ b/indra/newview/gltf/accessor.cpp
@@ -132,7 +132,13 @@ bool Buffer::prep(Asset& asset)
{ // loaded from an asset, fetch the buffer data from the asset store
LLFileSystem file(id, LLAssetType::AT_GLTF_BIN, LLFileSystem::READ);
- mData.resize(file.getSize());
+ if (mByteLength > file.getSize())
+ {
+ LL_WARNS("GLTF") << "Unexpected glbin size: " << id << " is " << file.getSize() << " bytes, expected " << mByteLength << LL_ENDL;
+ return false;
+ }
+
+ mData.resize(mByteLength);
if (!file.read((U8*)mData.data(), mData.size()))
{
LL_WARNS("GLTF") << "Failed to load buffer data from asset: " << id << LL_ENDL;
diff --git a/indra/newview/gltf/animation.cpp b/indra/newview/gltf/animation.cpp
index f18bba788c..45e9e1ddef 100644
--- a/indra/newview/gltf/animation.cpp
+++ b/indra/newview/gltf/animation.cpp
@@ -28,6 +28,7 @@
#include "asset.h"
#include "buffer_util.h"
+#include "../llskinningutil.h"
using namespace LL::GLTF;
using namespace boost::json;
@@ -362,6 +363,71 @@ const Animation& Animation::operator=(const Value& src)
return *this;
}
+Skin::~Skin()
+{
+ if (mUBO)
+ {
+ glDeleteBuffers(1, &mUBO);
+ }
+}
+
+void Skin::uploadMatrixPalette(Asset& asset)
+{
+ // prepare matrix palette
+
+ U32 max_joints = LLSkinningUtil::getMaxGLTFJointCount();
+
+ if (mUBO == 0)
+ {
+ glGenBuffers(1, &mUBO);
+ }
+
+ U32 joint_count = llmin(max_joints, mJoints.size());
+
+ std::vector<mat4> t_mp;
+
+ t_mp.resize(joint_count);
+
+ for (U32 i = 0; i < joint_count; ++i)
+ {
+ Node& joint = asset.mNodes[mJoints[i]];
+ // build matrix palette in asset space
+ t_mp[i] = joint.mAssetMatrix * mInverseBindMatricesData[i];
+ }
+
+ std::vector<F32> glmp;
+
+ glmp.resize(joint_count * 12);
+
+ F32* mp = glmp.data();
+
+ for (U32 i = 0; i < joint_count; ++i)
+ {
+ F32* m = glm::value_ptr(t_mp[i]);
+
+ U32 idx = i * 12;
+
+ mp[idx + 0] = m[0];
+ mp[idx + 1] = m[1];
+ mp[idx + 2] = m[2];
+ mp[idx + 3] = m[12];
+
+ mp[idx + 4] = m[4];
+ mp[idx + 5] = m[5];
+ mp[idx + 6] = m[6];
+ mp[idx + 7] = m[13];
+
+ mp[idx + 8] = m[8];
+ mp[idx + 9] = m[9];
+ mp[idx + 10] = m[10];
+ mp[idx + 11] = m[14];
+ }
+
+ glBindBuffer(GL_UNIFORM_BUFFER, mUBO);
+ glBufferData(GL_UNIFORM_BUFFER, glmp.size() * sizeof(F32), glmp.data(), GL_STREAM_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
bool Skin::prep(Asset& asset)
{
if (mInverseBindMatrices != INVALID_INDEX)
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp
index 485984fac1..7870eb28b0 100644
--- a/indra/newview/gltf/asset.cpp
+++ b/indra/newview/gltf/asset.cpp
@@ -84,7 +84,7 @@ namespace LL
void Scene::updateTransforms(Asset& asset)
{
mat4 identity = glm::identity<mat4>();
-
+
for (auto& nodeIndex : mNodes)
{
Node& node = asset.mNodes[nodeIndex];
@@ -116,7 +116,7 @@ void Node::updateTransforms(Asset& asset, const mat4& parentMatrix)
{
makeMatrixValid();
mAssetMatrix = parentMatrix * mMatrix;
-
+
mAssetMatrixInv = glm::inverse(mAssetMatrix);
S32 my_index = this - &asset.mNodes[0];
@@ -356,94 +356,6 @@ const Image& Image::operator=(const Value& src)
return *this;
}
-void Asset::render(bool opaque, bool rigged)
-{
- if (rigged)
- {
- gGL.loadIdentity();
- }
-
- for (auto& node : mNodes)
- {
- if (node.mSkin != INVALID_INDEX)
- {
- if (rigged)
- {
- Skin& skin = mSkins[node.mSkin];
- skin.uploadMatrixPalette(*this, node);
- }
- else
- {
- //skip static nodes if we're rendering rigged
- continue;
- }
- }
- else if (rigged)
- {
- // skip rigged nodes if we're not rendering rigged
- continue;
- }
-
- if (node.mMesh != INVALID_INDEX)
- {
- Mesh& mesh = mMeshes[node.mMesh];
- for (auto& primitive : mesh.mPrimitives)
- {
- if (!rigged)
- {
- gGL.loadMatrix((F32*)glm::value_ptr(node.mRenderMatrix));
- }
- bool cull = true;
- if (primitive.mMaterial != INVALID_INDEX)
- {
- Material& material = mMaterials[primitive.mMaterial];
- bool mat_opaque = material.mAlphaMode != Material::AlphaMode::BLEND;
-
- if (mat_opaque != opaque)
- {
- continue;
- }
-
- material.bind(*this);
-
- cull = !material.mDoubleSided;
- }
- else
- {
- if (!opaque)
- {
- continue;
- }
- LLFetchedGLTFMaterial::sDefault.bind();
- }
-
- LLGLDisable cull_face(!cull ? GL_CULL_FACE : 0);
-
- primitive.mVertexBuffer->setBuffer();
- if (primitive.mVertexBuffer->getNumIndices() > 0)
- {
- primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0);
- }
- else
- {
- primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts());
- }
-
- }
- }
- }
-}
-
-void Asset::renderOpaque()
-{
- render(true);
-}
-
-void Asset::renderTransparent()
-{
- render(false);
-}
-
void Asset::update()
{
F32 dt = gFrameTimeSeconds - mLastUpdateTime;
@@ -461,6 +373,11 @@ void Asset::update()
}
updateTransforms();
+
+ for (auto& skin : mSkins)
+ {
+ skin.uploadMatrixPalette(*this);
+ }
}
}
@@ -1063,90 +980,6 @@ bool Material::PbrMetallicRoughness::operator!=(const Material::PbrMetallicRough
return !(*this == rhs);
}
-static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info, LLViewerTexture* fallback)
-{
- if (info.mIndex != INVALID_INDEX)
- {
- LLViewerTexture* tex = asset.mImages[asset.mTextures[info.mIndex].mSource].mTexture;
- if (tex)
- {
- tex->addTextureStats(2048.f * 2048.f);
- LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex);
- }
- else
- {
- LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, fallback);
- }
- }
- else
- {
- LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, fallback);
- }
-}
-
-void Material::bind(Asset& asset)
-{
- // bind for rendering (derived from LLFetchedGLTFMaterial::bind)
- // glTF 2.0 Specification 3.9.4. Alpha Coverage
- // mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK
- F32 min_alpha = -1.0;
-
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
-
- if (!LLPipeline::sShadowRender || (mAlphaMode == Material::AlphaMode::BLEND))
- {
- if (mAlphaMode == Material::AlphaMode::MASK)
- {
- // dividing the alpha cutoff by transparency here allows the shader to compare against
- // the alpha value of the texture without needing the transparency value
- if (mPbrMetallicRoughness.mBaseColorFactor.a > 0.f)
- {
- min_alpha = mAlphaCutoff / mPbrMetallicRoughness.mBaseColorFactor.a;
- }
- else
- {
- min_alpha = 1024.f;
- }
- }
- shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha);
- }
-
- bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep);
-
- F32 base_color_packed[8];
- //mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
- LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
- shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed);
-
- if (!LLPipeline::sShadowRender)
- {
- bindTexture(asset, LLShaderMgr::BUMP_MAP, mNormalTexture, LLViewerFetchedTexture::sFlatNormalImagep);
- bindTexture(asset, LLShaderMgr::SPECULAR_MAP, mPbrMetallicRoughness.mMetallicRoughnessTexture, LLViewerFetchedTexture::sWhiteImagep);
- bindTexture(asset, LLShaderMgr::EMISSIVE_MAP, mEmissiveTexture, LLViewerFetchedTexture::sWhiteImagep);
-
- // NOTE: base color factor is baked into vertex stream
-
- shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mPbrMetallicRoughness.mRoughnessFactor);
- shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mPbrMetallicRoughness.mMetallicFactor);
- shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(mEmissiveFactor));
-
- F32 normal_packed[8];
- //mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
- LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
- shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed);
-
- F32 metallic_roughness_packed[8];
- //mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
- LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
- shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed);
-
- F32 emissive_packed[8];
- //mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
- LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
- shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, (F32*)emissive_packed);
- }
-}
-
void Material::serialize(object& dst) const
{
write(mName, "name", dst);
@@ -1264,52 +1097,4 @@ const Sampler& Sampler::operator=(const Value& src)
return *this;
}
-void Skin::uploadMatrixPalette(Asset& asset, Node& node)
-{
- // prepare matrix palette
-
- // modelview will be applied by the shader, so assume matrix palette is in asset space
- std::vector<mat4> t_mp;
-
- t_mp.resize(mJoints.size());
-
- for (U32 i = 0; i < mJoints.size(); ++i)
- {
- Node& joint = asset.mNodes[mJoints[i]];
- t_mp[i] = joint.mRenderMatrix * mInverseBindMatricesData[i];
- }
-
- std::vector<F32> glmp;
-
- glmp.resize(mJoints.size() * 12);
-
- F32* mp = glmp.data();
-
- for (U32 i = 0; i < mJoints.size(); ++i)
- {
- F32* m = glm::value_ptr(t_mp[i]);
-
- U32 idx = i * 12;
-
- mp[idx + 0] = m[0];
- mp[idx + 1] = m[1];
- mp[idx + 2] = m[2];
- mp[idx + 3] = m[12];
-
- mp[idx + 4] = m[4];
- mp[idx + 5] = m[5];
- mp[idx + 6] = m[6];
- mp[idx + 7] = m[13];
-
- mp[idx + 8] = m[8];
- mp[idx + 9] = m[9];
- mp[idx + 10] = m[10];
- mp[idx + 11] = m[14];
- }
-
- LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
- mJoints.size(),
- GL_FALSE,
- (GLfloat*)glmp.data());
-}
diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h
index 761e746aa1..022fc484c2 100644
--- a/indra/newview/gltf/asset.h
+++ b/indra/newview/gltf/asset.h
@@ -118,8 +118,6 @@ namespace LL
F32 mAlphaCutoff = 0.5f;
bool mDoubleSided = false;
- // bind for rendering
- void bind(Asset& asset);
const Material& operator=(const Value& src);
void serialize(boost::json::object& dst) const;
};
@@ -197,14 +195,18 @@ namespace LL
class Skin
{
public:
+ ~Skin();
+
S32 mInverseBindMatrices = INVALID_INDEX;
S32 mSkeleton = INVALID_INDEX;
+
+ U32 mUBO = 0;
std::vector<S32> mJoints;
std::string mName;
std::vector<mat4> mInverseBindMatricesData;
bool prep(Asset& asset);
- void uploadMatrixPalette(Asset& asset, Node& node);
+ void uploadMatrixPalette(Asset& asset);
const Skin& operator=(const Value& src);
void serialize(boost::json::object& dst) const;
@@ -332,10 +334,6 @@ namespace LL
// update node render transforms
void updateRenderTransforms(const mat4& modelview);
- void render(bool opaque, bool rigged = false);
- void renderOpaque();
- void renderTransparent();
-
// return the index of the node that the line segment intersects with, or -1 if no hit
// input and output values must be in this asset's local coordinate frame
S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
diff --git a/indra/newview/gltf/common.h b/indra/newview/gltf/common.h
index 59f2ba38db..4f660d7cfc 100644
--- a/indra/newview/gltf/common.h
+++ b/indra/newview/gltf/common.h
@@ -36,6 +36,7 @@
#include "glm/ext/quaternion_float.hpp"
#include "glm/gtx/quaternion.hpp"
#include "glm/gtx/matrix_decompose.hpp"
+#include <boost/json.hpp>
// Common types and constants used in the GLTF implementation
namespace LL
@@ -62,6 +63,21 @@ namespace LL
class Asset;
+ class Material;
+ class Mesh;
+ class Node;
+ class Scene;
+ class Texture;
+ class Sampler;
+ class Image;
+ class Animation;
+ class Skin;
+ class Camera;
+ class Light;
+ class Primitive;
+ class Accessor;
+ class BufferView;
+ class Buffer;
}
}