diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llrender/llglslshader.h | 4 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 5 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.h | 5 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 10 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 3 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl | 20 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl | 92 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.cpp | 20 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.h | 6 | ||||
| -rw-r--r-- | indra/newview/gltf/buffer_util.h | 2 | ||||
| -rw-r--r-- | indra/newview/gltf/primitive.cpp | 201 | ||||
| -rw-r--r-- | indra/newview/gltf/primitive.h | 3 | ||||
| -rw-r--r-- | indra/newview/gltfscenemanager.cpp | 19 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.cpp | 10 | 
15 files changed, 318 insertions, 84 deletions
| diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index f2b5c4881c..d42df28809 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -328,14 +328,16 @@ public:      // bit 0 = alpha mode blend (1) or opaque (0)      // bit 1 = rigged (1) or static (0)      // bit 2 = unlit (1) or lit (0) +    // bit 3 = single (0) or multi (1) uv coordinates      struct GLTFVariant      {          constexpr static U8 ALPHA_BLEND = 1;          constexpr static U8 RIGGED = 2;          constexpr static U8 UNLIT = 4; +        constexpr static U8 MULTI_UV = 8;      }; -    constexpr static U8 NUM_GLTF_VARIANTS = 8; +    constexpr static U8 NUM_GLTF_VARIANTS = 16;      std::vector<LLGLSLShader> mGLTFVariants; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 51028e5667..cfefde3acc 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1686,7 +1686,7 @@ void LLRender::flush()                  if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)                  { -                    vb->setTexCoordData(mTexcoordsp.get()); +                    vb->setTexCoord0Data(mTexcoordsp.get());                  }                  if (attribute_mask & LLVertexBuffer::MAP_COLOR) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5f30fc3879..6f4454f07a 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1180,6 +1180,11 @@ void LLShaderMgr::initAttribsAndUniforms()      mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF)      mReservedUniforms.push_back("texture_occlusion_transform"); // (GLTF)      mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF) +    mReservedUniforms.push_back("base_color_texcoord"); // (GLTF) +    mReservedUniforms.push_back("emissive_texcoord"); // (GLTF) +    mReservedUniforms.push_back("normal_texcoord"); // (GLTF) +    mReservedUniforms.push_back("metallic_roughness_texcoord"); // (GLTF) +    mReservedUniforms.push_back("occlusion_texcoord"); // (GLTF)      mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF) diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 244fc41de6..c00aff3a9a 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -58,6 +58,11 @@ public:          TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, //  "texture_metallic_roughness_transform" (GLTF)          TEXTURE_OCCLUSION_TRANSFORM,          //  "texture_occlusion_transform" (GLTF)          TEXTURE_EMISSIVE_TRANSFORM,           //  "texture_emissive_transform" (GLTF) +        BASE_COLOR_TEXCOORD,                  //  "base_color_texcoord" (GLTF) +        EMISSIVE_TEXCOORD,                    //  "emissive_texcoord" (GLTF) +        NORMAL_TEXCOORD,                      //  "normal_texcoord" (GLTF) +        METALLIC_ROUGHNESS_TEXCOORD,          //  "metallic_roughness_texcoord" (GLTF) +        OCCLUSION_TEXCOORD,                   //  "occlusion_texcoord" (GLTF)          TERRAIN_TEXTURE_TRANSFORMS,           //  "terrain_texture_transforms" (GLTF) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index a4d33c91df..33f7a6527f 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1635,7 +1635,7 @@ void LLVertexBuffer::setPositionData(const LLVector4a* data)      flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data, mMappedData);  } -void LLVertexBuffer::setTexCoordData(const LLVector2* data) +void LLVertexBuffer::setTexCoord0Data(const LLVector2* data)  {  #if !LL_DARWIN      llassert(sGLRenderBuffer == mGLBuffer); @@ -1643,6 +1643,14 @@ void LLVertexBuffer::setTexCoordData(const LLVector2* data)      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data, mMappedData);  } +void LLVertexBuffer::setTexCoord1Data(const LLVector2* data) +{ +#if !LL_DARWIN +    llassert(sGLRenderBuffer == mGLBuffer); +#endif +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + sTypeSize[TYPE_TEXCOORD1] * getNumVerts() - 1, (U8*)data, mMappedData); +} +  void LLVertexBuffer::setColorData(const LLColor4U* data)  {  #if !LL_DARWIN diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 94339191a4..66a7f2bf26 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -196,7 +196,8 @@ public:      void setTangentData(const LLVector4a* data);      void setWeight4Data(const LLVector4a* data);      void setJointData(const U64* data); -    void setTexCoordData(const LLVector2* data); +    void setTexCoord0Data(const LLVector2* data); +    void setTexCoord1Data(const LLVector2* data);      void setColorData(const LLColor4U* data);      void setIndexData(const U16* data);      void setIndexData(const U32* data); diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl index 99bfcf70fa..789c00259b 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl @@ -37,8 +37,8 @@ uniform sampler2D emissiveMap;  uniform vec3 emissiveColor;  in vec3 vary_position;  in vec4 vertex_color; -in vec2 base_color_texcoord; -in vec2 emissive_texcoord; +in vec2 base_color_uv; +in vec2 emissive_uv;  uniform float minimum_alpha;  void mirrorClip(vec3 pos); @@ -59,9 +59,9 @@ uniform float roughnessFactor;  in vec3 vary_normal;  in vec3 vary_tangent;  flat in float vary_sign; -in vec2 normal_texcoord; -in vec2 metallic_roughness_texcoord; -in vec2 occlusion_texcoord; +in vec2 normal_uv; +in vec2 metallic_roughness_uv; +in vec2 occlusion_uv;  #endif  // ================================== @@ -165,7 +165,7 @@ void main()      vec3 pos = vary_position;      mirrorClip(pos); -    vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; +    vec4 basecolor = texture(diffuseMap, base_color_uv.xy).rgba;      basecolor.rgb = srgb_to_linear(basecolor.rgb);      basecolor *= vertex_color; @@ -175,7 +175,7 @@ void main()      }      vec3 emissive = emissiveColor; -    emissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb); +    emissive *= srgb_to_linear(texture(emissiveMap, emissive_uv.xy).rgb);  // ==================================  // ================================== @@ -185,7 +185,7 @@ void main()  // ==================================  #ifndef UNLIT      // from mikktspace.com -    vec3 vNt = texture(normalMap, normal_texcoord.xy).xyz*2.0-1.0; +    vec3 vNt = texture(normalMap, normal_uv.xy).xyz*2.0-1.0;      float sign = vary_sign;      vec3 vN = vary_normal;      vec3 vT = vary_tangent.xyz; @@ -199,8 +199,8 @@ void main()      //   occlusion 1.0      //   roughness 0.0      //   metal     0.0 -    vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb; -    orm.r = texture(occlusionMap, occlusion_texcoord.xy).r; +    vec3 orm = texture(metallicRoughnessMap, metallic_roughness_uv.xy).rgb; +    orm.r = texture(occlusionMap, occlusion_uv.xy).r;      orm.g *= roughnessFactor;      orm.b *= metallicFactor;  #endif diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl index bc9a47d41e..aac3dc917f 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl @@ -33,7 +33,6 @@ uniform mat4 projection_matrix;  uniform mat3 normal_matrix;  uniform mat4 modelview_projection_matrix;  #endif -uniform mat4 texture_matrix0;  uniform vec4[2] texture_base_color_transform;  uniform vec4[2] texture_normal_transform; @@ -44,21 +43,31 @@ uniform vec4[2] texture_occlusion_transform;  in vec3 position;  in vec4 diffuse_color;  in vec2 texcoord0; -out vec2 base_color_texcoord; -out vec2 emissive_texcoord; +out vec2 base_color_uv; +out vec2 emissive_uv;  out vec4 vertex_color;  out vec3 vary_position;  #ifndef UNLIT  in vec3 normal;  in vec4 tangent; -out vec2 normal_texcoord; -out vec2 metallic_roughness_texcoord; -out vec2 occlusion_texcoord; +out vec2 normal_uv; +out vec2 metallic_roughness_uv; +out vec2 occlusion_uv;  out vec3 vary_tangent;  flat out float vary_sign;  out vec3 vary_normal; -vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); +#endif + +#ifdef MULTI_UV +in vec2 texcoord1; +uniform int base_color_texcoord; +uniform int emissive_texcoord; +#ifndef UNLIT +uniform int normal_texcoord; +uniform int metallic_roughness_texcoord; +uniform int occlusion_texcoord; +#endif  #endif  vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p) @@ -86,6 +95,36 @@ vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p)      return uvTransformed;  } +#ifndef UNLIT +vec3 gltf_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform) +{ //derived from tangent_space_transform in textureUtilV.glsl +    vec2 weights = vec2(0, 1); + +    // Convert to left-handed coordinate system +    weights.y = -weights.y; + +    // Apply KHR_texture_transform (rotation only) +    float khr_rotation = khr_gltf_transform[0].z; +    mat2 khr_rotation_mat = mat2( +        cos(khr_rotation),-sin(khr_rotation), +        sin(khr_rotation), cos(khr_rotation) +    ); +    weights = khr_rotation_mat * weights; + +    // Convert back to right-handed coordinate system +    weights.y = -weights.y; + +    // Similar to the MikkTSpace-compatible method of extracting the binormal +    // from the normal and tangent, as seen in the fragment shader +    vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz); + +    return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); + +    return vertex_tangent.xyz; +} +#endif + +  #ifdef ALPHA_BLEND  out vec3 vary_fragcoord; @@ -161,13 +200,40 @@ void main()      gl_Position = vert;  #endif -    base_color_texcoord = gltf_texture_transform(texcoord0, texture_base_color_transform); -    emissive_texcoord = gltf_texture_transform(texcoord0, texture_emissive_transform); +    vec2 bcuv; +    vec2 emuv; + +#ifdef MULTI_UV +    vec2 uv[2]; +    uv[0] = texcoord0; +    uv[1] = texcoord1; + +    bcuv = uv[base_color_texcoord]; +    emuv = uv[emissive_texcoord]; +#else +    bcuv = texcoord0; +    emuv = texcoord0; +#endif + +    base_color_uv = gltf_texture_transform(bcuv, texture_base_color_transform); +    emissive_uv = gltf_texture_transform(emuv, texture_emissive_transform);  #ifndef UNLIT -    normal_texcoord = gltf_texture_transform(texcoord0, texture_normal_transform); -    metallic_roughness_texcoord = gltf_texture_transform(texcoord0, texture_metallic_roughness_transform); -    occlusion_texcoord = gltf_texture_transform(texcoord0, texture_occlusion_transform); +    vec2 normuv; +    vec2 rmuv; +    vec2 ouv; +#ifdef MULTI_UV +    normuv = uv[normal_texcoord]; +    rmuv = uv[metallic_roughness_texcoord]; +    ouv = uv[occlusion_texcoord]; +#else +    normuv = texcoord0; +    rmuv = texcoord0; +    ouv = texcoord0; +#endif +    normal_uv = gltf_texture_transform(normuv, texture_normal_transform); +    metallic_roughness_uv = gltf_texture_transform(rmuv, texture_metallic_roughness_transform); +    occlusion_uv = gltf_texture_transform(ouv, texture_occlusion_transform);  #endif  #ifndef UNLIT @@ -180,7 +246,7 @@ void main()  #endif      n = normalize(n); -    vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform, texture_matrix0)); +    vary_tangent = normalize(gltf_tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform));      vary_sign = tangent.w;      vary_normal = n;  #endif diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 4c1da3e645..21be69aae2 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -910,6 +910,24 @@ void Material::TextureInfo::serialize(object& dst) const      write_extensions(dst, &mTextureTransform, "KHR_texture_transform");  } +S32 Material::TextureInfo::getTexCoord() const +{ +    if (mTextureTransform.mPresent && mTextureTransform.mTexCoord != INVALID_INDEX) +    { +        return mTextureTransform.mTexCoord; +    } +    return mTexCoord; +} + +bool Material::isMultiUV() const +{ +    return mPbrMetallicRoughness.mBaseColorTexture.getTexCoord() != 0 || +        mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord() != 0 || +        mNormalTexture.getTexCoord() != 0 || +        mOcclusionTexture.getTexCoord() != 0 || +        mEmissiveTexture.getTexCoord() != 0; +} +  const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)  {      if (src.is_object()) @@ -1048,7 +1066,7 @@ void TextureTransform::serialize(object& dst) const      write(mOffset, "offset", dst, vec2(0.f, 0.f));      write(mRotation, "rotation", dst, 0.f);      write(mScale, "scale", dst, vec2(1.f, 1.f)); -    write(mTexCoord, "texCoord", dst, 0); +    write(mTexCoord, "texCoord", dst, -1);  } diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index bca269d5dc..ea3f7d480a 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -102,6 +102,10 @@ namespace LL                  bool operator==(const TextureInfo& rhs) const;                  bool operator!=(const TextureInfo& rhs) const; +                // get the UV channel that should be used for sampling this texture +                // returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord +                S32 getTexCoord() const; +                  const TextureInfo& operator=(const Value& src);                  void serialize(boost::json::object& dst) const;              }; @@ -152,6 +156,8 @@ namespace LL              bool mDoubleSided = false;              Unlit mUnlit; +            bool isMultiUV() const; +              const Material& operator=(const Value& src);              void serialize(boost::json::object& dst) const;          }; diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h index 943a1748f9..c1101818b7 100644 --- a/indra/newview/gltf/buffer_util.h +++ b/indra/newview/gltf/buffer_util.h @@ -826,7 +826,7 @@ namespace LL                  if (arr.size() == 2)                  {                      std::error_code ec; -                    vec3 t; +                    vec2 t;                      t.x = arr[0].to_number<F32>(ec); if (ec) return false;                      t.y = arr[1].to_number<F32>(ec); if (ec) return false; diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index bc333aff69..4cff0622b3 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -42,13 +42,14 @@ using namespace boost::json;  // Mesh data useful for Mikktspace tangent generation (and flat normal generation)  struct MikktMesh  { -    std::vector<LLVector3> p; -    std::vector<LLVector3> n; -    std::vector<LLVector2> tc; -    std::vector<LLVector4> w; -    std::vector<LLVector4> t; -    std::vector<LLColor4U> c; -    std::vector<U64> j; +    std::vector<LLVector3> p;       //positions +    std::vector<LLVector3> n;       //normals +    std::vector<LLVector4> t;       //tangents +    std::vector<LLVector2> tc0;     //texcoords 0 +    std::vector<LLVector2> tc1;     //texcoords 1 +    std::vector<LLColor4U> c;       //colors +    std::vector<LLVector4> w;       //weights +    std::vector<U64> j;             //joints      // initialize from src primitive and make an unrolled triangle list      // returns false if the Primitive cannot be converted to a triangle list @@ -57,15 +58,28 @@ struct MikktMesh          bool indexed = !prim->mIndexArray.empty();          U32 vert_count = indexed ? prim->mIndexArray.size() : prim->mPositions.size(); -        if (prim->mMode != Primitive::Mode::TRIANGLES) +        U32 triangle_count = 0; + +        if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP || +            prim->mMode == Primitive::Mode::TRIANGLE_FAN) +        { +            triangle_count = vert_count - 2; +        } +        else if (prim->mMode == Primitive::Mode::TRIANGLES)          { -            LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32) prim->mMode << LL_ENDL; +            triangle_count = vert_count / 3; +        } +        else +        { +            LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32)prim->mMode << LL_ENDL;              return false;          } +        vert_count = triangle_count * 3; +          p.resize(vert_count);          n.resize(vert_count); -        tc.resize(vert_count); +        tc0.resize(vert_count);          c.resize(vert_count);          bool has_normals = !prim->mNormals.empty(); @@ -78,6 +92,7 @@ struct MikktMesh          {              t.resize(vert_count);          } +          bool rigged = !prim->mWeights.empty();          if (rigged)          { @@ -85,23 +100,69 @@ struct MikktMesh              j.resize(vert_count);          } -        for (int i = 0; i < vert_count; ++i) +        bool multi_uv = !prim->mTexCoords1.empty(); +        if (multi_uv)          { -            U32 idx = indexed ? prim->mIndexArray[i] : i; +            tc1.resize(vert_count); +        } -            p[i].set(prim->mPositions[idx].getF32ptr()); -            tc[i].set(prim->mTexCoords[idx]); -            c[i] = prim->mColors[idx]; +        for (int tri_idx = 0; tri_idx < triangle_count; ++tri_idx) +        { +            U32 idx[3]; + +            if (prim->mMode == Primitive::Mode::TRIANGLES) +            { +                idx[0] = tri_idx * 3; +                idx[1] = tri_idx * 3 + 1; +                idx[2] = tri_idx * 3 + 2; +            } +            else if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP) +            { +                idx[0] = tri_idx; +                idx[1] = tri_idx + 1; +                idx[2] = tri_idx + 2; -            if (has_normals) +                if (tri_idx % 2 != 0) +                { +                    std::swap(idx[1], idx[2]); +                } +            } +            else if (prim->mMode == Primitive::Mode::TRIANGLE_FAN)              { -                n[i].set(prim->mNormals[idx].getF32ptr()); +                idx[0] = 0; +                idx[1] = tri_idx + 1; +                idx[2] = tri_idx + 2;              } -            if (rigged) +            if (indexed)              { -                w[i].set(prim->mWeights[idx].getF32ptr()); -                j[i] = prim->mJoints[idx]; +                idx[0] = prim->mIndexArray[idx[0]]; +                idx[1] = prim->mIndexArray[idx[1]]; +                idx[2] = prim->mIndexArray[idx[2]]; +            } + +            for (U32 v = 0; v < 3; ++v) +            { +                U32 i = tri_idx * 3 + v; +                p[i].set(prim->mPositions[idx[v]].getF32ptr()); +                tc0[i].set(prim->mTexCoords0[idx[v]]); +                c[i] = prim->mColors[idx[v]]; + +                if (multi_uv) +                { +                    tc1[i].set(prim->mTexCoords1[idx[v]]); +                } + +                if (has_normals) +                { +                    n[i].set(prim->mNormals[idx[v]].getF32ptr()); +                } + +                if (rigged) +                { +                    w[i].set(prim->mWeights[idx[v]].getF32ptr()); +                    j[i] = prim->mJoints[idx[v]]; +                }              }          } @@ -138,25 +199,34 @@ struct MikktMesh      void write(Primitive* prim) const      {          //re-weld -        meshopt_Stream mos[] = +        std::vector<meshopt_Stream> mos =          {              { &p[0], sizeof(LLVector3), sizeof(LLVector3) },              { &n[0], sizeof(LLVector3), sizeof(LLVector3) },              { &t[0], sizeof(LLVector4), sizeof(LLVector4) }, -            { &tc[0], sizeof(LLVector2), sizeof(LLVector2) }, -            { &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }, -            { w.empty() ? nullptr : &w[0], sizeof(LLVector4), sizeof(LLVector4) }, -            { j.empty() ? nullptr : &j[0], sizeof(U64), sizeof(U64) } +            { &tc0[0], sizeof(LLVector2), sizeof(LLVector2) }, +            { &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }          }; +        if (!w.empty()) +        { +            mos.push_back({ &w[0], sizeof(LLVector4), sizeof(LLVector4) }); +            mos.push_back({ &j[0], sizeof(U64), sizeof(U64) }); +        } + +        if (!tc1.empty()) +        { +            mos.push_back({ &tc1[0], sizeof(LLVector2), sizeof(LLVector2) }); +        } +          std::vector<U32> remap;          remap.resize(p.size()); -        U32 stream_count = w.empty() ? 5 : 7; +        U32 stream_count = mos.size(); -        size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, p.size(), p.size(), mos, stream_count); +        size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, p.size(), p.size(), mos.data(), stream_count); -        prim->mTexCoords.resize(vert_count); +        prim->mTexCoords0.resize(vert_count);          prim->mNormals.resize(vert_count);          prim->mTangents.resize(vert_count);          prim->mPositions.resize(vert_count); @@ -166,6 +236,10 @@ struct MikktMesh              prim->mWeights.resize(vert_count);              prim->mJoints.resize(vert_count);          } +        if (!tc1.empty()) +                    { +            prim->mTexCoords1.resize(vert_count); +        }          prim->mIndexArray.resize(remap.size()); @@ -178,7 +252,7 @@ struct MikktMesh              prim->mPositions[dst_idx].load3(p[src_idx].mV);              prim->mNormals[dst_idx].load3(n[src_idx].mV); -            prim->mTexCoords[dst_idx] = tc[src_idx]; +            prim->mTexCoords0[dst_idx] = tc0[src_idx];              prim->mTangents[dst_idx].loadua(t[src_idx].mV);              prim->mColors[dst_idx] = c[src_idx]; @@ -187,6 +261,11 @@ struct MikktMesh                  prim->mWeights[dst_idx].loadua(w[src_idx].mV);                  prim->mJoints[dst_idx] = j[src_idx];              } + +            if (!tc1.empty()) +            { +                prim->mTexCoords1[dst_idx] = tc1[src_idx]; +            }          }          prim->mGLMode = LLRender::TRIANGLES; @@ -210,8 +289,8 @@ struct MikktMesh      mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)      { -        F32* uv = tc[face_num * 3 + vert_num].mV; -        return mikk::float3(uv[0], uv[1], 1.0f); +        F32* uv = tc0[face_num * 3 + vert_num].mV; +        return mikk::float3(uv[0], 1.f-uv[1], 1.0f);      }      mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) @@ -228,6 +307,14 @@ struct MikktMesh  }; +static void vertical_flip(std::vector<LLVector2>& texcoords) +{ +    for (auto& tc : texcoords) +    { +        tc[1] = 1.f - tc[1]; +    } +} +  bool Primitive::prep(Asset& asset)  {      // allocate vertex buffer @@ -261,7 +348,11 @@ bool Primitive::prep(Asset& asset)          }          else if (attribName == "TEXCOORD_0")          { -            copy(asset, accessor, mTexCoords); +            copy(asset, accessor, mTexCoords0); +        } +        else if (attribName == "TEXCOORD_1") +        { +            copy(asset, accessor, mTexCoords1);          }          else if (attribName == "JOINTS_0")          { @@ -297,24 +388,28 @@ bool Primitive::prep(Asset& asset)          mask |= LLVertexBuffer::MAP_JOINT;      } -    if (mTexCoords.empty()) +    if (mTexCoords0.empty())      { -        mTexCoords.resize(mPositions.size()); +        mTexCoords0.resize(mPositions.size());      } -    // TODO: support more than one texcoord set (or no texcoords)      mask |= LLVertexBuffer::MAP_TEXCOORD0; +    if (!mTexCoords1.empty()) +    { +        mask |= LLVertexBuffer::MAP_TEXCOORD1; +    } +      if (mColors.empty())      {          mColors.resize(mPositions.size(), LLColor4U::white);      } +    mShaderVariant = 0; +      // TODO: support colorless vertex buffers      mask |= LLVertexBuffer::MAP_COLOR; -    mShaderVariant = 0; -      bool unlit = false;      // bake material basecolor into color array @@ -332,6 +427,11 @@ bool Primitive::prep(Asset& asset)              mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;              unlit = true;          } + +        if (material.isMultiUV()) +        { +            mShaderVariant |= LLGLSLShader::GLTFVariant::MULTI_UV; +        }      }      if (mNormals.empty() && !unlit) @@ -434,15 +534,17 @@ bool Primitive::prep(Asset& asset)      }      // flip texcoord y, upload, then flip back (keep the off-spec data in vram only) -    for (auto& tc : mTexCoords) -    { -        tc[1] = 1.f - tc[1]; -    } -    mVertexBuffer->setTexCoordData(mTexCoords.data()); -    for (auto& tc : mTexCoords) +    vertical_flip(mTexCoords0); +    mVertexBuffer->setTexCoord0Data(mTexCoords0.data()); +    vertical_flip(mTexCoords0); + +    if (!mTexCoords1.empty())      { -        tc[1] = 1.f - tc[1]; +        vertical_flip(mTexCoords1); +        mVertexBuffer->setTexCoord1Data(mTexCoords1.data()); +        vertical_flip(mTexCoords1);      } +          if (!mIndexArray.empty())      { @@ -453,10 +555,13 @@ bool Primitive::prep(Asset& asset)      mVertexBuffer->unbind(); -    Material& material = asset.mMaterials[mMaterial]; -    if (material.mAlphaMode == Material::AlphaMode::BLEND) +    if (mMaterial != INVALID_INDEX)      { -        mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; +        Material& material = asset.mMaterials[mMaterial]; +        if (material.mAlphaMode == Material::AlphaMode::BLEND) +        { +            mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; +        }      }      return true; @@ -614,7 +719,7 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,      //create a proxy LLVolumeFace for the raycast      LLVolumeFace face;      face.mPositions = mPositions.data(); -    face.mTexCoords = mTexCoords.data(); +    face.mTexCoords = mTexCoords0.data();      face.mNormals = mNormals.data();      face.mTangents = mTangents.data();      face.mIndices = nullptr; // unreferenced diff --git a/indra/newview/gltf/primitive.h b/indra/newview/gltf/primitive.h index f9d7c63c65..7cc05cf831 100644 --- a/indra/newview/gltf/primitive.h +++ b/indra/newview/gltf/primitive.h @@ -58,7 +58,8 @@ namespace LL              LLPointer<LLVertexBuffer> mVertexBuffer;              // CPU copy of mesh data, keep these as LLVector types for compatibility with raycasting code -            std::vector<LLVector2> mTexCoords; +            std::vector<LLVector2> mTexCoords0; +            std::vector<LLVector2> mTexCoords1;              std::vector<LLVector4a> mNormals;              std::vector<LLVector4a> mTangents;              std::vector<LLVector4a> mPositions; diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index b390afee37..16f362b3e4 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -549,10 +549,16 @@ void GLTFSceneManager::render(bool opaque, bool rigged, bool unlit)  void GLTFSceneManager::render(U8 variant)  { -    // for debugging, just render the whole scene as opaque -    // by traversing the whole scenegraph -    // Assumes camera transform is already set and -    // appropriate shader is already boundd +    // just render the whole scene by traversing the whole scenegraph +    // Assumes camera transform is already set and appropriate shader is already bound. +    // Eventually we'll want a smarter render pipe that has pre-sorted the scene graph +    // into buckets by material and shader. + +    // HACK -- implicitly render multi-uv variant +    if (!(variant & LLGLSLShader::GLTFVariant::MULTI_UV)) +    { +        render((U8) (variant | LLGLSLShader::GLTFVariant::MULTI_UV)); +    }      gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -732,6 +738,7 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)      F32 tf[8];      material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf);      shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf); +    shader->uniform1i(LLShaderMgr::BASE_COLOR_TEXCOORD, material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord());      if (!LLPipeline::sShadowRender)      { @@ -748,15 +755,19 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)          material.mNormalTexture.mTextureTransform.getPacked(tf);          shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::NORMAL_TEXCOORD, material.mNormalTexture.getTexCoord());          material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf);          shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::METALLIC_ROUGHNESS_TEXCOORD, material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord());          material.mOcclusionTexture.mTextureTransform.getPacked(tf);          shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::OCCLUSION_TEXCOORD, material.mOcclusionTexture.getTexCoord());          material.mEmissiveTexture.mTextureTransform.getPacked(tf);          shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::EMISSIVE_TEXCOORD, material.mEmissiveTexture.getTexCoord());      }  } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d43d6fea37..5913e7ba6f 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, bool unlit, bool use_sun_shadow) +static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged, bool unlit, bool multi_uv, bool use_sun_shadow)  {      variant.mName = shader.mName.c_str();      variant.mFeatures = shader.mFeatures; @@ -271,6 +271,11 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool          variant.addPermutation("UNLIT", "1");      } +    if (multi_uv) +    { +        variant.addPermutation("MULTI_UV", "1"); +    } +      if (alpha_blend)      {          variant.addPermutation("ALPHA_BLEND", "1"); @@ -317,8 +322,9 @@ static bool make_gltf_variants(LLGLSLShader& shader, bool use_sun_shadow)          bool alpha_blend = i & LLGLSLShader::GLTFVariant::ALPHA_BLEND;          bool rigged = i & LLGLSLShader::GLTFVariant::RIGGED;          bool unlit = i & LLGLSLShader::GLTFVariant::UNLIT; +        bool multi_uv = i & LLGLSLShader::GLTFVariant::MULTI_UV; -        if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, use_sun_shadow)) +        if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, multi_uv, use_sun_shadow))          {              return false;          } | 
