#1687 Add support for KHR_texture_transform (#1717)

master
Dave Parks 2024-06-11 13:27:54 -05:00 committed by GitHub
parent 961b6b0c7e
commit 429c92ad75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 164 additions and 34 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -45,7 +45,8 @@ namespace LL
namespace GLTF
{
static std::unordered_set<std::string> 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);

View File

@ -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;

View File

@ -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<class... Types>
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<F32>(ec); if (ec) return false;
t.y = arr[1].to_number<F32>(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)

View File

@ -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);
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.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf);
shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_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.mOcclusionTexture.mTextureTransform.getPacked(tf);
shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf);
material.mEmissiveTexture.mTextureTransform.getPacked(tf);
shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf);
}
}