Merge pull request #1453 from secondlife/v-907
secondlife/viewer#907: Local PBR terrain texture transform in advanced settingsmaster
commit
193d9d5f76
|
|
@ -81,7 +81,7 @@ LLGLTFMaterial::LLGLTFMaterial()
|
|||
#endif
|
||||
}
|
||||
|
||||
void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8]) const
|
||||
void LLGLTFMaterial::TextureTransform::getPacked(Pack& packed) const
|
||||
{
|
||||
packed[0] = mScale.mV[VX];
|
||||
packed[1] = mScale.mV[VY];
|
||||
|
|
@ -92,6 +92,15 @@ void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8]) const
|
|||
packed[3] = packed[6] = packed[7] = 0.f;
|
||||
}
|
||||
|
||||
void LLGLTFMaterial::TextureTransform::getPackedTight(PackTight& packed) const
|
||||
{
|
||||
packed[0] = mScale.mV[VX];
|
||||
packed[1] = mScale.mV[VY];
|
||||
packed[2] = mRotation;
|
||||
packed[3] = mOffset.mV[VX];
|
||||
packed[4] = mOffset.mV[VY];
|
||||
}
|
||||
|
||||
bool LLGLTFMaterial::TextureTransform::operator==(const TextureTransform& other) const
|
||||
{
|
||||
return mOffset == other.mOffset && mScale == other.mScale && mRotation == other.mRotation;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,12 @@ public:
|
|||
LLVector2 mScale = { 1.f, 1.f };
|
||||
F32 mRotation = 0.f;
|
||||
|
||||
void getPacked(F32 (&packed)[8]) const;
|
||||
static const size_t PACK_SIZE = 8;
|
||||
static const size_t PACK_TIGHT_SIZE = 5;
|
||||
using Pack = F32[PACK_SIZE];
|
||||
using PackTight = F32[PACK_TIGHT_SIZE];
|
||||
void getPacked(Pack& packed) const;
|
||||
void getPackedTight(PackTight& packed) const;
|
||||
|
||||
bool operator==(const TextureTransform& other) const;
|
||||
bool operator!=(const TextureTransform& other) const { return !(*this == other); }
|
||||
|
|
@ -120,12 +125,6 @@ public:
|
|||
// heightmaps cannot currently be described as finite enclosed
|
||||
// volumes.
|
||||
// See also LLPanelRegionTerrainInfo::validateMaterials
|
||||
bool mDoubleSided = false;
|
||||
|
||||
|
||||
// These fields are local to viewer and are a part of local bitmap support
|
||||
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
|
||||
local_tex_map_t mTrackingIdToLocalTexture;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include "linden_common.h"
|
||||
#include "lltut.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "../llgltfmaterial.h"
|
||||
#include "lluuid.cpp"
|
||||
|
||||
|
|
@ -108,9 +110,9 @@ namespace tut
|
|||
|
||||
material.setAlphaCutoff(test_fraction);
|
||||
// Because this is the default value, it should append to the extras field to mark it as an override
|
||||
material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_OPAQUE);
|
||||
material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_OPAQUE, true);
|
||||
// Because this is the default value, it should append to the extras field to mark it as an override
|
||||
material.setDoubleSided(false);
|
||||
material.setDoubleSided(false, true);
|
||||
|
||||
return material;
|
||||
}
|
||||
|
|
@ -143,7 +145,7 @@ namespace tut
|
|||
#if LL_WINDOWS
|
||||
// If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial)
|
||||
// This test result will vary between compilers, so only test a single platform
|
||||
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 224);
|
||||
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 232);
|
||||
#endif
|
||||
#endif
|
||||
ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4);
|
||||
|
|
@ -366,4 +368,74 @@ namespace tut
|
|||
ensure_equals("LLGLTFMaterial: double sided override flag unset", material.mOverrideDoubleSided, false);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ensure_material_hash_pre(LLGLTFMaterial& material, T& material_field, const T new_value, const std::string& field_name)
|
||||
{
|
||||
ensure("LLGLTFMaterial: Hash: Test field " + field_name + " is part of the test material object", (
|
||||
size_t(&material_field) >= size_t(&material) &&
|
||||
(size_t(&material_field) + sizeof(material_field)) <= (size_t(&material) + sizeof(material))
|
||||
));
|
||||
ensure("LLGLTFMaterial: Hash: " + field_name + " differs and will cause a perturbation worth hashing", material_field != new_value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ensure_material_hash_not_changed(LLGLTFMaterial& material, T& material_field, const T new_value, const std::string& field_name)
|
||||
{
|
||||
ensure_material_hash_pre(material, material_field, new_value, field_name);
|
||||
|
||||
const LLGLTFMaterial old_material = material;
|
||||
material_field = new_value;
|
||||
// If this test fails, consult LLGLTFMaterial::getHash, and optionally consult http://www.catb.org/esr/structure-packing/ for guidance on optimal memory packing (effectiveness is platform-dependent)
|
||||
ensure_equals(("LLGLTFMaterial: Hash: Perturbing " + field_name + " to new value does NOT change the hash").c_str(), material.getHash(), old_material.getHash());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ensure_material_hash_changed(LLGLTFMaterial& material, T& material_field, const T new_value, const std::string& field_name)
|
||||
{
|
||||
ensure_material_hash_pre(material, material_field, new_value, field_name);
|
||||
|
||||
const LLGLTFMaterial old_material = material;
|
||||
material_field = new_value;
|
||||
// If this test fails, consult LLGLTFMaterial::getHash, and optionally consult http://www.catb.org/esr/structure-packing/ for guidance on optimal memory packing (effectiveness is platform-dependent)
|
||||
ensure_not_equals(("LLGLTFMaterial: Hash: Perturbing " + field_name + " to new value changes the hash").c_str(), material.getHash(), old_material.getHash());
|
||||
}
|
||||
|
||||
#define ENSURE_HASH_NOT_CHANGED(HASH_MAT, SOURCE_MAT, FIELD) ensure_material_hash_not_changed(HASH_MAT, HASH_MAT.FIELD, SOURCE_MAT.FIELD, #FIELD)
|
||||
#define ENSURE_HASH_CHANGED(HASH_MAT, SOURCE_MAT, FIELD) ensure_material_hash_changed(HASH_MAT, HASH_MAT.FIELD, SOURCE_MAT.FIELD, #FIELD)
|
||||
|
||||
// Test LLGLTFMaterial::getHash, which is very sensitive to the ordering of fields
|
||||
template<> template<>
|
||||
void llgltfmaterial_object_t::test<12>()
|
||||
{
|
||||
// *NOTE: Due to direct manipulation of the fields of materials
|
||||
// throughout this test, the resulting modified materials may not be
|
||||
// compliant or properly serializable.
|
||||
|
||||
// Ensure all fields of source_mat are set to values that differ from
|
||||
// LLGLTFMaterial::sDefault, even if that would result in an invalid
|
||||
// material object.
|
||||
LLGLTFMaterial source_mat = create_test_material();
|
||||
source_mat.mTrackingIdToLocalTexture[LLUUID::generateNewID()] = LLUUID::generateNewID();
|
||||
source_mat.mLocalTexDataDigest = 1;
|
||||
source_mat.mAlphaMode = LLGLTFMaterial::ALPHA_MODE_MASK;
|
||||
source_mat.mDoubleSided = true;
|
||||
|
||||
LLGLTFMaterial hash_mat;
|
||||
|
||||
ENSURE_HASH_NOT_CHANGED(hash_mat, source_mat, mTrackingIdToLocalTexture);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mLocalTexDataDigest);
|
||||
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mTextureId);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mTextureTransform);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mBaseColor);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mEmissiveColor);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mMetallicFactor);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mRoughnessFactor);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mAlphaCutoff);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mAlphaMode);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mDoubleSided);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mOverrideDoubleSided);
|
||||
ENSURE_HASH_CHANGED(hash_mat, source_mat, mOverrideAlphaMode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1179,7 +1179,9 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF)
|
||||
|
||||
llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM+1);
|
||||
mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF)
|
||||
|
||||
llassert(mReservedUniforms.size() == LLShaderMgr::TERRAIN_TEXTURE_TRANSFORMS +1);
|
||||
|
||||
mReservedUniforms.push_back("viewport");
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ public:
|
|||
TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF)
|
||||
TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF)
|
||||
|
||||
TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF)
|
||||
|
||||
VIEWPORT, // "viewport"
|
||||
LIGHT_POSITION, // "light_position"
|
||||
LIGHT_DIRECTION, // "light_direction"
|
||||
|
|
|
|||
|
|
@ -16828,6 +16828,226 @@
|
|||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>00000000-0000-0000-0000-000000000000</string>
|
||||
</map>
|
||||
<key>LocalTerrainTransform1ScaleU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset1 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform1ScaleV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset1 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform1Rotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset1 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform1OffsetU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset1 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform1OffsetV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset1 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform2ScaleU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset2 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform2ScaleV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset2 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform2Rotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset2 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform2OffsetU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset2 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform2OffsetV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset2 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform3ScaleU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset3 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform3ScaleV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset3 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform3Rotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset3 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform3OffsetU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset3 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform3OffsetV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset3 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform4ScaleU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset4 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform4ScaleV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset4 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform4Rotation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset4 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform4OffsetU</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset4 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>LocalTerrainTransform4OffsetV</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>KHR texture transform component if LocalTerrainAsset4 is set</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>PathfindingRetrieveNeighboringRegion</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
|
||||
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
#define TerrainCoord vec4[2]
|
||||
#define TerrainCoord vec4[3]
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
#define TerrainCoord vec2
|
||||
#endif
|
||||
|
|
@ -131,12 +131,16 @@ uniform vec3[4] emissiveColors;
|
|||
uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
|
||||
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
in vec4[10] vary_coords;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
in vec4[2] vary_coords;
|
||||
#endif
|
||||
in vec3 vary_position;
|
||||
in vec3 vary_normal;
|
||||
in vec3 vary_tangent;
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
in vec3 vary_tangents[4];
|
||||
flat in float vary_sign;
|
||||
#endif
|
||||
in vec4 vary_texcoord0;
|
||||
in vec4 vary_texcoord1;
|
||||
|
||||
|
|
@ -144,17 +148,26 @@ void mirrorClip(vec3 position);
|
|||
|
||||
float terrain_mix(TerrainMix tm, vec4 tms4);
|
||||
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
// from mikktspace.com
|
||||
vec3 mikktspace(vec3 vNt, vec3 vT)
|
||||
{
|
||||
vec3 vN = vary_normal;
|
||||
|
||||
vec3 vB = vary_sign * cross(vN, vT);
|
||||
vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
|
||||
|
||||
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
|
||||
|
||||
return tnorm;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
// Make sure we clip the terrain if we're in a mirror.
|
||||
mirrorClip(vary_position);
|
||||
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
TerrainCoord terrain_texcoord = vary_coords;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
TerrainCoord terrain_texcoord = vary_texcoord0.xy;
|
||||
#endif
|
||||
|
||||
float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a;
|
||||
float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a;
|
||||
float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a;
|
||||
|
|
@ -185,6 +198,16 @@ void main()
|
|||
switch (tm.type & MIX_X)
|
||||
{
|
||||
case MIX_X:
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
TerrainCoord terrain_texcoord;
|
||||
terrain_texcoord[0].xy = vary_coords[0].xy;
|
||||
terrain_texcoord[0].zw = vary_coords[0].zw;
|
||||
terrain_texcoord[1].xy = vary_coords[1].xy;
|
||||
terrain_texcoord[1].zw = vary_coords[1].zw;
|
||||
terrain_texcoord[2].xy = vary_coords[2].xy;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
TerrainCoord terrain_texcoord = vary_coords[0].xy;
|
||||
#endif
|
||||
mix2 = terrain_sample_and_multiply_pbr(
|
||||
terrain_texcoord
|
||||
, detail_0_base_color
|
||||
|
|
@ -207,6 +230,9 @@ void main()
|
|||
, emissiveColors[0]
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix2.vNt = mikktspace(mix2.vNt, vary_tangents[0]);
|
||||
#endif
|
||||
mix = mix_pbr(mix, mix2, tm.weight.x);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -215,6 +241,16 @@ void main()
|
|||
switch (tm.type & MIX_Y)
|
||||
{
|
||||
case MIX_Y:
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
TerrainCoord terrain_texcoord;
|
||||
terrain_texcoord[0].xy = vary_coords[2].zw;
|
||||
terrain_texcoord[0].zw = vary_coords[3].xy;
|
||||
terrain_texcoord[1].xy = vary_coords[3].zw;
|
||||
terrain_texcoord[1].zw = vary_coords[4].xy;
|
||||
terrain_texcoord[2].xy = vary_coords[4].zw;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
TerrainCoord terrain_texcoord = vary_coords[0].zw;
|
||||
#endif
|
||||
mix2 = terrain_sample_and_multiply_pbr(
|
||||
terrain_texcoord
|
||||
, detail_1_base_color
|
||||
|
|
@ -237,6 +273,9 @@ void main()
|
|||
, emissiveColors[1]
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix2.vNt = mikktspace(mix2.vNt, vary_tangents[1]);
|
||||
#endif
|
||||
mix = mix_pbr(mix, mix2, tm.weight.y);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -245,6 +284,16 @@ void main()
|
|||
switch (tm.type & MIX_Z)
|
||||
{
|
||||
case MIX_Z:
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
TerrainCoord terrain_texcoord;
|
||||
terrain_texcoord[0].xy = vary_coords[5].xy;
|
||||
terrain_texcoord[0].zw = vary_coords[5].zw;
|
||||
terrain_texcoord[1].xy = vary_coords[6].xy;
|
||||
terrain_texcoord[1].zw = vary_coords[6].zw;
|
||||
terrain_texcoord[2].xy = vary_coords[7].xy;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
TerrainCoord terrain_texcoord = vary_coords[1].xy;
|
||||
#endif
|
||||
mix2 = terrain_sample_and_multiply_pbr(
|
||||
terrain_texcoord
|
||||
, detail_2_base_color
|
||||
|
|
@ -267,6 +316,9 @@ void main()
|
|||
, emissiveColors[2]
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix2.vNt = mikktspace(mix2.vNt, vary_tangents[2]);
|
||||
#endif
|
||||
mix = mix_pbr(mix, mix2, tm.weight.z);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -275,6 +327,16 @@ void main()
|
|||
switch (tm.type & MIX_W)
|
||||
{
|
||||
case MIX_W:
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
TerrainCoord terrain_texcoord;
|
||||
terrain_texcoord[0].xy = vary_coords[7].zw;
|
||||
terrain_texcoord[0].zw = vary_coords[8].xy;
|
||||
terrain_texcoord[1].xy = vary_coords[8].zw;
|
||||
terrain_texcoord[1].zw = vary_coords[9].xy;
|
||||
terrain_texcoord[2].xy = vary_coords[9].zw;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
TerrainCoord terrain_texcoord = vary_coords[1].zw;
|
||||
#endif
|
||||
mix2 = terrain_sample_and_multiply_pbr(
|
||||
terrain_texcoord
|
||||
, detail_3_base_color
|
||||
|
|
@ -297,6 +359,9 @@ void main()
|
|||
, emissiveColors[3]
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix2.vNt = mikktspace(mix2.vNt, vary_tangents[3]);
|
||||
#endif
|
||||
mix = mix_pbr(mix, mix2, tm.weight.w);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -311,19 +376,11 @@ void main()
|
|||
float base_color_factor_alpha = terrain_mix(tm, vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z));
|
||||
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
// from mikktspace.com
|
||||
vec3 vNt = mix.vNt;
|
||||
vec3 vN = vary_normal;
|
||||
vec3 vT = vary_tangent.xyz;
|
||||
|
||||
vec3 vB = vary_sign * cross(vN, vT);
|
||||
vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
|
||||
|
||||
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
|
||||
vec3 tnorm = normalize(mix.vNt);
|
||||
#else
|
||||
vec3 tnorm = vary_normal;
|
||||
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
|
||||
#endif
|
||||
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
|
||||
|
||||
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
|
|
|
|||
|
|
@ -233,17 +233,12 @@ float terrain_mix(TerrainMix tm, vec4 tms4)
|
|||
// Triplanar mapping
|
||||
|
||||
// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused)
|
||||
#define TerrainCoord vec4[2]
|
||||
#define TerrainCoord vec4[3]
|
||||
|
||||
vec2 _t_uv(vec2 uv_unflipped, float sign_or_zero)
|
||||
// If sign_or_zero is positive, use uv_unflippped, otherwise use uv_flipped
|
||||
vec2 _t_uv(vec2 uv_unflipped, vec2 uv_flipped, float sign_or_zero)
|
||||
{
|
||||
// Handle case where sign is 0
|
||||
float sign = (2.0*sign_or_zero) + 1.0;
|
||||
sign /= abs(sign);
|
||||
// If the vertex normal is negative, flip the texture back
|
||||
// right-side up.
|
||||
vec2 uv = uv_unflipped * vec2(sign, 1);
|
||||
return uv;
|
||||
return mix(uv_flipped, uv_unflipped, max(0.0, sign_or_zero));
|
||||
}
|
||||
|
||||
vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero)
|
||||
|
|
@ -298,9 +293,9 @@ PBRMix terrain_sample_pbr(
|
|||
{
|
||||
PBRMix mix = init_pbr_mix();
|
||||
|
||||
#define get_uv_x() _t_uv(terrain_coord[0].zw, sign(vary_vertex_normal.x))
|
||||
#define get_uv_y() _t_uv(terrain_coord[1].xy, sign(vary_vertex_normal.y))
|
||||
#define get_uv_z() _t_uv(terrain_coord[0].xy, sign(vary_vertex_normal.z))
|
||||
#define get_uv_x() _t_uv(terrain_coord[0].zw, terrain_coord[1].zw, sign(vary_vertex_normal.x))
|
||||
#define get_uv_y() _t_uv(terrain_coord[1].xy, terrain_coord[2].xy, sign(vary_vertex_normal.y))
|
||||
#define get_uv_z() _t_uv(terrain_coord[0].xy, vec2(0), sign(vary_vertex_normal.z))
|
||||
switch (tw.type & SAMPLE_X)
|
||||
{
|
||||
case SAMPLE_X:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#define TERRAIN_PBR_DETAIL_EMISSIVE 0
|
||||
#define TERRAIN_PBR_DETAIL_OCCLUSION -1
|
||||
#define TERRAIN_PBR_DETAIL_NORMAL -2
|
||||
#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
|
||||
|
||||
uniform mat3 normal_matrix;
|
||||
uniform mat4 texture_matrix0;
|
||||
uniform mat4 modelview_matrix;
|
||||
|
|
@ -34,24 +39,28 @@ in vec4 tangent;
|
|||
in vec4 diffuse_color;
|
||||
in vec2 texcoord1;
|
||||
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
out vec4[2] vary_coords;
|
||||
#endif
|
||||
out vec3 vary_vertex_normal; // Used by pbrterrainUtilF.glsl
|
||||
out vec3 vary_normal;
|
||||
out vec3 vary_tangent;
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
out vec3 vary_tangents[4];
|
||||
flat out float vary_sign;
|
||||
#endif
|
||||
out vec4 vary_texcoord0;
|
||||
out vec4 vary_texcoord1;
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
out vec4[10] vary_coords;
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
out vec4[2] vary_coords;
|
||||
#endif
|
||||
out vec3 vary_position;
|
||||
|
||||
// *HACK: tangent_space_transform should use texture_normal_transform, or maybe
|
||||
// we shouldn't use tangent_space_transform at all. See the call to
|
||||
// tangent_space_transform below.
|
||||
uniform vec4[2] texture_base_color_transform;
|
||||
// *HACK: Each material uses only one texture transform, but the KHR texture
|
||||
// transform spec allows handling texture transforms separately for each
|
||||
// individual texture info.
|
||||
uniform vec4[5] terrain_texture_transforms;
|
||||
|
||||
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);
|
||||
vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform);
|
||||
vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -63,31 +72,101 @@ void main()
|
|||
vary_vertex_normal = normal;
|
||||
vec3 t = normal_matrix * tangent.xyz;
|
||||
|
||||
vary_tangent = normalize(t);
|
||||
// *TODO: Decide if we want this. It may be better to just calculate the
|
||||
// tangents on-the-fly in the fragment shader, due to the subtleties of the
|
||||
// effect of triplanar mapping on UVs.
|
||||
// *HACK: Should be using texture_normal_transform here. The KHR texture
|
||||
// transform spec requires handling texture transforms separately for each
|
||||
// individual texture.
|
||||
vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform, texture_matrix0));
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
{
|
||||
vec4[2] ttt;
|
||||
// material 1
|
||||
ttt[0].xyz = terrain_texture_transforms[0].xyz;
|
||||
ttt[1].x = terrain_texture_transforms[0].w;
|
||||
ttt[1].y = terrain_texture_transforms[1].x;
|
||||
vary_tangents[0] = normalize(terrain_tangent_space_transform(vec4(t, tangent.w), n, ttt));
|
||||
// material 2
|
||||
ttt[0].xyz = terrain_texture_transforms[1].yzw;
|
||||
ttt[1].xy = terrain_texture_transforms[2].xy;
|
||||
vary_tangents[1] = normalize(terrain_tangent_space_transform(vec4(t, tangent.w), n, ttt));
|
||||
// material 3
|
||||
ttt[0].xy = terrain_texture_transforms[2].zw;
|
||||
ttt[0].z = terrain_texture_transforms[3].x;
|
||||
ttt[1].xy = terrain_texture_transforms[3].yz;
|
||||
vary_tangents[2] = normalize(terrain_tangent_space_transform(vec4(t, tangent.w), n, ttt));
|
||||
// material 4
|
||||
ttt[0].x = terrain_texture_transforms[3].w;
|
||||
ttt[0].yz = terrain_texture_transforms[4].xy;
|
||||
ttt[1].xy = terrain_texture_transforms[4].zw;
|
||||
vary_tangents[3] = normalize(terrain_tangent_space_transform(vec4(t, tangent.w), n, ttt));
|
||||
}
|
||||
|
||||
vary_sign = tangent.w;
|
||||
#endif
|
||||
vary_normal = normalize(n);
|
||||
|
||||
// Transform and pass tex coords
|
||||
// *HACK: texture_base_color_transform is used for all of these here, but
|
||||
// the KHR texture transform spec requires handling texture transforms
|
||||
// separately for each individual texture.
|
||||
{
|
||||
vec4[2] ttt;
|
||||
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
|
||||
// xy
|
||||
vary_coords[0].xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0);
|
||||
// yz
|
||||
vary_coords[0].zw = texture_transform(position.yz, texture_base_color_transform, texture_matrix0);
|
||||
// (-x)z
|
||||
vary_coords[1].xy = texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform, texture_matrix0);
|
||||
// Don't care about upside-down (transform_xy_flipped())
|
||||
#define transform_xy() terrain_texture_transform(position.xy, ttt)
|
||||
#define transform_yz() terrain_texture_transform(position.yz, ttt)
|
||||
#define transform_negx_z() terrain_texture_transform(position.xz * vec2(-1, 1), ttt)
|
||||
#define transform_yz_flipped() terrain_texture_transform(position.yz * vec2(-1, 1), ttt)
|
||||
#define transform_negx_z_flipped() terrain_texture_transform(position.xz, ttt)
|
||||
// material 1
|
||||
ttt[0].xyz = terrain_texture_transforms[0].xyz;
|
||||
ttt[1].x = terrain_texture_transforms[0].w;
|
||||
ttt[1].y = terrain_texture_transforms[1].x;
|
||||
vary_coords[0].xy = transform_xy();
|
||||
vary_coords[0].zw = transform_yz();
|
||||
vary_coords[1].xy = transform_negx_z();
|
||||
vary_coords[1].zw = transform_yz_flipped();
|
||||
vary_coords[2].xy = transform_negx_z_flipped();
|
||||
// material 2
|
||||
ttt[0].xyz = terrain_texture_transforms[1].yzw;
|
||||
ttt[1].xy = terrain_texture_transforms[2].xy;
|
||||
vary_coords[2].zw = transform_xy();
|
||||
vary_coords[3].xy = transform_yz();
|
||||
vary_coords[3].zw = transform_negx_z();
|
||||
vary_coords[4].xy = transform_yz_flipped();
|
||||
vary_coords[4].zw = transform_negx_z_flipped();
|
||||
// material 3
|
||||
ttt[0].xy = terrain_texture_transforms[2].zw;
|
||||
ttt[0].z = terrain_texture_transforms[3].x;
|
||||
ttt[1].xy = terrain_texture_transforms[3].yz;
|
||||
vary_coords[5].xy = transform_xy();
|
||||
vary_coords[5].zw = transform_yz();
|
||||
vary_coords[6].xy = transform_negx_z();
|
||||
vary_coords[6].zw = transform_yz_flipped();
|
||||
vary_coords[7].xy = transform_negx_z_flipped();
|
||||
// material 4
|
||||
ttt[0].x = terrain_texture_transforms[3].w;
|
||||
ttt[0].yz = terrain_texture_transforms[4].xy;
|
||||
ttt[1].xy = terrain_texture_transforms[4].zw;
|
||||
vary_coords[7].zw = transform_xy();
|
||||
vary_coords[8].xy = transform_yz();
|
||||
vary_coords[8].zw = transform_negx_z();
|
||||
vary_coords[9].xy = transform_yz_flipped();
|
||||
vary_coords[9].zw = transform_negx_z_flipped();
|
||||
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
|
||||
vary_texcoord0.xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0);
|
||||
// material 1
|
||||
ttt[0].xyz = terrain_texture_transforms[0].xyz;
|
||||
ttt[1].x = terrain_texture_transforms[0].w;
|
||||
ttt[1].y = terrain_texture_transforms[1].x;
|
||||
vary_coords[0].xy = terrain_texture_transform(position.xy, ttt);
|
||||
// material 2
|
||||
ttt[0].xyz = terrain_texture_transforms[1].yzw;
|
||||
ttt[1].xy = terrain_texture_transforms[2].xy;
|
||||
vary_coords[0].zw = terrain_texture_transform(position.xy, ttt);
|
||||
// material 3
|
||||
ttt[0].xy = terrain_texture_transforms[2].zw;
|
||||
ttt[0].z = terrain_texture_transforms[3].x;
|
||||
ttt[1].xy = terrain_texture_transforms[3].yz;
|
||||
vary_coords[1].xy = terrain_texture_transform(position.xy, ttt);
|
||||
// material 4
|
||||
ttt[0].x = terrain_texture_transforms[3].w;
|
||||
ttt[0].yz = terrain_texture_transforms[4].xy;
|
||||
ttt[1].xy = terrain_texture_transforms[4].zw;
|
||||
vary_coords[1].zw = terrain_texture_transform(position.xy, ttt);
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 tc = vec4(texcoord1,0,1);
|
||||
vary_texcoord0.zw = tc.xy;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ vec2 khr_texture_transform(vec2 texcoord, vec2 scale, float rotation, vec2 offse
|
|||
return (transform * vec3(texcoord, 1)).xy;
|
||||
}
|
||||
|
||||
// A texture transform function for PBR materials applied to shape prims/Collada model prims
|
||||
// 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.
|
||||
|
|
@ -77,6 +78,21 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl
|
|||
return texcoord;
|
||||
}
|
||||
|
||||
// Similar to texture_transform but no offset during coordinate system
|
||||
// conversion, and no texture animation support.
|
||||
vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform)
|
||||
{
|
||||
vec2 texcoord = vertex_texcoord;
|
||||
|
||||
texcoord.y = 1.0 - texcoord.y;
|
||||
//texcoord.y = -texcoord.y;
|
||||
texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy);
|
||||
texcoord.y = 1.0 - texcoord.y;
|
||||
//texcoord.y = -texcoord.y;
|
||||
|
||||
return texcoord;
|
||||
}
|
||||
|
||||
// Take the rotation only from both transforms and apply to the tangent. This
|
||||
// accounts for the change of the topology of the normal texture when a texture
|
||||
// rotation is applied to it.
|
||||
|
|
@ -120,3 +136,26 @@ vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] kh
|
|||
|
||||
return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz);
|
||||
}
|
||||
|
||||
// Similar to tangent_space_transform but no offset during coordinate system
|
||||
// conversion, and no texture animation support.
|
||||
vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform)
|
||||
{
|
||||
// Immediately convert to left-handed coordinate system ((0,1) -> (0, -1))
|
||||
vec2 weights = vec2(0, -1);
|
||||
|
||||
// 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;
|
||||
|
||||
vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz);
|
||||
|
||||
return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials)
|
|||
// Hack! Get the region that this draw pool is rendering from!
|
||||
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
|
||||
LLVLComposition *compp = regionp->getComposition();
|
||||
LLPointer<LLFetchedGLTFMaterial> (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials;
|
||||
LLPointer<LLFetchedGLTFMaterial> (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailRenderMaterials;
|
||||
|
||||
constexpr U32 terrain_material_count = LLVLComposition::ASSET_COUNT;
|
||||
#ifdef SHOW_ASSERT
|
||||
|
|
@ -341,7 +341,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials)
|
|||
if (local_materials)
|
||||
{
|
||||
// Override region terrain with the global local override terrain
|
||||
fetched_materials = &gLocalTerrainMaterials.mDetailMaterials;
|
||||
fetched_materials = &gLocalTerrainMaterials.mDetailRenderMaterials;
|
||||
}
|
||||
const LLGLTFMaterial* materials[terrain_material_count];
|
||||
for (U32 i = 0; i < terrain_material_count; ++i)
|
||||
|
|
@ -433,21 +433,51 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials)
|
|||
llassert(shader);
|
||||
|
||||
|
||||
// *TODO: Figure out why this offset is *sometimes* producing seams at the
|
||||
// region edge, and repeat jumps when crossing regions, when
|
||||
// RenderTerrainPBRScale is not a factor of the region scale.
|
||||
LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
|
||||
F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale;
|
||||
F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale;
|
||||
// Like for PBR materials, PBR terrain texture transforms are defined by
|
||||
// the KHR_texture_transform spec, but with the following notable
|
||||
// differences:
|
||||
// 1) The PBR UV origin is defined as the Southwest corner of the region,
|
||||
// with positive U facing East and positive V facing South.
|
||||
// 2) There is an additional scaling factor RenderTerrainPBRScale. If
|
||||
// we've done our math right, RenderTerrainPBRScale should not affect the
|
||||
// overall behavior of KHR_texture_transform
|
||||
// 3) There is only one texture transform per material, whereas
|
||||
// KHR_texture_transform supports one texture transform per texture info.
|
||||
// i.e. this isn't fully compliant with KHR_texture_transform, but is
|
||||
// compliant when all texture infos used by a material have the same
|
||||
// texture transform.
|
||||
|
||||
LLGLTFMaterial::TextureTransform base_color_transform;
|
||||
base_color_transform.mScale = LLVector2(sPBRDetailScale, sPBRDetailScale);
|
||||
base_color_transform.mOffset = LLVector2(offset_x, offset_y);
|
||||
F32 base_color_packed[8];
|
||||
base_color_transform.getPacked(base_color_packed);
|
||||
// *HACK: Use the same texture repeats for all PBR terrain textures for now
|
||||
// (not compliant with KHR texture transform spec)
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed);
|
||||
LLGLTFMaterial::TextureTransform::PackTight transforms_packed[terrain_material_count];
|
||||
for (U32 i = 0; i < terrain_material_count; ++i)
|
||||
{
|
||||
const LLFetchedGLTFMaterial* fetched_material = (*fetched_materials)[i].get();
|
||||
LLGLTFMaterial::TextureTransform transform;
|
||||
if (fetched_material)
|
||||
{
|
||||
transform = fetched_material->mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR];
|
||||
#ifdef SHOW_ASSERT
|
||||
// Assert condition where the contents of the texture transforms
|
||||
// differ per texture info - we currently don't support this case.
|
||||
for (U32 ti = 1; ti < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++ti)
|
||||
{
|
||||
llassert(fetched_material->mTextureTransform[0] == fetched_material->mTextureTransform[ti]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// *NOTE: Notice here we are combining the scale from
|
||||
// RenderTerrainPBRScale into the KHR_texture_transform. This only
|
||||
// works if the scale is uniform and no other transforms are
|
||||
// applied to the terrain UVs.
|
||||
transform.mScale.mV[VX] *= sPBRDetailScale;
|
||||
transform.mScale.mV[VY] *= sPBRDetailScale;
|
||||
|
||||
transform.getPackedTight(transforms_packed[i]);
|
||||
}
|
||||
const U32 transform_param_count = LLGLTFMaterial::TextureTransform::PACK_TIGHT_SIZE * terrain_material_count;
|
||||
constexpr U32 vec4_size = 4;
|
||||
const U32 transform_vec4_count = (transform_param_count + (vec4_size - 1)) / vec4_size;
|
||||
llassert(transform_vec4_count == 5); // If false, need to update shader
|
||||
shader->uniform4fv(LLShaderMgr::TERRAIN_TEXTURE_TRANSFORMS, transform_vec4_count, (F32*)transforms_packed);
|
||||
|
||||
LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
|
||||
|
||||
|
|
|
|||
|
|
@ -691,6 +691,28 @@ void handleLocalTerrainChanged(const LLSD& newValue)
|
|||
const auto setting = gSavedSettings.getString(std::string("LocalTerrainAsset") + std::to_string(i + 1));
|
||||
const LLUUID materialID(setting);
|
||||
gLocalTerrainMaterials.setDetailAssetID(i, materialID);
|
||||
|
||||
// *NOTE: The GLTF spec allows for different texture infos to have their texture transforms set independently, but as a simplification, this debug setting only updates all the transforms in-sync (i.e. only one texture transform per terrain material).
|
||||
LLGLTFMaterial::TextureTransform transform;
|
||||
const std::string prefix = std::string("LocalTerrainTransform") + std::to_string(i + 1);
|
||||
transform.mScale.mV[VX] = gSavedSettings.getF32(prefix + "ScaleU");
|
||||
transform.mScale.mV[VY] = gSavedSettings.getF32(prefix + "ScaleV");
|
||||
transform.mRotation = gSavedSettings.getF32(prefix + "Rotation") * DEG_TO_RAD;
|
||||
transform.mOffset.mV[VX] = gSavedSettings.getF32(prefix + "OffsetU");
|
||||
transform.mOffset.mV[VY] = gSavedSettings.getF32(prefix + "OffsetV");
|
||||
LLPointer<LLGLTFMaterial> mat_override = new LLGLTFMaterial();
|
||||
for (U32 info = 0; info < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++info)
|
||||
{
|
||||
mat_override->mTextureTransform[info] = transform;
|
||||
}
|
||||
if (*mat_override == LLGLTFMaterial::sDefault)
|
||||
{
|
||||
gLocalTerrainMaterials.setMaterialOverride(i, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
gLocalTerrainMaterials.setMaterialOverride(i, mat_override);
|
||||
}
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -879,10 +901,25 @@ void settings_setup_listeners()
|
|||
setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorFarAwayDistance", handleUserImpostorDistanceChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorByDistEnabled", handleUserImpostorByDistEnabledChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "TuningFPSStrategy", handleFPSTuningStrategyChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset1", handleLocalTerrainChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset2", handleLocalTerrainChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset3", handleLocalTerrainChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset4", handleLocalTerrainChanged);
|
||||
{
|
||||
const char* transform_suffixes[] = {
|
||||
"ScaleU",
|
||||
"ScaleV",
|
||||
"Rotation",
|
||||
"OffsetU",
|
||||
"OffsetV"
|
||||
};
|
||||
for (U32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
|
||||
{
|
||||
const auto asset_setting_name = std::string("LocalTerrainAsset") + std::to_string(i + 1);
|
||||
setting_setup_signal_listener(gSavedSettings, asset_setting_name, handleLocalTerrainChanged);
|
||||
for (const char* ts : transform_suffixes)
|
||||
{
|
||||
const auto transform_setting_name = std::string("LocalTerrainTransform") + std::to_string(i + 1) + ts;
|
||||
setting_setup_signal_listener(gSavedSettings, transform_setting_name, handleLocalTerrainChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setting_setup_signal_listener(gSavedPerAccountSettings, "AvatarHoverOffsetZ", handleAvatarHoverOffsetChanged);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,9 +188,24 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id)
|
|||
mDetailTextures[asset] = fetch_terrain_texture(id);
|
||||
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[asset];
|
||||
mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id);
|
||||
mDetailRenderMaterials[asset] = nullptr;
|
||||
mMaterialTexturesSet[asset] = false;
|
||||
}
|
||||
|
||||
const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset)
|
||||
{
|
||||
return mDetailMaterialOverrides[asset];
|
||||
}
|
||||
|
||||
void LLTerrainMaterials::setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override)
|
||||
{
|
||||
// Non-null overrides must be nontrivial. Otherwise, please set the override to null instead.
|
||||
llassert(!mat_override || *mat_override != LLGLTFMaterial::sDefault);
|
||||
|
||||
mDetailMaterialOverrides[asset] = mat_override;
|
||||
mDetailRenderMaterials[asset] = nullptr;
|
||||
}
|
||||
|
||||
LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
|
@ -221,13 +236,36 @@ bool LLTerrainMaterials::texturesReady(bool boost, bool strict)
|
|||
return one_ready;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool material_asset_ready(LLFetchedGLTFMaterial* mat) { return mat && mat->isLoaded(); }
|
||||
};
|
||||
|
||||
bool LLTerrainMaterials::materialsReady(bool boost, bool strict)
|
||||
{
|
||||
bool ready[ASSET_COUNT];
|
||||
// *NOTE: Calls to materialReady may boost materials/textures. Do not early-return.
|
||||
// *NOTE: This section may boost materials/textures. Do not early-return if ready[i] is false.
|
||||
for (S32 i = 0; i < ASSET_COUNT; i++)
|
||||
{
|
||||
ready[i] = materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost, strict);
|
||||
ready[i] = false;
|
||||
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
|
||||
if (!material_asset_ready(mat)) { continue; }
|
||||
|
||||
LLPointer<LLFetchedGLTFMaterial>& render_mat = mDetailRenderMaterials[i];
|
||||
if (!render_mat)
|
||||
{
|
||||
render_mat = new LLFetchedGLTFMaterial();
|
||||
*render_mat = *mat;
|
||||
// This render_mat is effectively already loaded, because it gets its data from mat.
|
||||
|
||||
LLPointer<LLGLTFMaterial>& override_mat = mDetailMaterialOverrides[i];
|
||||
if (override_mat)
|
||||
{
|
||||
render_mat->applyOverride(*override_mat);
|
||||
}
|
||||
}
|
||||
|
||||
ready[i] = materialTexturesReady(render_mat, mMaterialTexturesSet[i], boost, strict);
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
|
@ -308,15 +346,13 @@ bool LLTerrainMaterials::textureReady(LLPointer<LLViewerFetchedTexture>& tex, bo
|
|||
return true;
|
||||
}
|
||||
|
||||
// Boost the loading priority of every known texture in the material
|
||||
// Return true when ready to use
|
||||
// Make sure to call material_asset_ready first
|
||||
// strict = true -> all materials must be sufficiently loaded
|
||||
// strict = false -> at least one material must be loaded
|
||||
// static
|
||||
bool LLTerrainMaterials::materialReady(LLPointer<LLFetchedGLTFMaterial> &mat, bool &textures_set, bool boost, bool strict)
|
||||
bool LLTerrainMaterials::materialTexturesReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict)
|
||||
{
|
||||
if (!mat || !mat->isLoaded())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
llassert(mat);
|
||||
|
||||
// Material is loaded, but textures may not be
|
||||
if (!textures_set)
|
||||
|
|
@ -357,6 +393,16 @@ bool LLTerrainMaterials::materialReady(LLPointer<LLFetchedGLTFMaterial> &mat, bo
|
|||
return true;
|
||||
}
|
||||
|
||||
// Boost the loading priority of every known texture in the material
|
||||
// Return true when ready to use
|
||||
// static
|
||||
bool LLTerrainMaterials::materialReady(LLPointer<LLFetchedGLTFMaterial> &mat, bool &textures_set, bool boost, bool strict)
|
||||
{
|
||||
if (!material_asset_ready(mat)) { return false; }
|
||||
|
||||
return materialTexturesReady(mat, textures_set, boost, strict);
|
||||
}
|
||||
|
||||
// static
|
||||
const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT]
|
||||
{
|
||||
|
|
@ -669,19 +715,20 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
|||
}
|
||||
else
|
||||
{
|
||||
tex = mDetailMaterials[i]->mBaseColorTexture;
|
||||
tex_emissive = mDetailMaterials[i]->mEmissiveTexture;
|
||||
base_color_factor = LLColor3(mDetailMaterials[i]->mBaseColor);
|
||||
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailRenderMaterials[i];
|
||||
tex = mat->mBaseColorTexture;
|
||||
tex_emissive = mat->mEmissiveTexture;
|
||||
base_color_factor = LLColor3(mat->mBaseColor);
|
||||
// *HACK: Treat alpha as black
|
||||
base_color_factor *= (mDetailMaterials[i]->mBaseColor.mV[VW]);
|
||||
emissive_factor = mDetailMaterials[i]->mEmissiveColor;
|
||||
base_color_factor *= (mat->mBaseColor.mV[VW]);
|
||||
emissive_factor = mat->mEmissiveColor;
|
||||
has_base_color_factor = (base_color_factor.mV[VX] != 1.f ||
|
||||
base_color_factor.mV[VY] != 1.f ||
|
||||
base_color_factor.mV[VZ] != 1.f);
|
||||
has_emissive_factor = (emissive_factor.mV[VX] != 1.f ||
|
||||
emissive_factor.mV[VY] != 1.f ||
|
||||
emissive_factor.mV[VZ] != 1.f);
|
||||
has_alpha = mDetailMaterials[i]->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE;
|
||||
has_alpha = mat->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE;
|
||||
}
|
||||
|
||||
if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; }
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
class LLSurface;
|
||||
|
||||
class LLViewerFetchedTexture;
|
||||
class LLGLTFMaterial;
|
||||
class LLFetchedGLTFMaterial;
|
||||
|
||||
class LLTerrainMaterials
|
||||
|
|
@ -62,6 +63,8 @@ public:
|
|||
|
||||
virtual LLUUID getDetailAssetID(S32 asset);
|
||||
virtual void setDetailAssetID(S32 asset, const LLUUID& id);
|
||||
virtual const LLGLTFMaterial* getMaterialOverride(S32 asset);
|
||||
virtual void setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override);
|
||||
Type getMaterialType();
|
||||
bool texturesReady(bool boost, bool strict);
|
||||
// strict = true -> all materials must be sufficiently loaded
|
||||
|
|
@ -74,8 +77,13 @@ protected:
|
|||
// strict = true -> all materials must be sufficiently loaded
|
||||
// strict = false -> at least one material must be loaded
|
||||
static bool materialReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict);
|
||||
// *NOTE: Prefer calling materialReady if mat is known to be LLFetchedGLTFMaterial
|
||||
static bool materialTexturesReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost, bool strict);
|
||||
|
||||
LLPointer<LLViewerFetchedTexture> mDetailTextures[ASSET_COUNT];
|
||||
LLPointer<LLFetchedGLTFMaterial> mDetailMaterials[ASSET_COUNT];
|
||||
LLPointer<LLGLTFMaterial> mDetailMaterialOverrides[ASSET_COUNT];
|
||||
LLPointer<LLFetchedGLTFMaterial> mDetailRenderMaterials[ASSET_COUNT];
|
||||
bool mMaterialTexturesSet[ASSET_COUNT];
|
||||
};
|
||||
|
||||
|
|
@ -125,9 +133,6 @@ public:
|
|||
bool getParamsReady() const { return mParamsReady; }
|
||||
|
||||
protected:
|
||||
static bool textureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost = false);
|
||||
static bool materialReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, bool boost = false);
|
||||
|
||||
bool mParamsReady = false;
|
||||
LLSurface *mSurfacep;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue