diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 13074032e07c852c8bc599d87e71479560887472..c355115e8c909dfbc65c34233dc0d1ab0d3b2bc5 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1073,11 +1073,21 @@ void LLShaderMgr::initAttribsAndUniforms()
 	mReservedUniforms.push_back("texture_matrix3");
 	mReservedUniforms.push_back("object_plane_s");
 	mReservedUniforms.push_back("object_plane_t");
-    mReservedUniforms.push_back("texture_basecolor_matrix"); // GLTF
-    mReservedUniforms.push_back("texture_normal_matrix"); // GLTF
-    mReservedUniforms.push_back("texture_metallic_roughness_matrix"); // GLTF
-    mReservedUniforms.push_back("texture_emissive_matrix"); // GLTF
-    llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_MATRIX+1);
+
+    mReservedUniforms.push_back("texture_base_color_scale"); // (GLTF)
+    mReservedUniforms.push_back("texture_base_color_rotation"); // (GLTF)
+    mReservedUniforms.push_back("texture_base_color_offset"); // (GLTF)
+    mReservedUniforms.push_back("texture_normal_scale"); // (GLTF)
+    mReservedUniforms.push_back("texture_normal_rotation"); // (GLTF)
+    mReservedUniforms.push_back("texture_normal_offset"); // (GLTF)
+    mReservedUniforms.push_back("texture_metallic_roughness_scale"); // (GLTF)
+    mReservedUniforms.push_back("texture_metallic_roughness_rotation"); // (GLTF)
+    mReservedUniforms.push_back("texture_metallic_roughness_offset"); // (GLTF)
+    mReservedUniforms.push_back("texture_emissive_scale"); // (GLTF)
+    mReservedUniforms.push_back("texture_emissive_rotation"); // (GLTF)
+    mReservedUniforms.push_back("texture_emissive_offset"); // (GLTF)
+
+    llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_OFFSET+1);
 
 	mReservedUniforms.push_back("viewport");
 
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 3c8bef635abfdd1af87077104885422703cc4b7e..f7439a65af543b5aa7aa3e93bd10b30978afcb8b 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -52,10 +52,20 @@ class LLShaderMgr
         TEXTURE_MATRIX3,                    //  "texture_matrix3"
         OBJECT_PLANE_S,                     //  "object_plane_s"
         OBJECT_PLANE_T,                     //  "object_plane_t"
-        TEXTURE_BASECOLOR_MATRIX,           //  "texture_basecolor_matrix" (GLTF)
-        TEXTURE_NORMAL_MATRIX,              //  "texture_normal_matrix" (GLTF)
-        TEXTURE_METALLIC_ROUGHNESS_MATRIX,  //  "texture_metallic_roughness_matrix" (GLTF)
-        TEXTURE_EMISSIVE_MATRIX,            //  "texture_emissive_matrix" (GLTF)
+
+        TEXTURE_BASE_COLOR_SCALE,           //  "texture_base_color_scale" (GLTF)
+        TEXTURE_BASE_COLOR_ROTATION,        //  "texture_base_color_rotation" (GLTF)
+        TEXTURE_BASE_COLOR_OFFSET,          //  "texture_base_color_offset" (GLTF)
+        TEXTURE_NORMAL_SCALE,               //  "texture_normal_scale" (GLTF)
+        TEXTURE_NORMAL_ROTATION,            //  "texture_normal_rotation" (GLTF)
+        TEXTURE_NORMAL_OFFSET,              //  "texture_normal_offset" (GLTF)
+        TEXTURE_METALLIC_ROUGHNESS_SCALE,   //  "texture_metallic_roughness_scale" (GLTF)
+        TEXTURE_METALLIC_ROUGHNESS_ROTATION,//  "texture_metallic_roughness_rotation" (GLTF)
+        TEXTURE_METALLIC_ROUGHNESS_OFFSET,  //  "texture_metallic_roughness_offset" (GLTF)
+        TEXTURE_EMISSIVE_SCALE,             //  "texture_emissive_scale" (GLTF)
+        TEXTURE_EMISSIVE_ROTATION,          //  "texture_emissive_rotation" (GLTF)
+        TEXTURE_EMISSIVE_OFFSET,            //  "texture_emissive_offset" (GLTF)
+
         VIEWPORT,                           //  "viewport"
         LIGHT_POSITION,                     //  "light_position"
         LIGHT_DIRECTION,                    //  "light_direction"
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
index 24faf1763f9b7e1a87d6372e3c7e7b4eb3303d4e..a9e114dddc87d14ddc8f8517516a72c69ace7be2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
@@ -44,10 +44,18 @@ uniform mat4 modelview_matrix;
 
 out vec3 vary_position;
 
-uniform mat3 texture_basecolor_matrix;
-uniform mat3 texture_normal_matrix;
-uniform mat3 texture_metallic_roughness_matrix;
-uniform mat3 texture_emissive_matrix;
+uniform vec2 texture_base_color_scale;
+uniform float texture_base_color_rotation;
+uniform vec2 texture_base_color_offset;
+uniform vec2 texture_normal_scale;
+uniform float texture_normal_rotation;
+uniform vec2 texture_normal_offset;
+uniform vec2 texture_metallic_roughness_scale;
+uniform float texture_metallic_roughness_rotation;
+uniform vec2 texture_metallic_roughness_offset;
+uniform vec2 texture_emissive_scale;
+uniform float texture_emissive_rotation;
+uniform vec2 texture_emissive_offset;
 
 out vec3 vary_fragcoord;
 
@@ -59,7 +67,7 @@ in vec3 normal;
 in vec4 tangent;
 in vec2 texcoord0;
 
-out vec2 basecolor_texcoord;
+out vec2 base_color_texcoord;
 out vec2 normal_texcoord;
 out vec2 metallic_roughness_texcoord;
 out vec2 emissive_texcoord;
@@ -70,7 +78,7 @@ out vec3 vary_tangent;
 flat out float vary_sign;
 out vec3 vary_normal;
 
-vec2 texture_transform(vec2 vertex_texcoord, mat3 khr_gltf_transform, mat4 sl_animation_transform);
+vec2 texture_transform(vec2 vertex_texcoord, vec2 khr_gltf_scale, float khr_gltf_rotation, vec2 khr_gltf_offset, mat4 sl_animation_transform);
 
 
 void main()
@@ -89,10 +97,10 @@ void main()
 
     vary_fragcoord.xyz = vert.xyz + vec3(0,0,near_clip);
 
-	basecolor_texcoord = texture_transform(texcoord0, texture_basecolor_matrix, texture_matrix0);
-	normal_texcoord = texture_transform(texcoord0, texture_normal_matrix, texture_matrix0);
-	metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_matrix, texture_matrix0);
-	emissive_texcoord = texture_transform(texcoord0, texture_emissive_matrix, texture_matrix0);
+	base_color_texcoord = texture_transform(texcoord0, texture_base_color_scale, texture_base_color_rotation, texture_base_color_offset, texture_matrix0);
+	normal_texcoord = texture_transform(texcoord0, texture_normal_scale, texture_normal_rotation, texture_normal_offset, texture_matrix0);
+	metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_scale, texture_metallic_roughness_rotation, texture_metallic_roughness_offset, texture_matrix0);
+	emissive_texcoord = texture_transform(texcoord0, texture_emissive_scale, texture_emissive_rotation, texture_emissive_offset, texture_matrix0);
 
 #ifdef HAS_SKIN
 	vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz;
@@ -125,19 +133,23 @@ uniform mat4 modelview_matrix;
 
 out vec3 vary_position;
 
-uniform mat3 texture_basecolor_matrix;
-uniform mat3 texture_emissive_matrix;
+uniform vec2 texture_base_color_scale;
+uniform float texture_base_color_rotation;
+uniform vec2 texture_base_color_offset;
+uniform vec2 texture_emissive_scale;
+uniform float texture_emissive_rotation;
+uniform vec2 texture_emissive_offset;
 
 in vec3 position;
 in vec4 diffuse_color;
 in vec2 texcoord0;
 
-out vec2 basecolor_texcoord;
+out vec2 base_color_texcoord;
 out vec2 emissive_texcoord;
 
 out vec4 vertex_color;
 
-vec2 texture_transform(vec2 vertex_texcoord, mat3 khr_gltf_transform, mat4 sl_animation_transform);
+vec2 texture_transform(vec2 vertex_texcoord, vec2 khr_gltf_scale, float khr_gltf_rotation, vec2 khr_gltf_offset, mat4 sl_animation_transform);
 
 
 void main()
@@ -147,8 +159,8 @@ void main()
     gl_Position = vert;
     vary_position = vert.xyz;
 
-	basecolor_texcoord = texture_transform(texcoord0, texture_basecolor_matrix, texture_matrix0);
-	emissive_texcoord = texture_transform(texcoord0, texture_emissive_matrix, texture_matrix0);
+	base_color_texcoord = texture_transform(texcoord0, texture_base_color_scale, texture_base_color_rotation, texture_base_color_offset, texture_matrix0);
+	emissive_texcoord = texture_transform(texcoord0, texture_emissive_scale, texture_emissive_rotation, texture_emissive_offset, texture_matrix0);
 
 	vertex_color = diffuse_color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrglowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrglowF.glsl
index 8dc9e02f7a9e74724d811f7433f1858f6f938683..1c36aa6b5063b6e8f7ddc8d7ad438da0ca3285ea 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbrglowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrglowF.glsl
@@ -37,7 +37,7 @@ out vec4 frag_color;
 in vec3 vary_position;
 in vec4 vertex_emissive;
 
-in vec2 basecolor_texcoord;
+in vec2 base_color_texcoord;
 in vec2 emissive_texcoord;
 
 uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
@@ -47,7 +47,7 @@ vec3 srgb_to_linear(vec3 c);
 
 void main()
 {
-    vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
+    vec4 basecolor = texture2D(diffuseMap, base_color_texcoord.xy).rgba;
 
     if (basecolor.a < minimum_alpha)
     {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrglowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrglowV.glsl
index bcad1c1cebee35fef7bb20ad9a4c7df8160c3636..b73d08cf0d5db63d382f1801fcde549d14dd1b6f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbrglowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrglowV.glsl
@@ -34,20 +34,24 @@ uniform mat4 modelview_projection_matrix;
 
 uniform mat4 texture_matrix0;
 
-uniform mat3 texture_basecolor_matrix;
-uniform mat3 texture_emissive_matrix;
+uniform vec2 texture_base_color_scale;
+uniform float texture_base_color_rotation;
+uniform vec2 texture_base_color_offset;
+uniform vec2 texture_emissive_scale;
+uniform float texture_emissive_rotation;
+uniform vec2 texture_emissive_offset;
 
 in vec3 position;
 in vec4 emissive;
 
 in vec2 texcoord0;
 
-out vec2 basecolor_texcoord;
+out vec2 base_color_texcoord;
 out vec2 emissive_texcoord;
  
 out vec4 vertex_emissive;
 
-vec2 texture_transform(vec2 vertex_texcoord, mat3 khr_gltf_transform, mat4 sl_animation_transform);
+vec2 texture_transform(vec2 vertex_texcoord, vec2 khr_gltf_scale, float khr_gltf_rotation, vec2 khr_gltf_offset, mat4 sl_animation_transform);
 
 void main()
 {
@@ -64,8 +68,8 @@ void main()
     gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
 #endif
 
-    basecolor_texcoord = texture_transform(texcoord0, texture_basecolor_matrix, texture_matrix0);
-    emissive_texcoord = texture_transform(texcoord0, texture_emissive_matrix, texture_matrix0);
+    base_color_texcoord = texture_transform(texcoord0, texture_base_color_scale, texture_base_color_rotation, texture_base_color_offset, texture_matrix0);
+    emissive_texcoord = texture_transform(texcoord0, texture_emissive_scale, texture_emissive_rotation, texture_emissive_offset, texture_matrix0);
 
     vertex_emissive = emissive;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
index c4c5a7872be7c36643190d0c1b982cf74ba38910..6659e67a7abafa70597d9393ff91293135957dac 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -47,7 +47,7 @@ in vec3 vary_normal;
 in vec3 vary_tangent;
 flat in float vary_sign;
 
-in vec2 basecolor_texcoord;
+in vec2 base_color_texcoord;
 in vec2 normal_texcoord;
 in vec2 metallic_roughness_texcoord;
 in vec2 emissive_texcoord;
@@ -62,7 +62,7 @@ uniform mat3 normal_matrix;
 
 void main()
 {
-    vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
+    vec4 basecolor = texture2D(diffuseMap, base_color_texcoord.xy).rgba;
     if (basecolor.a < minimum_alpha)
     {
         discard;
@@ -121,7 +121,7 @@ out vec4 frag_color;
 in vec3 vary_position;
 in vec4 vertex_color;
 
-in vec2 basecolor_texcoord;
+in vec2 base_color_texcoord;
 in vec2 emissive_texcoord;
 
 uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
@@ -131,7 +131,7 @@ vec3 srgb_to_linear(vec3 c);
 
 void main()
 {
-    vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
+    vec4 basecolor = texture2D(diffuseMap, base_color_texcoord.xy).rgba;
     if (basecolor.a < minimum_alpha)
     {
         discard;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
index f0e3d4f034681a9e288a31bf12ba779a7c849e9d..6f50aefdab4444310edf398a9273e4ead9409c61 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
@@ -38,10 +38,18 @@ uniform mat4 modelview_projection_matrix;
 #endif
 uniform mat4 texture_matrix0;
 
-uniform mat3 texture_basecolor_matrix;
-uniform mat3 texture_normal_matrix;
-uniform mat3 texture_metallic_roughness_matrix;
-uniform mat3 texture_emissive_matrix;
+uniform vec2 texture_base_color_scale;
+uniform float texture_base_color_rotation;
+uniform vec2 texture_base_color_offset;
+uniform vec2 texture_normal_scale;
+uniform float texture_normal_rotation;
+uniform vec2 texture_normal_offset;
+uniform vec2 texture_metallic_roughness_scale;
+uniform float texture_metallic_roughness_rotation;
+uniform vec2 texture_metallic_roughness_offset;
+uniform vec2 texture_emissive_scale;
+uniform float texture_emissive_rotation;
+uniform vec2 texture_emissive_offset;
 
 in vec3 position;
 in vec4 diffuse_color;
@@ -49,7 +57,7 @@ in vec3 normal;
 in vec4 tangent;
 in vec2 texcoord0;
 
-out vec2 basecolor_texcoord;
+out vec2 base_color_texcoord;
 out vec2 normal_texcoord;
 out vec2 metallic_roughness_texcoord;
 out vec2 emissive_texcoord;
@@ -60,7 +68,7 @@ out vec3 vary_tangent;
 flat out float vary_sign;
 out vec3 vary_normal;
 
-vec2 texture_transform(vec2 vertex_texcoord, mat3 khr_gltf_transform, mat4 sl_animation_transform);
+vec2 texture_transform(vec2 vertex_texcoord, vec2 khr_gltf_scale, float khr_gltf_rotation, vec2 khr_gltf_offset, mat4 sl_animation_transform);
 
 void main()
 {
@@ -78,10 +86,10 @@ void main()
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
 #endif
 
-    basecolor_texcoord = texture_transform(texcoord0, texture_basecolor_matrix, texture_matrix0);
-    normal_texcoord = texture_transform(texcoord0, texture_normal_matrix, texture_matrix0);
-    metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_matrix, texture_matrix0);
-    emissive_texcoord = texture_transform(texcoord0, texture_emissive_matrix, texture_matrix0);
+    base_color_texcoord = texture_transform(texcoord0, texture_base_color_scale, texture_base_color_rotation, texture_base_color_offset, texture_matrix0);
+    normal_texcoord = texture_transform(texcoord0, texture_normal_scale, texture_normal_rotation, texture_normal_offset, texture_matrix0);
+    metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_scale, texture_metallic_roughness_rotation, texture_metallic_roughness_offset, texture_matrix0);
+    emissive_texcoord = texture_transform(texcoord0, texture_emissive_scale, texture_emissive_rotation, texture_emissive_offset, texture_matrix0);
 
 #ifdef HAS_SKIN
 	vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz;
@@ -106,29 +114,37 @@ uniform mat4 modelview_projection_matrix;
 
 uniform mat4 texture_matrix0;
 
-uniform mat3 texture_basecolor_matrix;
-uniform mat3 texture_normal_matrix;
-uniform mat3 texture_metallic_roughness_matrix;
-uniform mat3 texture_emissive_matrix;
+uniform vec2 texture_base_color_scale;
+uniform float texture_base_color_rotation;
+uniform vec2 texture_base_color_offset;
+uniform vec2 texture_normal_scale;
+uniform float texture_normal_rotation;
+uniform vec2 texture_normal_offset;
+uniform vec2 texture_metallic_roughness_scale;
+uniform float texture_metallic_roughness_rotation;
+uniform vec2 texture_metallic_roughness_offset;
+uniform vec2 texture_emissive_scale;
+uniform float texture_emissive_rotation;
+uniform vec2 texture_emissive_offset;
 
 in vec3 position;
 in vec4 diffuse_color;
 in vec2 texcoord0;
 
-out vec2 basecolor_texcoord;
+out vec2 base_color_texcoord;
 out vec2 emissive_texcoord;
  
 out vec4 vertex_color;
 
-vec2 texture_transform(vec2 vertex_texcoord, mat3 khr_gltf_transform, mat4 sl_animation_transform);
+vec2 texture_transform(vec2 vertex_texcoord, vec2 khr_gltf_scale, float khr_gltf_rotation, vec2 khr_gltf_offset, mat4 sl_animation_transform);
 
 void main()
 {
     //transform vertex
     gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
 
-    basecolor_texcoord = texture_transform(texcoord0, texture_basecolor_matrix, texture_matrix0);
-    emissive_texcoord = texture_transform(texcoord0, texture_emissive_matrix, texture_matrix0);
+    base_color_texcoord = texture_transform(texcoord0, texture_base_color_scale, texture_base_color_rotation, texture_base_color_offset, texture_matrix0);
+    emissive_texcoord = texture_transform(texcoord0, texture_emissive_scale, texture_emissive_rotation, texture_emissive_offset, texture_matrix0);
 
     vertex_color = diffuse_color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl
index b146c665f9682325df85628ec6bf4353938ecd50..39cc07d2d137b9aac0ff0ae329eb317817f981eb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl
@@ -23,6 +23,31 @@
  * $/LicenseInfo$
  */
 
+// This shader code is taken from the sample code on the KHR_texture_transform
+// spec page page, plus or minus some sign error corrections (I think because the GLSL
+// matrix constructor is backwards?):
+// https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform
+// Previously (6494eed242b1), we passed in a single, precalculated matrix
+// uniform per transform into the shaders. However, that was found to produce
+// small-but-noticeable discrepancies with the GLTF sample model
+// "TextureTransformTest", likely due to numerical precision differences. In
+// the interest of parity with other renderers, calculate the transform
+// directly in the shader. -Cosmic,2023-02-24
+vec2 khr_texture_transform(vec2 texcoord, vec2 scale, float rotation, vec2 offset)
+{
+    mat3 scale_mat = mat3(scale.x,0,0, 0,scale.y,0, 0,0,1);
+    mat3 offset_mat = mat3(1,0,0, 0,1,0, offset.x, offset.y, 1);
+    mat3 rotation_mat = mat3(
+        cos(rotation),-sin(rotation), 0,
+        sin(rotation), cos(rotation), 0,
+                    0,             0, 1
+    );
+
+    mat3 transform = offset_mat * rotation_mat * scale_mat;
+
+    return (transform * vec3(texcoord, 1)).xy;
+}
+
 // vertex_texcoord - The UV texture coordinates sampled from the vertex at
 //     runtime. Per SL convention, this is in a right-handed UV coordinate
 //     system. Collada models also have right-handed UVs.
@@ -33,20 +58,18 @@
 //     animations, available through LSL script functions such as
 //     LlSetTextureAnim. It assumes a right-handed UV coordinate system.
 // texcoord - The final texcoord to use for image sampling
-vec2 texture_transform(vec2 vertex_texcoord, mat3 khr_gltf_transform, mat4 sl_animation_transform)
+vec2 texture_transform(vec2 vertex_texcoord, vec2 khr_gltf_scale, float khr_gltf_rotation, vec2 khr_gltf_offset, mat4 sl_animation_transform)
 {
     vec2 texcoord = vertex_texcoord;
 
+    // Apply texture animation first to avoid shearing and other artifacts
+    texcoord = (sl_animation_transform * vec4(texcoord, 0, 1)).xy;
     // Convert to left-handed coordinate system. The offset of 1 is necessary
     // for rotations to be applied correctly.
-    // In the future, we could bake this coordinate conversion into the uniform
-    // that khr_gltf_transform comes from, since it's applied immediately
-    // before.
     texcoord.y = 1.0 - texcoord.y;
-    texcoord = (khr_gltf_transform * vec3(texcoord, 1.0)).xy;
+    texcoord = khr_texture_transform(texcoord, khr_gltf_scale, khr_gltf_rotation, khr_gltf_offset);
     // Convert back to right-handed coordinate system
     texcoord.y = 1.0 - texcoord.y;
-    texcoord = (sl_animation_transform * vec4(texcoord, 0, 1)).xy;
 
     // To make things more confusing, all SL image assets are upside-down
     // We may need an additional sign flip here when we implement a Vulkan backend
diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
index 987b0ca1d5cdb3101da7d05a2d6d6071b64eec38..2a093827cb8fc607a898d38c5fe24382fc1aaded 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
@@ -54,7 +54,7 @@ in vec3 vary_fragcoord;
 
 in vec3 vary_position;
 
-in vec2 basecolor_texcoord;
+in vec2 base_color_texcoord;
 in vec2 normal_texcoord;
 in vec2 metallic_roughness_texcoord;
 in vec2 emissive_texcoord;
@@ -168,7 +168,7 @@ void main()
 
     waterClip(pos);
 
-    vec4 basecolor = texture(diffuseMap, basecolor_texcoord.xy).rgba;
+    vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
     basecolor.rgb = srgb_to_linear(basecolor.rgb);
 #ifdef HAS_ALPHA_MASK
     if (basecolor.a < minimum_alpha)
@@ -267,7 +267,7 @@ out vec4 frag_color;
 
 in vec3 vary_position;
 
-in vec2 basecolor_texcoord;
+in vec2 base_color_texcoord;
 in vec2 emissive_texcoord;
 
 in vec4 vertex_color;
@@ -286,7 +286,7 @@ void main()
 
     vec3  pos         = vary_position;
 
-    vec4 basecolor = texture(diffuseMap, basecolor_texcoord.xy).rgba;
+    vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
     basecolor.rgb = srgb_to_linear(basecolor.rgb);
 #ifdef HAS_ALPHA_MASK
     if (basecolor.a < minimum_alpha)
diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp
index f3583daa0a991dabbc907c29f1a5f1689d522676..2f2c58aa3a19d42bb3335452ebe5f282c001eeda 100644
--- a/indra/newview/llfetchedgltfmaterial.cpp
+++ b/indra/newview/llfetchedgltfmaterial.cpp
@@ -110,14 +110,21 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex)
         shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor);
         shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV);
 
-        const LLMatrix3 base_color_matrix = mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].asMatrix();
-        shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_BASECOLOR_MATRIX, 1, false, (F32*)base_color_matrix.mMatrix);
-        const LLMatrix3 normal_matrix = mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].asMatrix();
-        shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_NORMAL_MATRIX, 1, false, (F32*)normal_matrix.mMatrix);
-        const LLMatrix3 metallic_roughness_matrix = mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].asMatrix();
-        shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_MATRIX, 1, false, (F32*)metallic_roughness_matrix.mMatrix);
-        const LLMatrix3 emissive_matrix = mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].asMatrix();
-        shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_EMISSIVE_MATRIX, 1, false, (F32*)emissive_matrix.mMatrix);
+        shader->uniform2fv(LLShaderMgr::TEXTURE_BASE_COLOR_SCALE, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].mScale.mV);
+        shader->uniform1f(LLShaderMgr::TEXTURE_BASE_COLOR_ROTATION, mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].mRotation);
+        shader->uniform2fv(LLShaderMgr::TEXTURE_BASE_COLOR_OFFSET, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].mOffset.mV);
+
+        shader->uniform2fv(LLShaderMgr::TEXTURE_NORMAL_SCALE, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].mScale.mV);
+        shader->uniform1f(LLShaderMgr::TEXTURE_NORMAL_ROTATION, mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].mRotation);
+        shader->uniform2fv(LLShaderMgr::TEXTURE_NORMAL_OFFSET, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].mOffset.mV);
+
+        shader->uniform2fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_SCALE, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].mScale.mV);
+        shader->uniform1f(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_ROTATION, mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].mRotation);
+        shader->uniform2fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_OFFSET, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].mOffset.mV);
+
+        shader->uniform2fv(LLShaderMgr::TEXTURE_EMISSIVE_SCALE, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].mScale.mV);
+        shader->uniform1f(LLShaderMgr::TEXTURE_EMISSIVE_ROTATION, mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].mRotation);
+        shader->uniform2fv(LLShaderMgr::TEXTURE_EMISSIVE_OFFSET, 1, (F32*)mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].mOffset.mV);
     }
 
 }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index fec9f1cdd11491d6ebbd47ba1a9c2b2996dc4d78..42e764b492e4ed1efed4ffc118feb78752a4129b 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -625,18 +625,24 @@ void LLVOVolume::animateTextures()
 					continue;
 				}
 		
-				if (!(result & LLViewerTextureAnim::ROTATE))
-				{
-					te->getRotation(&rot);
-				}
-				if (!(result & LLViewerTextureAnim::TRANSLATE))
-				{
-					te->getOffset(&off_s,&off_t);
-				}			
-				if (!(result & LLViewerTextureAnim::SCALE))
-				{
-					te->getScale(&scale_s, &scale_t);
-				}
+                LLGLTFMaterial *gltf_mat = te->getGLTFRenderMaterial();
+                const bool is_pbr = gltf_mat != nullptr;
+
+                if (!is_pbr)
+                {
+                    if (!(result & LLViewerTextureAnim::ROTATE))
+                    {
+                        te->getRotation(&rot);
+                    }
+                    if (!(result & LLViewerTextureAnim::TRANSLATE))
+                    {
+                        te->getOffset(&off_s,&off_t);
+                    }
+                    if (!(result & LLViewerTextureAnim::SCALE))
+                    {
+                        te->getScale(&scale_s, &scale_t);
+                    }
+                }
 
 				if (!facep->mTextureMatrix)
 				{
@@ -645,6 +651,7 @@ void LLVOVolume::animateTextures()
 
 				LLMatrix4& tex_mat = *facep->mTextureMatrix;
 				tex_mat.setIdentity();
+
 				LLVector3 trans ;
 
 					trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));