From 429c92ad75fd3b3f7b9dfc52ed034b25004a3b9c Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 11 Jun 2024 13:27:54 -0500 Subject: #1687 Add support for KHR_texture_transform (#1717) --- indra/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 1 + .../shaders/class1/gltf/pbrmetallicroughnessF.glsl | 3 +- .../shaders/class1/gltf/pbrmetallicroughnessV.glsl | 37 +++++++++++++--- indra/newview/gltf/asset.cpp | 51 +++++++++++++++++++--- indra/newview/gltf/asset.h | 17 ++++++++ indra/newview/gltf/buffer_util.h | 37 +++++++++++++++- indra/newview/gltfscenemanager.cpp | 51 ++++++++++++++-------- 8 files changed, 164 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 4d53df5f06..5f30fc3879 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1178,6 +1178,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF) mReservedUniforms.push_back("texture_normal_transform"); // (GLTF) 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("terrain_texture_transforms"); // (GLTF) diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 53e3d010db..244fc41de6 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -56,6 +56,7 @@ public: TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF) TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF) TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF) + TEXTURE_OCCLUSION_TRANSFORM, // "texture_occlusion_transform" (GLTF) TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF) TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF) diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl index d71a3fad99..99bfcf70fa 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl @@ -61,6 +61,7 @@ in vec3 vary_tangent; flat in float vary_sign; in vec2 normal_texcoord; in vec2 metallic_roughness_texcoord; +in vec2 occlusion_texcoord; #endif // ================================== @@ -199,7 +200,7 @@ void main() // roughness 0.0 // metal 0.0 vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb; - orm.r = texture(occlusionMap, metallic_roughness_texcoord.xy).r; + orm.r = texture(occlusionMap, occlusion_texcoord.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 f123c29101..bc9a47d41e 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl @@ -39,6 +39,7 @@ uniform vec4[2] texture_base_color_transform; uniform vec4[2] texture_normal_transform; uniform vec4[2] texture_metallic_roughness_transform; uniform vec4[2] texture_emissive_transform; +uniform vec4[2] texture_occlusion_transform; in vec3 position; in vec4 diffuse_color; @@ -53,13 +54,37 @@ in vec3 normal; in vec4 tangent; out vec2 normal_texcoord; out vec2 metallic_roughness_texcoord; +out vec2 occlusion_texcoord; 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 -vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); +vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p) +{ + texcoord.y = 1.0 - texcoord.y; + + vec2 Scale = p[0].xy; + float Rotation = -p[0].z; + vec2 Offset = vec2(p[0].w, p[1].x); + + mat3 translation = mat3(1,0,0, 0,1,0, Offset.x, Offset.y, 1); + mat3 rotation = mat3( + cos(Rotation), sin(Rotation), 0, + -sin(Rotation), cos(Rotation), 0, + 0, 0, 1); + + mat3 scale = mat3(Scale.x,0,0, 0,Scale.y,0, 0,0,1); + + mat3 matrix = translation * rotation * scale; + + vec2 uvTransformed = ( matrix * vec3(texcoord.xy, 1) ).xy; + + uvTransformed.y = 1.0 - uvTransformed.y; + + return uvTransformed; +} #ifdef ALPHA_BLEND @@ -136,14 +161,14 @@ void main() gl_Position = vert; #endif - base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); - emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0); + base_color_texcoord = gltf_texture_transform(texcoord0, texture_base_color_transform); + emissive_texcoord = gltf_texture_transform(texcoord0, texture_emissive_transform); #ifndef UNLIT - normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0); - metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_transform, texture_matrix0); + 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); #endif - #ifndef UNLIT #ifdef HAS_SKIN diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index a4efb25860..4c1da3e645 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -45,7 +45,8 @@ namespace LL namespace GLTF { static std::unordered_set ExtensionsSupported = { - "KHR_materials_unlit" + "KHR_materials_unlit", + "KHR_texture_transform" }; Material::AlphaMode gltf_alpha_mode_to_enum(const std::string& alpha_mode) @@ -906,6 +907,7 @@ void Material::TextureInfo::serialize(object& dst) const { write(mIndex, "index", dst, INVALID_INDEX); write(mTexCoord, "texCoord", dst, 0); + write_extensions(dst, &mTextureTransform, "KHR_texture_transform"); } const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src) @@ -914,6 +916,7 @@ const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src) { copy(src, "index", mIndex); copy(src, "texCoord", mTexCoord); + copy_extensions(src, "KHR_texture_transform", &mTextureTransform); } return *this; @@ -931,17 +934,16 @@ bool Material::TextureInfo::operator!=(const Material::TextureInfo& rhs) const void Material::OcclusionTextureInfo::serialize(object& dst) const { - write(mIndex, "index", dst, INVALID_INDEX); - write(mTexCoord, "texCoord", dst, 0); + TextureInfo::serialize(dst); write(mStrength, "strength", dst, 1.f); } const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src) { + TextureInfo::operator=(src); + if (src.is_object()) { - copy(src, "index", mIndex); - copy(src, "texCoord", mTexCoord); copy(src, "strength", mStrength); } @@ -950,13 +952,13 @@ const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=( void Material::NormalTextureInfo::serialize(object& dst) const { - write(mIndex, "index", dst, INVALID_INDEX); - write(mTexCoord, "texCoord", dst, 0); + TextureInfo::serialize(dst); write(mScale, "scale", dst, 1.f); } const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src) { + TextureInfo::operator=(src); if (src.is_object()) { copy(src, "index", mIndex); @@ -1015,6 +1017,41 @@ void Material::Unlit::serialize(object& dst) const // no members and object has already been created, nothing to do } +void TextureTransform::getPacked(F32* packed) const +{ + packed[0] = mScale.x; + packed[1] = mScale.y; + packed[2] = mRotation; + packed[3] = mOffset.x; + packed[4] = mOffset.y; + + packed[5] = packed[6] = packed[7] = 0.f; +} + + +const TextureTransform& TextureTransform::operator=(const Value& src) +{ + mPresent = true; + if (src.is_object()) + { + copy(src, "offset", mOffset); + copy(src, "rotation", mRotation); + copy(src, "scale", mScale); + copy(src, "texCoord", mTexCoord); + } + + return *this; +} + +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); +} + + void Material::serialize(object& dst) const { write(mName, "name", dst); diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 8f28e5905f..bca269d5dc 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -57,6 +57,21 @@ namespace LL bool mPresent = false; }; + class TextureTransform : public Extension // KHR_texture_transform implementation + { + public: + vec2 mOffset = vec2(0.f, 0.f); + F32 mRotation = 0.f; + vec2 mScale = vec2(1.f, 1.f); + S32 mTexCoord = INVALID_INDEX; + + // get the texture transform as a packed array of floats + // dst MUST point to at least 8 floats + void getPacked(F32* dst) const; + + const TextureTransform& operator=(const Value& src); + void serialize(boost::json::object& dst) const; + }; class Material { @@ -82,6 +97,8 @@ namespace LL S32 mIndex = INVALID_INDEX; S32 mTexCoord = 0; + TextureTransform mTextureTransform; + bool operator==(const TextureInfo& rhs) const; bool operator!=(const TextureInfo& rhs) const; diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h index c26752a6b6..943a1748f9 100644 --- a/indra/newview/gltf/buffer_util.h +++ b/indra/newview/gltf/buffer_util.h @@ -590,8 +590,8 @@ namespace LL // Write all extensions to dst.extensions // Usage: // write_extensions(dst, - // "KHR_materials_unlit", mUnlit, - // "KHR_materials_pbrSpecularGlossiness", mPbrSpecularGlossiness); + // mUnlit, "KHR_materials_unlit", + // mPbrSpecularGlossiness, "KHR_materials_pbrSpecularGlossiness"); // returns true if any of the extensions are written template inline bool write_extensions(boost::json::object& dst, Types... args) @@ -816,6 +816,39 @@ namespace LL return true; } + // vec2 + template<> + inline bool copy(const Value& src, vec2& dst) + { + if (src.is_array()) + { + const boost::json::array& arr = src.as_array(); + if (arr.size() == 2) + { + std::error_code ec; + vec3 t; + t.x = arr[0].to_number(ec); if (ec) return false; + t.y = arr[1].to_number(ec); if (ec) return false; + + dst = t; + return true; + } + } + return false; + } + + template<> + inline bool write(const vec2& src, Value& dst) + { + dst = boost::json::array(); + boost::json::array& arr = dst.as_array(); + arr.resize(2); + arr[0] = src.x; + arr[1] = src.y; + + return true; + } + // bool template<> inline bool copy(const Value& src, bool& dst) diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index d7eb605489..b390afee37 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -663,11 +663,30 @@ static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info, { if (info.mIndex != INVALID_INDEX) { - LLViewerTexture* tex = asset.mImages[asset.mTextures[info.mIndex].mSource].mTexture; + Texture& texture = asset.mTextures[info.mIndex]; + + LLViewerTexture* tex = asset.mImages[texture.mSource].mTexture; if (tex) { tex->addTextureStats(2048.f * 2048.f); - LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex); + S32 channel = LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex); + + if (channel != -1 && texture.mSampler != -1) + { // set sampler state + Sampler& sampler = asset.mSamplers[texture.mSampler]; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sampler.mWrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, sampler.mWrapT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler.mMagFilter); + + // NOTE: do not set min filter. Always respect client preference for min filter + } + else + { + // set default sampler state + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } } else { @@ -710,10 +729,9 @@ void GLTFSceneManager::bind(Asset& asset, Material& material) 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); + F32 tf[8]; + material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf); + shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf); if (!LLPipeline::sShadowRender) { @@ -728,20 +746,17 @@ void GLTFSceneManager::bind(Asset& asset, Material& material) 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); + material.mNormalTexture.mTextureTransform.getPacked(tf); + shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf); + + material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf); + shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf); - 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); + material.mOcclusionTexture.mTextureTransform.getPacked(tf); + shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf); - 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); + material.mEmissiveTexture.mTextureTransform.getPacked(tf); + shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf); } } -- cgit v1.2.3