summaryrefslogtreecommitdiff
path: root/indra
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
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')
-rw-r--r--indra/llrender/llgl.cpp5
-rw-r--r--indra/llrender/llgl.h1
-rw-r--r--indra/llrender/llglslshader.cpp25
-rw-r--r--indra/llrender/llglslshader.h28
-rw-r--r--indra/llrender/llshadermgr.cpp4
-rw-r--r--indra/llrender/llshadermgr.h4
-rw-r--r--indra/llrender/llvertexbuffer.cpp5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl185
-rw-r--r--indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl58
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/materialF.glsl1
-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
-rw-r--r--indra/newview/gltfscenemanager.cpp201
-rw-r--r--indra/newview/gltfscenemanager.h19
-rw-r--r--indra/newview/lldrawpoolalpha.cpp3
-rw-r--r--indra/newview/lldrawpoolavatar.cpp4
-rw-r--r--indra/newview/lldrawpoolpbropaque.cpp15
-rw-r--r--indra/newview/llenvironment.cpp16
-rw-r--r--indra/newview/llreflectionmapmanager.cpp50
-rw-r--r--indra/newview/llskinningutil.cpp6
-rw-r--r--indra/newview/llskinningutil.h1
-rw-r--r--indra/newview/llviewershadermgr.cpp48
-rw-r--r--indra/newview/llviewershadermgr.h3
-rw-r--r--indra/newview/pipeline.cpp6
30 files changed, 734 insertions, 400 deletions
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index ac697b72be..0586c34e50 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1238,6 +1238,11 @@ bool LLGLManager::initGL()
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
+ glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize);
+
+ // sanity clamp max uniform block size to 64k just in case
+ // there's some implementation that reports a crazy value
+ mMaxUniformBlockSize = llmin(mMaxUniformBlockSize, 65536);
if (mGLVersion >= 4.59f)
{
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 75a7c5d3b2..2f538d0844 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -87,6 +87,7 @@ public:
S32 mGLMaxIndexRange;
S32 mGLMaxTextureSize;
F32 mMaxAnisotropy = 0.f;
+ S32 mMaxUniformBlockSize = 0;
// GL 4.x capabilities
bool mHasCubeMapArray = false;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index ecd0c6908b..8ea134393a 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -983,17 +983,25 @@ bool LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms)
}
//........................................................................................................................................
- if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl).
- { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf
- static const GLuint BLOCKBINDING = 1; //picked by us
- //Get the index, similar to a uniform location
- GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, "ReflectionProbes");
+ // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl).
+ // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf
+ const char* ubo_names[] =
+ {
+ "ReflectionProbes", // UB_REFLECTION_PROBES
+ "GLTFJoints", // UB_GLTF_JOINTS
+ };
+
+ llassert(LL_ARRAY_SIZE(ubo_names) == NUM_UNIFORM_BLOCKS);
+
+ for (U32 i = 0; i < NUM_UNIFORM_BLOCKS; ++i)
+ {
+ GLuint UBOBlockIndex = glGetUniformBlockIndex(mProgramObject, ubo_names[i]);
if (UBOBlockIndex != GL_INVALID_INDEX)
{
- //Set this index to a binding index
- glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING);
+ glUniformBlockBinding(mProgramObject, UBOBlockIndex, i);
}
}
+
unbind();
LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
@@ -1049,9 +1057,10 @@ void LLGLSLShader::bind()
}
}
-void LLGLSLShader::bind(LLGLSLShader::GLTFVariant variant)
+void LLGLSLShader::bind(U32 variant)
{
llassert(mGLTFVariants.size() == LLGLSLShader::NUM_GLTF_VARIANTS);
+ llassert(variant < LLGLSLShader::NUM_GLTF_VARIANTS);
mGLTFVariants[variant].bind();
}
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index fa01d212e1..8ebea2deca 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -146,6 +146,14 @@ public:
SG_COUNT
} eGroup;
+ enum UniformBlock : GLuint
+ {
+ UB_REFLECTION_PROBES,
+ UB_GLTF_JOINTS,
+ NUM_UNIFORM_BLOCKS
+ };
+
+
static std::set<LLGLSLShader*> sInstances;
static bool sProfileEnabled;
@@ -320,20 +328,24 @@ public:
LLGLSLShader* mRiggedVariant = nullptr;
// variants for use by GLTF renderer
- // "this" is considered to be OPAQUE
- enum GLTFVariant
+ // bit 0 = alpha mode blend (1) or opaque (0)
+ // bit 1 = rigged (1) or static (0)
+ struct GLTFVariant
{
- STATIC_OPAQUE,
- STATIC_BLEND,
- RIGGED_OPAQUE,
- RIGGED_BLEND,
- NUM_GLTF_VARIANTS
+ constexpr static U32 RIGGED = 2;
+ constexpr static U32 ALPHA = 1;
+ constexpr static U32 OPAQUE_STATIC = 0;
+ constexpr static U32 ALPHA_STATIC = 1;
+ constexpr static U32 OPAQUE_RIGGED = 2;
+ constexpr static U32 ALPHA_RIGGED = 3;
};
+ constexpr static U32 NUM_GLTF_VARIANTS = 4;
+
std::vector<LLGLSLShader> mGLTFVariants;
//helper to bind GLTF variant
- void bind(GLTFVariant variant);
+ void bind(U32 variant);
// hacky flag used for optimization in LLDrawPoolAlpha
bool mCanBindFast = false;
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 694bcbeeb9..4e8adb2fb3 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1225,6 +1225,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap");
mReservedUniforms.push_back("specularMap");
+ mReservedUniforms.push_back("metallicRoughnessMap");
+ mReservedUniforms.push_back("normalMap");
+ mReservedUniforms.push_back("occlusionMap");
mReservedUniforms.push_back("emissiveMap");
mReservedUniforms.push_back("bumpMap");
mReservedUniforms.push_back("bumpMap2");
@@ -1348,7 +1351,6 @@ void LLShaderMgr::initAttribsAndUniforms()
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1);
- mReservedUniforms.push_back("normalMap");
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index c3e5a2aafd..03803c0e96 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -93,6 +93,9 @@ public:
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
+ METALLIC_ROUGHNESS_MAP, // "metallicRoughnessMap"
+ NORMAL_MAP, // "normalMap"
+ OCCLUSION_MAP, // "occlusionMap"
EMISSIVE_MAP, // "emissiveMap"
BUMP_MAP, // "bumpMap"
BUMP_MAP2, // "bumpMap2"
@@ -202,7 +205,6 @@ public:
DEFERRED_SHADOW3, // "shadowMap3"
DEFERRED_SHADOW4, // "shadowMap4"
DEFERRED_SHADOW5, // "shadowMap5"
- DEFERRED_NORMAL, // "normalMap"
DEFERRED_POSITION, // "positionMap"
DEFERRED_DIFFUSE, // "diffuseRect"
DEFERRED_SPECULAR, // "specularRect"
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 7caf20f40b..8cb124d406 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -687,6 +687,7 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
}
{
+#if 0 // not a reliable test for VBOs that are not backed by a CPU buffer
U16* idx = (U16*) mMappedIndexData+indices_offset;
for (U32 i = 0; i < count; ++i)
{
@@ -724,6 +725,7 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
}
}
}
+#endif
}
return true;
@@ -1036,8 +1038,7 @@ bool LLVertexBuffer::updateNumIndices(U32 nindices)
bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices)
{
- if (nverts < 0 || nindices < 0 ||
- nverts > 65536)
+ if (nverts < 0 || nindices < 0)
{
LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index 385920f622..8b23037934 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -496,6 +496,43 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
return clamp(color, vec3(0), vec3(10));
}
+vec3 pbrCalcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 p, // pixel position
+ vec3 v, // view vector (negative normalized pixel position)
+ vec3 lp, // light position
+ vec3 ld, // light direction (for spotlights)
+ vec3 lightColor,
+ float lightSize, float falloff, float is_pointlight, float ambiance)
+{
+ vec3 color = vec3(0,0,0);
+
+ vec3 lv = lp.xyz - p;
+
+ float lightDist = length(lv);
+
+ float dist = lightDist / lightSize;
+ if (dist <= 1.0)
+ {
+ lv /= lightDist;
+
+ float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
+
+ // spotlight coefficient.
+ float spot = max(dot(-ld, lv), is_pointlight);
+ // spot*spot => GL_SPOT_EXPONENT=2
+ float spot_atten = spot*spot;
+
+ vec3 intensity = spot_atten * dist_atten * lightColor * 3.0; //magic number to balance with legacy materials
+
+ color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
+ }
+
+ return color;
+}
+
void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor)
{
vec3 f0 = vec3(0.04);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
index d0fc362db9..ae179d3f37 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
@@ -51,8 +51,6 @@ uniform vec4[2] texture_emissive_transform;
out vec3 vary_fragcoord;
-uniform float near_clip;
-
in vec3 position;
in vec4 diffuse_color;
in vec3 normal;
@@ -88,7 +86,7 @@ void main()
#endif
gl_Position = vert;
- vary_fragcoord.xyz = vert.xyz + vec3(0,0,near_clip);
+ vary_fragcoord.xyz = vert.xyz;
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0);
diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl
index dbee58b76a..a59127ec77 100644
--- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl
+++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file pbrmetallicroughnessF.glsl
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,11 +33,82 @@ uniform sampler2D diffuseMap; //always in sRGB space
uniform float metallicFactor;
uniform float roughnessFactor;
uniform vec3 emissiveColor;
-uniform sampler2D bumpMap;
+uniform sampler2D normalMap;
uniform sampler2D emissiveMap;
-uniform sampler2D specularMap; // Packed: Occlusion, Metal, Roughness
+uniform sampler2D metallicRoughnessMap;
+uniform sampler2D occlusionMap;
+
+#ifdef ALPHA_BLEND
+out vec4 frag_color;
+
+in vec3 vary_fragcoord;
+
+#ifdef HAS_SUN_SHADOW
+uniform sampler2D lightMap;
+uniform vec2 screen_res;
+#endif
+
+// Lights
+// See: LLRender::syncLightState()
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8]; // spot direction
+uniform vec4 light_attenuation[8]; // linear, quadratic, is omni, unused, See: LLPipeline::setupHWLights() and syncLightState()
+uniform vec3 light_diffuse[8];
+uniform vec2 light_deferred_attenuation[8]; // light size and falloff
+
+uniform int sun_up_factor;
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
+
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color);
+
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+float calcLegacyDistanceAttenuation(float distance, float falloff);
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+ vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
+
+void mirrorClip(vec3 pos);
+void waterClip(vec3 pos);
+
+void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor);
+
+vec3 pbrBaseLight(vec3 diffuseColor,
+ vec3 specularColor,
+ float metallic,
+ vec3 pos,
+ vec3 norm,
+ float perceptualRoughness,
+ vec3 light_dir,
+ vec3 sunlit,
+ float scol,
+ vec3 radiance,
+ vec3 irradiance,
+ vec3 colorEmissive,
+ float ao,
+ vec3 additive,
+ vec3 atten);
+
+vec3 pbrCalcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
+ float metallic,
+ vec3 n, // normal
+ vec3 p, // pixel position
+ vec3 v, // view vector (negative normalized pixel position)
+ vec3 lp, // light position
+ vec3 ld, // light direction (for spotlights)
+ vec3 lightColor,
+ float lightSize, float falloff, float is_pointlight, float ambiance);
+
+
+#else
out vec4 frag_data[4];
+#endif
+
in vec3 vary_position;
in vec4 vertex_color;
@@ -50,7 +121,7 @@ in vec2 normal_texcoord;
in vec2 metallic_roughness_texcoord;
in vec2 emissive_texcoord;
-uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
+uniform float minimum_alpha;
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
@@ -62,9 +133,11 @@ void mirrorClip(vec3 pos);
uniform mat3 normal_matrix;
+
void main()
{
- mirrorClip(vary_position);
+ vec3 pos = vary_position;
+ mirrorClip(pos);
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
basecolor.rgb = srgb_to_linear(basecolor.rgb);
@@ -79,39 +152,97 @@ void main()
vec3 col = basecolor.rgb;
// from mikktspace.com
- vec3 vNt = texture(bumpMap, normal_texcoord.xy).xyz*2.0-1.0;
+ vec3 vNt = texture(normalMap, normal_texcoord.xy).xyz*2.0-1.0;
float sign = vary_sign;
vec3 vN = vary_normal;
vec3 vT = vary_tangent.xyz;
-
+
vec3 vB = sign * cross(vN, vT);
- vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
+ vec3 norm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
// RGB = Occlusion, Roughness, Metal
// default values, see LLViewerTexture::sDefaultPBRORMImagep
// occlusion 1.0
// roughness 0.0
// metal 0.0
- vec3 spec = texture(specularMap, metallic_roughness_texcoord.xy).rgb;
-
- spec.g *= roughnessFactor;
- spec.b *= metallicFactor;
+ vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb;
+ orm.r = texture(occlusionMap, metallic_roughness_texcoord.xy).r;
+ orm.g *= roughnessFactor;
+ orm.b *= metallicFactor;
vec3 emissive = emissiveColor;
emissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb);
- tnorm *= gl_FrontFacing ? 1.0 : -1.0;
+ norm *= gl_FrontFacing ? 1.0 : -1.0;
+
+#ifdef ALPHA_BLEND
+ vec3 color = vec3(0,0,0);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+
+ float scol = 1.0;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+ calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
+
+ vec3 sunlit_linear = srgb_to_linear(sunlit);
+
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+
+#ifdef HAS_SUN_SHADOW
+ scol = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
+#endif
+
+ float perceptualRoughness = orm.g * roughnessFactor;
+ float metallic = orm.b * metallicFactor;
+
+ // emissiveColor is the emissive color factor from GLTF and is already in linear space
+ vec3 colorEmissive = emissiveColor;
+ // emissiveMap here is a vanilla RGB texture encoded as sRGB, manually convert to linear
+ colorEmissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb);
+
+ // PBR IBL
+ float gloss = 1.0 - perceptualRoughness;
+ vec3 irradiance = vec3(0);
+ vec3 radiance = vec3(0);
+ sampleReflectionProbes(irradiance, radiance, vary_position.xy*0.5+0.5, pos.xyz, norm.xyz, gloss, true, amblit);
+
+ vec3 diffuseColor;
+ vec3 specularColor;
+ calcDiffuseSpecular(col.rgb, metallic, diffuseColor, specularColor);
+
+ vec3 v = -normalize(pos.xyz);
+
+ color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, orm.r, additive, atten);
+
+ vec3 light = vec3(0);
+
+ // Punctual lights
+#define LIGHT_LOOP(i) light += pbrCalcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ color.rgb += light.rgb;
+
+ color.rgb = applySkyAndWaterFog(pos.xyz, additive, atten, vec4(color, 1.0)).rgb;
+
+ float a = basecolor.a*vertex_color.a;
- //spec.rgb = vec3(1,1,0);
- //col = vec3(0,0,0);
- //emissive = vary_tangent.xyz*0.5+0.5;
- //emissive = vec3(sign*0.5+0.5);
- //emissive = vNt * 0.5 + 0.5;
- //emissive = tnorm*0.5+0.5;
+ frag_color = max(vec4(color.rgb,a), vec4(0));
+#else
// See: C++: addDeferredAttachments(), GLSL: softenLightF
- frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse
- frag_data[1] = max(vec4(spec.rgb,0.0), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal.
- frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags
- frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive
+ frag_data[0] = max(vec4(col, 0.0), vec4(0));
+ frag_data[1] = max(vec4(orm.rgb,0.0), vec4(0));
+ frag_data[2] = vec4(norm, GBUFFER_FLAG_HAS_PBR);
+ frag_data[3] = max(vec4(emissive,0), vec4(0));
+#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl
index 0add509002..403ca8b2db 100644
--- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl
+++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl
@@ -29,7 +29,6 @@ uniform mat4 modelview_matrix;
#ifdef HAS_SKIN
uniform mat4 projection_matrix;
-mat4 getObjectSkinnedTransform();
#else
uniform mat3 normal_matrix;
uniform mat4 modelview_projection_matrix;
@@ -62,21 +61,85 @@ out vec3 vary_position;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
+
+#ifdef ALPHA_BLEND
+out vec3 vary_fragcoord;
+#endif
+
+
+#ifdef HAS_SKIN
+in vec4 weight4;
+
+layout (std140) uniform GLTFJoints
+{
+ // list of OBBs for user override probes
+ mat3x4 gltf_joints[MAX_JOINTS_PER_GLTF_OBJECT];
+};
+
+mat4 getGLTFSkinTransform()
+{
+ int i;
+
+ vec4 w = fract(weight4);
+ vec4 index = floor(weight4);
+
+ index = min(index, vec4(MAX_JOINTS_PER_GLTF_OBJECT-1));
+ index = max(index, vec4( 0.0));
+
+ w *= 1.0/(w.x+w.y+w.z+w.w);
+
+ int i1 = int(index.x);
+ int i2 = int(index.y);
+ int i3 = int(index.z);
+ int i4 = int(index.w);
+
+ mat3 mat = mat3(gltf_joints[i1])*w.x;
+ mat += mat3(gltf_joints[i2])*w.y;
+ mat += mat3(gltf_joints[i3])*w.z;
+ mat += mat3(gltf_joints[i4])*w.w;
+
+ vec3 trans = vec3(gltf_joints[i1][0].w,gltf_joints[i1][1].w,gltf_joints[i1][2].w)*w.x;
+ trans += vec3(gltf_joints[i2][0].w,gltf_joints[i2][1].w,gltf_joints[i2][2].w)*w.y;
+ trans += vec3(gltf_joints[i3][0].w,gltf_joints[i3][1].w,gltf_joints[i3][2].w)*w.z;
+ trans += vec3(gltf_joints[i4][0].w,gltf_joints[i4][1].w,gltf_joints[i4][2].w)*w.w;
+
+ mat4 ret;
+
+ ret[0] = vec4(mat[0], 0);
+ ret[1] = vec4(mat[1], 0);
+ ret[2] = vec4(mat[2], 0);
+ ret[3] = vec4(trans, 1.0);
+
+ return ret;
+
+#ifdef IS_AMD_CARD
+ // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts.
+ mat3x4 dummy1 = gltf_joints[0];
+ mat3x4 dummy2 = gltf_joints[MAX_JOINTS_PER_MESH_OBJECT-1];
+#endif
+
+}
+
+#endif
+
void main()
{
#ifdef HAS_SKIN
- mat4 mat = getObjectSkinnedTransform();
+ mat4 mat = getGLTFSkinTransform();
mat = modelview_matrix * mat;
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
vary_position = pos;
- gl_Position = projection_matrix*vec4(pos,1.0);
+
+ vec4 vert = projection_matrix * vec4(pos, 1.0);
+ gl_Position = vert;
#else
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
//transform vertex
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 vert = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ gl_Position = vert;
#endif
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
@@ -99,6 +162,9 @@ void main()
vary_normal = n;
vertex_color = diffuse_color;
+#ifdef ALPHA_BLEND
+ vary_fragcoord = vert.xyz;
+#endif
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
index 059c2a64ce..f4a8051427 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file class1\deferred\pbralphaF.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -87,7 +87,7 @@ vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color);
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
void mirrorClip(vec3 pos);
@@ -111,15 +111,15 @@ vec3 pbrBaseLight(vec3 diffuseColor,
vec3 additive,
vec3 atten);
-vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
- float perceptualRoughness,
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
-vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
- float perceptualRoughness,
+vec3 pbrCalcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 p, // pixel position
@@ -127,33 +127,7 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
vec3 lp, // light position
vec3 ld, // light direction (for spotlights)
vec3 lightColor,
- float lightSize, float falloff, float is_pointlight, float ambiance)
-{
- vec3 color = vec3(0,0,0);
-
- vec3 lv = lp.xyz - p;
-
- float lightDist = length(lv);
-
- float dist = lightDist / lightSize;
- if (dist <= 1.0)
- {
- lv /= lightDist;
-
- float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
-
- // spotlight coefficient.
- float spot = max(dot(-ld, lv), is_pointlight);
- // spot*spot => GL_SPOT_EXPONENT=2
- float spot_atten = spot*spot;
-
- vec3 intensity = spot_atten * dist_atten * lightColor * 3.0; //magic number to balance with legacy materials
-
- color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
- }
-
- return color;
-}
+ float lightSize, float falloff, float is_pointlight, float ambiance);
void main()
{
@@ -181,7 +155,7 @@ void main()
float sign = vary_sign;
vec3 vN = vary_normal;
vec3 vT = vary_tangent.xyz;
-
+
vec3 vB = sign * cross(vN, vT);
vec3 norm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
@@ -218,7 +192,7 @@ void main()
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
sampleReflectionProbes(irradiance, radiance, vary_position.xy*0.5+0.5, pos.xyz, norm.xyz, gloss, true, amblit);
-
+
vec3 diffuseColor;
vec3 specularColor;
calcDiffuseSpecular(col.rgb, metallic, diffuseColor, specularColor);
@@ -230,7 +204,7 @@ void main()
vec3 light = vec3(0);
// Punctual lights
-#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
+#define LIGHT_LOOP(i) light += pbrCalcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
LIGHT_LOOP(1)
LIGHT_LOOP(2)
@@ -245,7 +219,7 @@ void main()
color.rgb = applySkyAndWaterFog(pos.xyz, additive, atten, vec4(color, 1.0)).rgb;
float a = basecolor.a*vertex_color.a;
-
+
frag_color = max(vec4(color.rgb,a), vec4(0));
}
@@ -295,7 +269,7 @@ void main()
// emissiveMap here is a vanilla RGB texture encoded as sRGB, manually convert to linear
colorEmissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb);
-
+
float a = basecolor.a*vertex_color.a;
color += colorEmissive;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
index d3e19cf4a8..26ab0406f6 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -77,7 +77,6 @@ uniform float is_mirror;
uniform vec3 sun_dir;
uniform vec3 moon_dir;
-in vec2 vary_fragcoord;
uniform mat4 proj_mat;
uniform mat4 inv_proj;
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;
}
}
diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp
index eb11c60e43..a20954d7d1 100644
--- a/indra/newview/gltfscenemanager.cpp
+++ b/indra/newview/gltfscenemanager.cpp
@@ -351,11 +351,18 @@ void GLTFSceneManager::onGLTFBinLoadComplete(const LLUUID& id, LLAssetType::ETyp
if (obj->mGLTFAsset->mPendingBuffers == 0)
{
- obj->mGLTFAsset->prep();
- GLTFSceneManager& mgr = GLTFSceneManager::instance();
- if (std::find(mgr.mObjects.begin(), mgr.mObjects.end(), obj) == mgr.mObjects.end())
+ if (obj->mGLTFAsset->prep())
{
- GLTFSceneManager::instance().mObjects.push_back(obj);
+ GLTFSceneManager& mgr = GLTFSceneManager::instance();
+ if (std::find(mgr.mObjects.begin(), mgr.mObjects.end(), obj) == mgr.mObjects.end())
+ {
+ GLTFSceneManager::instance().mObjects.push_back(obj);
+ }
+ }
+ else
+ {
+ LL_WARNS("GLTF") << "Failed to prepare GLTF asset: " << id << LL_ENDL;
+ obj->mGLTFAsset = nullptr;
}
}
}
@@ -528,7 +535,6 @@ void GLTFSceneManager::render(bool opaque, bool rigged)
}
Asset* asset = mObjects[i]->mGLTFAsset.get();
-
gGL.pushMatrix();
LLMatrix4a mat = mObjects[i]->getGLTFAssetToAgentTransform();
@@ -540,12 +546,195 @@ void GLTFSceneManager::render(bool opaque, bool rigged)
mat4 mdv = glm::make_mat4(modelview.getF32ptr());
asset->updateRenderTransforms(mdv);
- asset->render(opaque, rigged);
+
+ if (rigged)
+ { // provide a modelview matrix that goes from asset to camera space for rigged render passes
+ // (matrix palettes are in asset space)
+ gGL.loadMatrix(glm::value_ptr(mdv));
+ }
+ render(*asset, opaque, rigged);
gGL.popMatrix();
}
}
+void GLTFSceneManager::render(Asset& asset, bool opaque, bool rigged)
+{
+ U32 variant = 0;
+ if (rigged)
+ {
+ variant |= LLGLSLShader::GLTFVariant::RIGGED;
+ }
+ if (!opaque)
+ {
+ variant |= LLGLSLShader::GLTFVariant::ALPHA;
+ }
+
+ if (opaque)
+ {
+ gGLTFPBRMetallicRoughnessProgram.bind(variant);
+ }
+ else
+ { // alpha shaders need all the shadow map setup etc
+ gPipeline.bindDeferredShader(gGLTFPBRMetallicRoughnessProgram.mGLTFVariants[variant]);
+ }
+
+ for (auto& node : asset.mNodes)
+ {
+ if (node.mSkin != INVALID_INDEX)
+ {
+ if (rigged)
+ {
+ Skin& skin = asset.mSkins[node.mSkin];
+ glBindBufferBase(GL_UNIFORM_BUFFER, LLGLSLShader::UB_GLTF_JOINTS, skin.mUBO);
+ }
+ 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 = asset.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 = asset.mMaterials[primitive.mMaterial];
+ bool mat_opaque = material.mAlphaMode != Material::AlphaMode::BLEND;
+
+ if (mat_opaque != opaque)
+ {
+ continue;
+ }
+
+ bind(asset, material);
+
+ 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());
+ }
+ }
+ }
+ }
+}
+
+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 GLTFSceneManager::bind(Asset& asset, Material& material)
+{
+ // 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 || (material.mAlphaMode == Material::AlphaMode::BLEND))
+ {
+ if (material.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 (material.mPbrMetallicRoughness.mBaseColorFactor.a > 0.f)
+ {
+ min_alpha = material.mAlphaCutoff / material.mPbrMetallicRoughness.mBaseColorFactor.a;
+ }
+ else
+ {
+ min_alpha = 1024.f;
+ }
+ }
+ shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha);
+ }
+
+ bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, material.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::NORMAL_MAP, material.mNormalTexture, LLViewerFetchedTexture::sFlatNormalImagep);
+ bindTexture(asset, LLShaderMgr::METALLIC_ROUGHNESS_MAP, material.mPbrMetallicRoughness.mMetallicRoughnessTexture, LLViewerFetchedTexture::sWhiteImagep);
+ bindTexture(asset, LLShaderMgr::OCCLUSION_MAP, material.mOcclusionTexture, LLViewerFetchedTexture::sWhiteImagep);
+ bindTexture(asset, LLShaderMgr::EMISSIVE_MAP, material.mEmissiveTexture, LLViewerFetchedTexture::sWhiteImagep);
+
+ // NOTE: base color factor is baked into vertex stream
+
+ shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, material.mPbrMetallicRoughness.mRoughnessFactor);
+ shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, material.mPbrMetallicRoughness.mMetallicFactor);
+ shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(material.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);
+ }
+}
+
LLMatrix4a inverse(const LLMatrix4a& mat)
{
glh::matrix4f m((F32*)mat.mMatrix);
diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h
index 53b4ff0e4e..fcde6cf1f7 100644
--- a/indra/newview/gltfscenemanager.h
+++ b/indra/newview/gltfscenemanager.h
@@ -28,19 +28,13 @@
#include "llsingleton.h"
#include "llviewerobject.h"
+#include "gltf/common.h"
+
class LLVOVolume;
class LLDrawable;
namespace LL
{
- namespace GLTF
- {
- class Asset;
- }
-}
-
-namespace LL
-{
class GLTFSceneManager : public LLSimpleton<GLTFSceneManager>
{
public:
@@ -56,6 +50,11 @@ namespace LL
void update();
void render(bool opaque, bool rigged = false);
+ void render(LL::GLTF::Asset& asset, bool opaque, bool rigged);
+
+ // bind the given material for rendering
+ void bind(LL::GLTF::Asset& asset, LL::GLTF::Material& material);
+
void renderOpaque();
void renderAlpha();
@@ -71,7 +70,7 @@ namespace LL
LLVector4a* normal, // return the surface normal at the intersection point
LLVector4a* tangent); // return the surface tangent at the intersection point
- bool lineSegmentIntersect(LLVOVolume* obj, GLTF::Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32* face_hitp, S32* primitive_hitp,
+ bool lineSegmentIntersect(LLVOVolume* obj, LL::GLTF::Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32* face_hitp, S32* primitive_hitp,
LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent);
void renderDebug();
@@ -88,6 +87,8 @@ namespace LL
U32 mPendingImageUploads = 0;
U32 mPendingBinaryUploads = 0;
U32 mPendingGLTFUploads = 0;
+
+ U32 mJointUBO = 0;
};
}
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 201c337b26..2a376a40b2 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -263,10 +263,7 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)
if (rigged)
{ // draw GLTF scene to depth buffer before rigged alpha
- gPipeline.bindDeferredShader(gDeferredPBRAlphaProgram);
LL::GLTFSceneManager::instance().render(false, false);
-
- gPipeline.bindDeferredShader(*gDeferredPBRAlphaProgram.mRiggedVariant);
LL::GLTFSceneManager::instance().render(false, true);
}
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 25bce7bced..9afc705d3e 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -555,7 +555,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
sVertexProgram = &gDeferredImpostorProgram;
specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
- normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
+ normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::NORMAL_MAP);
sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
sVertexProgram->bind();
sVertexProgram->setMinimumAlpha(0.01f);
@@ -566,7 +566,7 @@ void LLDrawPoolAvatar::endDeferredImpostor()
LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR
sShaderLevel = mShaderLevel;
- sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
+ sVertexProgram->disableTexture(LLViewerShaderMgr::NORMAL_MAP);
sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
gPipeline.unbindDeferredShader(*sVertexProgram);
diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp
index a32b6b1687..5eb10fe335 100644
--- a/indra/newview/lldrawpoolpbropaque.cpp
+++ b/indra/newview/lldrawpoolpbropaque.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldrawpoolpbropaque.cpp
* @brief LLDrawPoolGLTFPBR class implementation
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -54,11 +54,10 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass)
{
llassert(!LLPipeline::sRenderingHUDs);
- gDeferredPBROpaqueProgram.bind();
-
LL::GLTFSceneManager::instance().renderOpaque();
- pushGLTFBatches(mRenderType);
+ gDeferredPBROpaqueProgram.bind();
+ pushGLTFBatches(mRenderType);
gDeferredPBROpaqueProgram.bind(true);
LL::GLTFSceneManager::instance().render(true, true);
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index fabba1972e..e075562e52 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1680,15 +1680,15 @@ void LLEnvironment::update(const LLViewerCamera * cam)
end_shaders = LLViewerShaderMgr::instance()->endShaders();
for (shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
{
- if ((shaders_iter->mProgramObject != 0)
- && (gPipeline.canUseWindLightShaders()
- || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
+ shaders_iter->mUniformsDirty = true;
+ if (shaders_iter->mRiggedVariant)
{
- shaders_iter->mUniformsDirty = true;
- if (shaders_iter->mRiggedVariant)
- {
- shaders_iter->mRiggedVariant->mUniformsDirty = true;
- }
+ shaders_iter->mRiggedVariant->mUniformsDirty = true;
+ }
+
+ for (auto& variant : shaders_iter->mGLTFVariants)
+ {
+ variant.mUniformsDirty = true;
}
}
}
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 2c01495934..f62cac3276 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -67,7 +67,7 @@ void load_exr(const std::string& filename)
const char* err = NULL; // or nullptr in C++11
int ret = LoadEXRWithLayer(&out, &width, &height, filename.c_str(), /* layername */ nullptr, &err);
- if (ret == TINYEXR_SUCCESS)
+ if (ret == TINYEXR_SUCCESS)
{
U32 texName = 0;
LLImageGL::generateTextures(1, &texName);
@@ -87,12 +87,12 @@ void load_exr(const std::string& filename)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
- else
+ else
{
LLSD notif_args;
notif_args["WHAT"] = filename;
notif_args["REASON"] = "Unknown";
- if (err)
+ if (err)
{
notif_args["REASON"] = std::string(err);
FreeEXRErrorMessage(err); // release memory of error message.
@@ -231,7 +231,7 @@ void LLReflectionMapManager::update()
{
U32 res = mProbeResolution;
U32 count = log2((F32)res) + 0.5f;
-
+
mMipChain.resize(count);
for (int i = 0; i < count; ++i)
{
@@ -241,7 +241,7 @@ void LLReflectionMapManager::update()
}
llassert(mProbes[0] == mDefaultProbe);
-
+
LLVector4a camera_pos;
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
@@ -256,7 +256,7 @@ void LLReflectionMapManager::update()
}
mKillList.clear();
-
+
// process create list
for (auto& probe : mCreateList)
{
@@ -272,12 +272,12 @@ void LLReflectionMapManager::update()
bool did_update = false;
-
+
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3);
bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
-
+
LLReflectionMap* closestDynamic = nullptr;
LLReflectionMap* oldestProbe = nullptr;
@@ -339,7 +339,7 @@ void LLReflectionMapManager::update()
--i;
continue;
}
-
+
if (probe != mDefaultProbe &&
(!probe->isRelevant() || mPaused))
{ // skip irrelevant probes (or all non-default probes if paused)
@@ -442,7 +442,7 @@ void LLReflectionMapManager::update()
{
LLReflectionMap* probe = oldestProbe;
llassert(probe->mCubeIndex != -1);
-
+
probe->autoAdjustOrigin();
sUpdateCount++;
@@ -636,7 +636,7 @@ void LLReflectionMapManager::doProbeUpdate()
llassert(mUpdatingProbe != nullptr);
updateProbeFace(mUpdatingProbe, mUpdatingFace);
-
+
bool debug_updates = gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PROBE_UPDATES) && mUpdatingProbe->mViewerObject;
if (++mUpdatingFace == 6)
@@ -689,11 +689,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
touch_default_probe(probe);
gPipeline.pushRenderTypeMask();
-
+
//only render sky, water, terrain, and clouds
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY,
LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES);
-
+
probe->update(mRenderTarget.getWidth(), face);
gPipeline.popRenderTypeMask();
@@ -702,7 +702,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
{
probe->update(mRenderTarget.getWidth(), face);
}
-
+
gPipeline.mRT = &gPipeline.mMainRT;
S32 sourceIdx = mReflectionProbeCount;
@@ -779,12 +779,12 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
}
-
+
gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));
-
+
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
+
res /= 2;
S32 mip = i - (mMipChain.size() - mips);
@@ -874,7 +874,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
-
+
mVertexBuffer->setBuffer();
int start_mip = 0;
// find the mip target to start with based on irradiance map resolution
@@ -951,7 +951,7 @@ void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
//remove from existing neighbors
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear");
-
+
for (auto& other : probe->mNeighbors)
{
auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
@@ -1063,7 +1063,7 @@ void LLReflectionMapManager::updateUniforms()
bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass();
F32 ambscale = is_ambiance_pass ? 0.f : 1.f;
F32 radscale = is_ambiance_pass ? 0.5f : 1.f;
-
+
for (auto* refmap : mReflectionMaps)
{
if (refmap == nullptr)
@@ -1194,7 +1194,7 @@ void LLReflectionMapManager::updateUniforms()
{
// fill in gaps in refBucket
S32 probe_idx = mReflectionProbeCount;
-
+
for (int i = 0; i < 256; ++i)
{
if (i < count)
@@ -1266,7 +1266,7 @@ void LLReflectionMapManager::setUniforms()
{
updateUniforms();
}
- glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
+ glBindBufferBase(GL_UNIFORM_BUFFER, LLGLSLShader::UB_REFLECTION_PROBES, mUBO);
}
@@ -1441,9 +1441,9 @@ void LLReflectionMapManager::initReflectionMaps()
buff->allocateBuffer(4, 0);
LLStrider<LLVector3> v;
-
+
buff->getVertexStrider(v);
-
+
v[0] = LLVector3(-1, -1, -1);
v[1] = LLVector3(1, -1, -1);
v[2] = LLVector3(-1, 1, -1);
@@ -1471,7 +1471,7 @@ void LLReflectionMapManager::cleanup()
mReflectionMaps.clear();
mUpdatingFace = 0;
-
+
mDefaultProbe = nullptr;
mUpdatingProbe = nullptr;
diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp
index 438b04ff39..4ffbd8a562 100644
--- a/indra/newview/llskinningutil.cpp
+++ b/indra/newview/llskinningutil.cpp
@@ -97,6 +97,12 @@ U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin)
return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size());
}
+S32 LLSkinningUtil::getMaxGLTFJointCount()
+{
+ // this is the maximum number of 3x4 matrices than can fit in a UBO
+ return gGLManager.mMaxUniformBlockSize / 48;
+}
+
void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin)
{
if (skin->mInvalidJointsScrubbed)
diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h
index bd2f8ea04e..aa0c0075af 100644
--- a/indra/newview/llskinningutil.h
+++ b/indra/newview/llskinningutil.h
@@ -40,6 +40,7 @@ class LLJointRiggingInfoTab;
namespace LLSkinningUtil
{
S32 getMaxJointCount();
+ S32 getMaxGLTFJointCount();
U32 getMeshJointCount(const LLMeshSkinInfo *skin);
void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
void initSkinningMatrixPalette(LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 0ca05b3460..e53e90b703 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -249,7 +249,7 @@ static bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader
}
-static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged)
+static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged, bool use_sun_shadow)
{
variant.mName = shader.mName.c_str();
variant.mFeatures = shader.mFeatures;
@@ -259,20 +259,50 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool
variant.mDefines = shader.mDefines; // NOTE: Must come before addPermutation
+ variant.addPermutation("MAX_JOINTS_PER_GLTF_OBJECT", std::to_string(LLSkinningUtil::getMaxGLTFJointCount()));
+
+ if (rigged)
+ {
+ variant.addPermutation("HAS_SKIN", "1");
+ }
+
if (alpha_blend)
{
variant.addPermutation("ALPHA_BLEND", "1");
+
+ variant.mFeatures.calculatesLighting = false;
+ variant.mFeatures.hasLighting = false;
+ variant.mFeatures.isAlphaLighting = true;
+ variant.mFeatures.hasSrgb = true;
+ variant.mFeatures.calculatesAtmospherics = true;
+ variant.mFeatures.hasAtmospherics = true;
+ variant.mFeatures.hasGamma = true;
+ variant.mFeatures.hasShadows = use_sun_shadow;
+ variant.mFeatures.isDeferred = true; // include deferredUtils
+ variant.mFeatures.hasReflectionProbes = true;
+
+ if (use_sun_shadow)
+ {
+ variant.addPermutation("HAS_SUN_SHADOW", "1");
+ }
+
+ bool success = variant.createShader(NULL, NULL);
+ llassert(success);
+
+ // Alpha Shader Hack
+ // See: LLRender::syncMatrices()
+ variant.mFeatures.calculatesLighting = true;
+ variant.mFeatures.hasLighting = true;
+
+ return success;
}
- if (rigged)
+ else
{
- variant.addPermutation("HAS_SKIN", "1");
- variant.mFeatures.hasObjectSkinning = true;
+ return variant.createShader(NULL, NULL);
}
-
- return variant.createShader(NULL, NULL);
}
-static bool make_gltf_variants(LLGLSLShader& shader)
+static bool make_gltf_variants(LLGLSLShader& shader, bool use_sun_shadow)
{
shader.mFeatures.mGLTF = true;
shader.mGLTFVariants.resize(LLGLSLShader::NUM_GLTF_VARIANTS);
@@ -282,7 +312,7 @@ static bool make_gltf_variants(LLGLSLShader& shader)
bool alpha_blend = i & 1;
bool rigged = i & 2;
- if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged))
+ if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, use_sun_shadow))
{
return false;
}
@@ -1269,7 +1299,7 @@ bool LLViewerShaderMgr::loadShadersDeferred()
gGLTFPBRMetallicRoughnessProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gGLTFPBRMetallicRoughnessProgram.clearPermutations();
- success = make_gltf_variants(gGLTFPBRMetallicRoughnessProgram);
+ success = make_gltf_variants(gGLTFPBRMetallicRoughnessProgram, use_sun_shadow);
llassert(success);
}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index f0de9e9715..60ce8c430b 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -287,6 +287,9 @@ extern LLGLSLShader gDeferredPBROpaqueProgram;
extern LLGLSLShader gDeferredPBRAlphaProgram;
extern LLGLSLShader gHUDPBRAlphaProgram;
+// GLTF shaders
+extern LLGLSLShader gGLTFPBRMetallicRoughnessProgram;
+
// Encodes detail level for dropping textures, in accordance with the GLTF spec where possible
// 0 is highest detail, -1 drops emissive, etc
// Dropping metallic roughness is off-spec - Reserve for potato machines as needed
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a0d2116eaa..249e66d098 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6825,7 +6825,7 @@ void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst)
mGlow[1].bindTexture(0, channel);
}
- channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_NORMAL);
+ channel = gLuminanceProgram.enableTexture(LLShaderMgr::NORMAL_MAP);
if (channel > -1)
{
// bind the normal map to get the environment mask
@@ -7632,7 +7632,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
+ channel = shader.enableTexture(LLShaderMgr::NORMAL_MAP, deferred_target->getUsage());
if (channel > -1)
{
deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT); // frag_data[2]
@@ -8667,7 +8667,7 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
LLRenderTarget* deferred_light_target = &mRT->deferredLight;
stop_glerror();
- shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
+ shader.disableTexture(LLShaderMgr::NORMAL_MAP, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage());