diff options
| author | Dave Parks <davep@lindenlab.com> | 2024-05-29 16:56:39 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-29 16:56:39 -0500 | 
| commit | 15fd13f83036ff781160957a21bb2d59771044bc (patch) | |
| tree | 984601482bc6d7384796123bce39b7e50074ec5a /indra | |
| parent | 2d0fe5ca7bf3bda62bf10a37a65f5859e6d1b095 (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')
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()); | 
