# Conflicts:
#	indra/llimage/llimage.cpp
#	indra/llrender/llvertexbuffer.h
#	indra/newview/app_settings/settings.xml
#	indra/newview/lldrawpoolterrain.cpp
#	indra/newview/lldynamictexture.cpp
#	indra/newview/lltexturectrl.cpp
#	indra/newview/llviewercontrol.cpp
#	indra/newview/llviewertexture.cpp
#	indra/newview/pipeline.cpp
#	indra/newview/skins/default/xui/en/panel_region_terrain.xml
master
Ansariel 2024-01-23 16:03:33 +01:00
commit 4d2549969c
54 changed files with 3046 additions and 473 deletions

View File

@ -31,6 +31,7 @@
#include "llmath.h"
#include "v4coloru.h"
#include "v3color.h"
#include "llimagebmp.h"
#include "llimagetga.h"
@ -1045,6 +1046,34 @@ bool LLImageRaw::optimizeAwayAlpha()
return false;
}
bool LLImageRaw::makeAlpha()
{
if (getComponents() == 3)
{
U8* data = getData();
U32 pixels = getWidth() * getHeight();
// alpha channel doesn't exist, make a new copy of data with alpha channel
U8* new_data = (U8*) ll_aligned_malloc_16(getWidth() * getHeight() * 4);
for (U32 i = 0; i < pixels; ++i)
{
U32 di = i * 4;
U32 si = i * 3;
for (U32 j = 0; j < 3; ++j)
{
new_data[di+j] = data[si+j];
}
}
setDataAndSize(new_data, getWidth(), getHeight(), 3);
return true;
}
return false;
}
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
@ -1130,7 +1159,7 @@ void LLImageRaw::composite( LLImageRaw* src )
}
// <FS:Beq> These assertions are nonsense.
// llassert(3 == src->getComponents());
// llassert((3 == src->getComponents()) || (4 == src->getComponents()));
// llassert(3 == dst->getComponents());
// </FS:Beq>
if( 3 == dst->getComponents() )
@ -1310,6 +1339,30 @@ void LLImageRaw::fill( const LLColor4U& color )
}
}
void LLImageRaw::tint( const LLColor3& color )
{
llassert( (3 == getComponents()) || (4 == getComponents()) );
if (isBufferInvalid())
{
LL_WARNS() << "Invalid image buffer" << LL_ENDL;
return;
}
S32 pixels = getWidth() * getHeight();
const S32 components = getComponents();
U8* data = getData();
for( S32 i = 0; i < pixels; i++ )
{
const float c0 = data[0] * color.mV[0];
const float c1 = data[1] * color.mV[1];
const float c2 = data[2] * color.mV[2];
data[0] = llclamp((U8)c0, 0, 255);
data[1] = llclamp((U8)c1, 0, 255);
data[2] = llclamp((U8)c2, 0, 255);
data += components;
}
}
LLPointer<LLImageRaw> LLImageRaw::duplicate()
{
if(getNumRefs() < 2)

View File

@ -33,7 +33,7 @@
#include "lltrace.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048
const S32 MAX_IMAGE_MIP = 12; // 4096x4096
// *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number
// of levels is read from the header's file, not inferred from its size.
@ -44,7 +44,7 @@ const S32 MAX_DISCARD_LEVEL = 5;
// and declared right here. Some come from the JPEG2000 spec, some conventions specific to SL.
const S32 MAX_DECOMPOSITION_LEVELS = 32; // Number of decomposition levels cannot exceed 32 according to jpeg2000 spec
const S32 MIN_DECOMPOSITION_LEVELS = 5; // the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is)
const S32 MAX_PRECINCT_SIZE = 2048; // No reason to be bigger than MAX_IMAGE_SIZE
const S32 MAX_PRECINCT_SIZE = 4096; // No reason to be bigger than MAX_IMAGE_SIZE
const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE
const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks
const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec
@ -52,11 +52,11 @@ const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after hea
const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit)
const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2
const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048
const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 4096
const S32 MIN_IMAGE_AREA = MIN_IMAGE_SIZE * MIN_IMAGE_SIZE;
const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
const S32 MAX_IMAGE_COMPONENTS = 8;
const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //2048 * 2048 * 8 = 16 MB
const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //4096 * 4096 * 8 = 128 MB
// Note! These CANNOT be changed without modifying simulator code
// *TODO: change both to 1024 when SIM texture fetching is deprecated
@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496;
class LLImageFormatted;
class LLImageRaw;
class LLColor4U;
class LLColor3;
typedef enum e_image_codec
{
@ -219,6 +220,8 @@ public:
// if the alpha channel is all 100% opaque, delete it
// returns true if alpha channel was deleted
bool optimizeAwayAlpha();
// Create an alpha channel if this image doesn't have one
bool makeAlpha();
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
@ -232,6 +235,9 @@ public:
// Fill the buffer with a constant color
void fill( const LLColor4U& color );
// Multiply this raw image by the given color
void tint( const LLColor3& color );
// Copy operations
//duplicate this raw image if refCount > 1.

View File

@ -65,7 +65,6 @@ class LLCamera
: public LLCoordFrame
{
public:
LLCamera(const LLCamera& rhs)
{
*this = rhs;

View File

@ -6512,9 +6512,6 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
return TRUE;
}
void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent);
void LLVolumeFace::createTangents()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
@ -6532,7 +6529,7 @@ void LLVolumeFace::createTangents()
(*ptr++).clear();
}
CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents);
LLCalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents);
//normalize normals
for (U32 i = 0; i < mNumVertices; i++)
@ -7242,7 +7239,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
}
//adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME

View File

@ -1157,6 +1157,8 @@ private:
std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent);
BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size);

View File

@ -56,6 +56,7 @@ public:
bool hasAlphaMask = false;
bool hasReflectionProbes = false;
bool attachNothing = false;
bool isPBRTerrain = false; // include: shaders\class1\deferred\pbrterrainUtilF.glsl
};
// ============= Structure for caching shader uniforms ===============

View File

@ -42,7 +42,7 @@ class LLGLTexture : public LLTexture
public:
enum
{
MAX_IMAGE_SIZE_DEFAULT = 1024,
MAX_IMAGE_SIZE_DEFAULT = 2048,
INVALID_DISCARD_LEVEL = 0x7fff
};

View File

@ -277,6 +277,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
if (features->isPBRTerrain)
{
if (!shader->attachFragmentObject("deferred/pbrterrainUtilF.glsl"))
{
return FALSE;
}
}
// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->hasAtmospherics)
{
@ -1392,8 +1400,32 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("detail_1");
mReservedUniforms.push_back("detail_2");
mReservedUniforms.push_back("detail_3");
mReservedUniforms.push_back("alpha_ramp");
mReservedUniforms.push_back("detail_0_base_color");
mReservedUniforms.push_back("detail_1_base_color");
mReservedUniforms.push_back("detail_2_base_color");
mReservedUniforms.push_back("detail_3_base_color");
mReservedUniforms.push_back("detail_0_normal");
mReservedUniforms.push_back("detail_1_normal");
mReservedUniforms.push_back("detail_2_normal");
mReservedUniforms.push_back("detail_3_normal");
mReservedUniforms.push_back("detail_0_metallic_roughness");
mReservedUniforms.push_back("detail_1_metallic_roughness");
mReservedUniforms.push_back("detail_2_metallic_roughness");
mReservedUniforms.push_back("detail_3_metallic_roughness");
mReservedUniforms.push_back("detail_0_emissive");
mReservedUniforms.push_back("detail_1_emissive");
mReservedUniforms.push_back("detail_2_emissive");
mReservedUniforms.push_back("detail_3_emissive");
mReservedUniforms.push_back("baseColorFactors");
mReservedUniforms.push_back("metallicFactors");
mReservedUniforms.push_back("roughnessFactors");
mReservedUniforms.push_back("emissiveColors");
mReservedUniforms.push_back("minimum_alphas");
mReservedUniforms.push_back("origin");
mReservedUniforms.push_back("display_gamma");

View File

@ -264,8 +264,32 @@ public:
TERRAIN_DETAIL1, // "detail_1"
TERRAIN_DETAIL2, // "detail_2"
TERRAIN_DETAIL3, // "detail_3"
TERRAIN_ALPHARAMP, // "alpha_ramp"
TERRAIN_DETAIL0_BASE_COLOR, // "detail_0_base_color" (GLTF)
TERRAIN_DETAIL1_BASE_COLOR, // "detail_1_base_color" (GLTF)
TERRAIN_DETAIL2_BASE_COLOR, // "detail_2_base_color" (GLTF)
TERRAIN_DETAIL3_BASE_COLOR, // "detail_3_base_color" (GLTF)
TERRAIN_DETAIL0_NORMAL, // "detail_0_normal" (GLTF)
TERRAIN_DETAIL1_NORMAL, // "detail_1_normal" (GLTF)
TERRAIN_DETAIL2_NORMAL, // "detail_2_normal" (GLTF)
TERRAIN_DETAIL3_NORMAL, // "detail_3_normal" (GLTF)
TERRAIN_DETAIL0_METALLIC_ROUGHNESS, // "detail_0_metallic_roughness" (GLTF)
TERRAIN_DETAIL1_METALLIC_ROUGHNESS, // "detail_1_metallic_roughness" (GLTF)
TERRAIN_DETAIL2_METALLIC_ROUGHNESS, // "detail_2_metallic_roughness" (GLTF)
TERRAIN_DETAIL3_METALLIC_ROUGHNESS, // "detail_3_metallic_roughness" (GLTF)
TERRAIN_DETAIL0_EMISSIVE, // "detail_0_emissive" (GLTF)
TERRAIN_DETAIL1_EMISSIVE, // "detail_1_emissive" (GLTF)
TERRAIN_DETAIL2_EMISSIVE, // "detail_2_emissive" (GLTF)
TERRAIN_DETAIL3_EMISSIVE, // "detail_3_emissive" (GLTF)
TERRAIN_BASE_COLOR_FACTORS, // "baseColorFactors" (GLTF)
TERRAIN_METALLIC_FACTORS, // "metallicFactors" (GLTF)
TERRAIN_ROUGHNESS_FACTORS, // "roughnessFactors" (GLTF)
TERRAIN_EMISSIVE_COLORS, // "emissiveColors" (GLTF)
TERRAIN_MINIMUM_ALPHAS, // "minimum_alphas" (GLTF)
SHINY_ORIGIN, // "origin"
DISPLAY_GAMMA, // "display_gamma"

View File

@ -1335,6 +1335,10 @@ bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, U32 index,
{
return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
return VertexBufferStrider<LLVector4a, TYPE_NORMAL>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count);

View File

@ -180,6 +180,7 @@ public:
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getNormalStrider(LLStrider<LLVector4a>& strider, U32 index = 0, S32 count = -1);
bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
@ -191,10 +192,6 @@ public:
bool getWeight4Strider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getClothWeightStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
// </FS:Ansariel>
bool getBasecolorTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getNormalTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getMetallicRoughnessTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getEmissiveTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
void setPositionData(const LLVector4a* data);
void setTexCoordData(const LLVector2* data);

View File

@ -423,6 +423,7 @@ set(viewer_SOURCE_FILES
llgiveinventory.cpp
llglsandbox.cpp
llgltfmateriallist.cpp
llgltfmaterialpreviewmgr.cpp
llgroupactions.cpp
llgroupiconctrl.cpp
llgrouplist.cpp
@ -1216,6 +1217,7 @@ set(viewer_HEADER_FILES
llgesturemgr.h
llgiveinventory.h
llgltfmateriallist.h
llgltfmaterialpreviewmgr.h
llgroupactions.h
llgroupiconctrl.h
llgrouplist.h

View File

@ -13787,7 +13787,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>2.0</real>
<real>1.0</real>
</map>
<key>RendeSkyAutoAdjustBlueHorizonScale</key>
<map>
@ -13942,7 +13942,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>RenderTerrainScale</key>
<map>
<key>Comment</key>
<string>Terrain detail texture scale</string>
<string>Terrain detail texture scale (meters)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -13950,6 +13950,50 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<real>12.0</real>
</map>
<key>RenderTerrainPBRDetail</key>
<map>
<key>Comment</key>
<string>Detail level for PBR terrain. 0 is full detail. Negative values drop rendering features in accordance with the GLTF specification, which reduces the number of texture binds. Some Intel and Mac graphics drivers do not support more than 16 texture binds. Because PBR terrain exceeds this limit at the highest detail level, reducing texture binds is necessary for compatibility.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderTerrainPBRScale</key>
<map>
<key>Comment</key>
<string>PBR terrain detail texture scale (meters)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>4.0</real>
</map>
<key>RenderTerrainPBRPlanarSampleCount</key>
<map>
<key>Comment</key>
<string>How many UV planes to sample PBR terrain textures from. 1 is "flat", 3 is triplanar mapping (aka box mapping)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>3</real>
</map>
<key>RenderTerrainPBRTriplanarBlendFactor</key>
<map>
<key>Comment</key>
<string>Higher values create sharper transitions, but are more likely to produce artifacts.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>8.0</real>
</map>
<key>FSATIFullTextureMem</key>
<map>
<key>Comment</key>
@ -19436,7 +19480,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>2048</integer>
<integer>1024</integer>
</map>
<key>max_texture_dimension_Y</key>
<map>
@ -19447,7 +19491,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>2048</integer>
<integer>1024</integer>
</map>
<!-- End of back compatibility settings -->
<key>teleport_offer_invitation_max_length</key>
@ -20985,6 +21029,50 @@ Change of this parameter will affect the layout of buttons in notification toast
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LocalTerrainAsset1</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LocalTerrainAsset2</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LocalTerrainAsset3</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LocalTerrainAsset4</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>PathfindingRetrieveNeighboringRegion</key>
<map>

View File

@ -0,0 +1,272 @@
/**
* @file class1\deferred\terrainF.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
/*[EXTRA_CODE_HERE]*/
#define TERRAIN_PBR_DETAIL_EMISSIVE 0
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
#define TerrainCoord vec4[2]
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
#define TerrainCoord vec2
#endif
#define MIX_X 1 << 3
#define MIX_Y 1 << 4
#define MIX_Z 1 << 5
#define MIX_W 1 << 6
// TODO: Decide if this struct needs to be declared
struct TerrainMix
{
vec4 weight;
int type;
};
TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal);
// TODO: Decide if this struct needs to be declared
struct PBRMix
{
vec4 col; // RGB color with alpha, linear space
vec3 orm; // Occlusion, roughness, metallic
vec3 vNt; // Unpacked normal texture sample, vector
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
vec3 emissive; // RGB emissive color, linear space
#endif
};
PBRMix init_pbr_mix();
PBRMix terrain_sample_and_multiply_pbr(
TerrainCoord terrain_coord
, sampler2D tex_col
, sampler2D tex_orm
, sampler2D tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
, vec4 factor_col
, vec3 factor_orm
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, vec3 factor_emissive
#endif
);
PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight);
out vec4 frag_data[4];
uniform sampler2D alpha_ramp;
// *TODO: More configurable quality level which disables PBR features on machines
// with limited texture availability
// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures
uniform sampler2D detail_0_base_color;
uniform sampler2D detail_1_base_color;
uniform sampler2D detail_2_base_color;
uniform sampler2D detail_3_base_color;
uniform sampler2D detail_0_normal;
uniform sampler2D detail_1_normal;
uniform sampler2D detail_2_normal;
uniform sampler2D detail_3_normal;
uniform sampler2D detail_0_metallic_roughness;
uniform sampler2D detail_1_metallic_roughness;
uniform sampler2D detail_2_metallic_roughness;
uniform sampler2D detail_3_metallic_roughness;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
uniform sampler2D detail_0_emissive;
uniform sampler2D detail_1_emissive;
uniform sampler2D detail_2_emissive;
uniform sampler2D detail_3_emissive;
#endif
uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl
uniform vec4 metallicFactors;
uniform vec4 roughnessFactors;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
uniform vec3[4] emissiveColors;
#endif
uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
in vec4[2] vary_coords;
#endif
in vec3 vary_normal;
in vec3 vary_tangent;
flat in float vary_sign;
in vec4 vary_texcoord0;
in vec4 vary_texcoord1;
vec2 encode_normal(vec3 n);
float terrain_mix(TerrainMix tm, vec4 tms4);
void main()
{
#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;
TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal);
// RGB = Occlusion, Roughness, Metal
// default values, see LLViewerTexture::sDefaultPBRORMImagep
// occlusion 1.0
// roughness 0.0
// metal 0.0
vec3[4] orm_factors;
orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x);
orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y);
orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z);
orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w);
PBRMix mix = init_pbr_mix();
PBRMix mix2;
switch (tm.type & MIX_X)
{
case MIX_X:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_0_base_color
, detail_0_metallic_roughness
, detail_0_normal
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_0_emissive
#endif
, baseColorFactors[0]
, orm_factors[0]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[0]
#endif
);
mix = mix_pbr(mix, mix2, tm.weight.x);
break;
default:
break;
}
switch (tm.type & MIX_Y)
{
case MIX_Y:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_1_base_color
, detail_1_metallic_roughness
, detail_1_normal
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_1_emissive
#endif
, baseColorFactors[1]
, orm_factors[1]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[1]
#endif
);
mix = mix_pbr(mix, mix2, tm.weight.y);
break;
default:
break;
}
switch (tm.type & MIX_Z)
{
case MIX_Z:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_2_base_color
, detail_2_metallic_roughness
, detail_2_normal
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_2_emissive
#endif
, baseColorFactors[2]
, orm_factors[2]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[2]
#endif
);
mix = mix_pbr(mix, mix2, tm.weight.z);
break;
default:
break;
}
switch (tm.type & MIX_W)
{
case MIX_W:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_3_base_color
, detail_3_metallic_roughness
, detail_3_normal
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_3_emissive
#endif
, baseColorFactors[3]
, orm_factors[3]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[3]
#endif
);
mix = mix_pbr(mix, mix2, tm.weight.w);
break;
default:
break;
}
float minimum_alpha = terrain_mix(tm, minimum_alphas);
if (mix.col.a < minimum_alpha)
{
discard;
}
float base_color_factor_alpha = terrain_mix(tm, vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z));
// 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;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
#define emissive mix.emissive
#else
#define emissive vec3(0)
#endif
frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse
frag_data[1] = max(vec4(mix.orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal.
frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags
frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive
}

View File

@ -0,0 +1,396 @@
/**
* @file class1\deferred\pbrterrainUtilF.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
/*[EXTRA_CODE_HERE]*/
/**
* Triplanar mapping implementation adapted from Inigo Quilez' example shader,
* MIT license.
* https://www.shadertoy.com/view/MtsGWH
* Copyright © 2015 Inigo Quilez
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: The above copyright
* notice and this permission notice shall be included in all copies or
* substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
* WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define TERRAIN_PBR_DETAIL_EMISSIVE 0
in vec3 vary_vertex_normal;
vec3 srgb_to_linear(vec3 c);
// A relatively agressive threshold for terrain material mixing sampling
// cutoff. This ensures that only one or two materials are used in most places,
// making PBR terrain blending more performant. Should be greater than 0 to work.
#define TERRAIN_RAMP_MIX_THRESHOLD 0.1
// A small threshold for triplanar mapping sampling cutoff. This and
// TERRAIN_TRIPLANAR_BLEND_FACTOR together ensures that only one or two samples
// per texture are used in most places, making triplanar mapping more
// performant. Should be greater than 0 to work.
// There's also an artistic design choice in the use of these factors, and the
// use of triplanar generally. Don't take these triplanar constants for granted.
#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01
#define SAMPLE_X 1 << 0
#define SAMPLE_Y 1 << 1
#define SAMPLE_Z 1 << 2
#define MIX_X 1 << 3
#define MIX_Y 1 << 4
#define MIX_Z 1 << 5
#define MIX_W 1 << 6
struct PBRMix
{
vec4 col; // RGB color with alpha, linear space
vec3 orm; // Occlusion, roughness, metallic
vec3 vNt; // Unpacked normal texture sample, vector
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
vec3 emissive; // RGB emissive color, linear space
#endif
};
PBRMix init_pbr_mix()
{
PBRMix mix;
mix.col = vec4(0);
mix.orm = vec3(0);
mix.vNt = vec3(0);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive = vec3(0);
#endif
return mix;
}
// Usage example, for two weights:
// vec2 weights = ... // Weights must add up to 1
// PBRMix mix = init_pbr_mix();
// PBRMix mix1 = ...
// mix = mix_pbr(mix, mix1, weights.x);
// PBRMix mix2 = ...
// mix = mix_pbr(mix, mix2, weights.y);
PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight)
{
PBRMix mix;
mix.col = mix1.col + (mix2.col * mix2_weight);
mix.orm = mix1.orm + (mix2.orm * mix2_weight);
mix.vNt = mix1.vNt + (mix2.vNt * mix2_weight);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive = mix1.emissive + (mix2.emissive * mix2_weight);
#endif
return mix;
}
PBRMix sample_pbr(
vec2 uv
, sampler2D tex_col
, sampler2D tex_orm
, sampler2D tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
)
{
PBRMix mix;
mix.col = texture(tex_col, uv);
mix.col.rgb = srgb_to_linear(mix.col.rgb);
mix.orm = texture(tex_orm, uv).xyz;
mix.vNt = texture(tex_vNt, uv).xyz*2.0-1.0;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive = srgb_to_linear(texture(tex_emissive, uv).xyz);
#endif
return mix;
}
struct TerrainTriplanar
{
vec3 weight;
int type;
};
struct TerrainMix
{
vec4 weight;
int type;
};
#define TerrainMixSample vec4[4]
#define TerrainMixSample3 vec3[4]
TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal)
{
TerrainMix tm;
vec4 sample_x = vec4(1,0,0,0);
vec4 sample_y = vec4(0,1,0,0);
vec4 sample_z = vec4(0,0,1,0);
vec4 sample_w = vec4(0,0,0,1);
tm.weight = mix( mix(sample_w, sample_z, alpha2), mix(sample_y, sample_x, alpha1), alphaFinal );
tm.weight -= TERRAIN_RAMP_MIX_THRESHOLD;
ivec4 usage = max(ivec4(0), ivec4(ceil(tm.weight)));
// Prevent negative weights and keep weights balanced
tm.weight = tm.weight*vec4(usage);
tm.weight /= (tm.weight.x + tm.weight.y + tm.weight.z + tm.weight.w);
tm.type = (usage.x * MIX_X) |
(usage.y * MIX_Y) |
(usage.z * MIX_Z) |
(usage.w * MIX_W);
return tm;
}
TerrainTriplanar _t_triplanar()
{
float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR;
float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD;
vec3 weight_signed = pow(abs(vary_vertex_normal), vec3(sharpness));
weight_signed /= (weight_signed.x + weight_signed.y + weight_signed.z);
weight_signed -= vec3(threshold);
TerrainTriplanar tw;
// *NOTE: Make sure the threshold doesn't affect the materials
tw.weight = max(vec3(0), weight_signed);
tw.weight /= (tw.weight.x + tw.weight.y + tw.weight.z);
ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed))));
tw.type = ((usage.x) * SAMPLE_X) |
((usage.y) * SAMPLE_Y) |
((usage.z) * SAMPLE_Z);
return tw;
}
// Assume weights add to 1
float terrain_mix(TerrainMix tm, vec4 tms4)
{
return (tm.weight.x * tms4[0]) +
(tm.weight.y * tms4[1]) +
(tm.weight.z * tms4[2]) +
(tm.weight.w * tms4[3]);
}
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
// Triplanar mapping
// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused)
#define TerrainCoord vec4[2]
vec2 _t_uv(vec2 uv_unflipped, 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;
}
vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero)
{
// Assume normal is unpacked
vec3 vNt1 = vNt0;
// Get sign
float sign = sign_or_zero;
// Handle case where sign is 0
sign = (2.0*sign) + 1.0;
sign /= abs(sign);
// If the sign is negative, rotate normal by 180 degrees
vNt1.xy = (min(0, sign) * vNt1.xy) + (min(0, -sign) * -vNt1.xy);
return vNt1;
}
// Triplanar-specific normal texture fixes
vec3 _t_normal_post_x(vec3 vNt0)
{
vec3 vNt_x = _t_normal_post_1(vNt0, sign(vary_vertex_normal.x));
// *HACK: Transform normals according to orientation of the UVs
vNt_x.xy = vec2(-vNt_x.y, vNt_x.x);
return vNt_x;
}
vec3 _t_normal_post_y(vec3 vNt0)
{
vec3 vNt_y = _t_normal_post_1(vNt0, sign(vary_vertex_normal.y));
// *HACK: Transform normals according to orientation of the UVs
vNt_y.xy = -vNt_y.xy;
return vNt_y;
}
vec3 _t_normal_post_z(vec3 vNt0)
{
vec3 vNt_z = _t_normal_post_1(vNt0, sign(vary_vertex_normal.z));
return vNt_z;
}
PBRMix terrain_sample_pbr(
TerrainCoord terrain_coord
, TerrainTriplanar tw
, sampler2D tex_col
, sampler2D tex_orm
, sampler2D tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
)
{
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))
switch (tw.type & SAMPLE_X)
{
case SAMPLE_X:
PBRMix mix_x = sample_pbr(
get_uv_x()
, tex_col
, tex_orm
, tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
// Triplanar-specific normal texture fix
mix_x.vNt = _t_normal_post_x(mix_x.vNt);
mix = mix_pbr(mix, mix_x, tw.weight.x);
break;
default:
break;
}
switch (tw.type & SAMPLE_Y)
{
case SAMPLE_Y:
PBRMix mix_y = sample_pbr(
get_uv_y()
, tex_col
, tex_orm
, tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
// Triplanar-specific normal texture fix
mix_y.vNt = _t_normal_post_y(mix_y.vNt);
mix = mix_pbr(mix, mix_y, tw.weight.y);
break;
default:
break;
}
switch (tw.type & SAMPLE_Z)
{
case SAMPLE_Z:
PBRMix mix_z = sample_pbr(
get_uv_z()
, tex_col
, tex_orm
, tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
// Triplanar-specific normal texture fix
// *NOTE: Bottom face has not been tested
mix_z.vNt = _t_normal_post_z(mix_z.vNt);
mix = mix_pbr(mix, mix_z, tw.weight.z);
break;
default:
break;
}
return mix;
}
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
#define TerrainCoord vec2
#define terrain_sample_pbr sample_pbr
#endif
PBRMix multiply_factors_pbr(
PBRMix mix_in
, vec4 factor_col
, vec3 factor_orm
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, vec3 factor_emissive
#endif
)
{
PBRMix mix = mix_in;
mix.col *= factor_col;
mix.orm *= factor_orm;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive *= factor_emissive;
#endif
return mix;
}
PBRMix terrain_sample_and_multiply_pbr(
TerrainCoord terrain_coord
, sampler2D tex_col
, sampler2D tex_orm
, sampler2D tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
, vec4 factor_col
, vec3 factor_orm
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, vec3 factor_emissive
#endif
)
{
PBRMix mix = terrain_sample_pbr(
terrain_coord
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
, _t_triplanar()
#endif
, tex_col
, tex_orm
, tex_vNt
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
mix = multiply_factors_pbr(mix
, factor_col
, factor_orm
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, factor_emissive
#endif
);
return mix;
}

View File

@ -0,0 +1,93 @@
/**
* @file class1\environment\pbrterrainV.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix;
in vec3 position;
in vec3 normal;
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;
flat out float vary_sign;
out vec4 vary_texcoord0;
out vec4 vary_texcoord1;
// *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;
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);
void main()
{
//transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vec3 n = normal_matrix * normal;
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));
vary_sign = tangent.w;
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.
#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);
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
vary_texcoord0.xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0);
#endif
vec4 tc = vec4(texcoord1,0,1);
vary_texcoord0.zw = tc.xy;
vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0);
vary_texcoord1.zw = tc.xy-vec2(1.0, 0.0);
}

View File

@ -30,7 +30,6 @@ uniform mat4 modelview_projection_matrix;
in vec3 position;
in vec3 normal;
in vec4 diffuse_color;
in vec2 texcoord0;
in vec2 texcoord1;
out vec3 pos;
@ -41,18 +40,16 @@ out vec4 vary_texcoord1;
uniform vec4 object_plane_s;
uniform vec4 object_plane_t;
vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
vec2 texgen_object(vec4 vpos, mat4 mat, vec4 tp0, vec4 tp1)
{
vec4 tcoord;
tcoord.x = dot(vpos, tp0);
tcoord.y = dot(vpos, tp1);
tcoord.z = tc.z;
tcoord.w = tc.w;
tcoord = mat * tcoord;
return tcoord;
return tcoord.xy;
}
void main()
@ -67,7 +64,7 @@ void main()
vary_normal = normalize(normal_matrix * normal);
// Transform and pass tex coords
vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy;
vary_texcoord0.xy = texgen_object(vec4(position, 1.0), texture_matrix0, object_plane_s, object_plane_t);
vec4 t = vec4(texcoord1,0,1);

View File

@ -65,7 +65,7 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl
// 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.
// for rotation and scale to be applied correctly.
texcoord.y = 1.0 - texcoord.y;
texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy);
// Convert back to right-handed coordinate system

View File

@ -48,6 +48,8 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRDetail 1 0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTreeLODFactor 1 1.0
RenderVBOEnable 1 1
RenderVBOMappingDisable 1 1
@ -94,6 +96,7 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTerrainPBRPlanarSampleCount 1 1
RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.5
RenderDeferredSSAO 1 0
@ -123,6 +126,7 @@ RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTerrainPBRPlanarSampleCount 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
RenderDeferredSSAO 1 0
@ -150,6 +154,7 @@ RenderLocalLightCount 1 512
RenderTransparentWater 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
RenderDeferredSSAO 1 0
@ -179,6 +184,7 @@ RenderLocalLightCount 1 1024
RenderTransparentWater 1 1
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
RenderDeferredSSAO 1 0
@ -208,6 +214,7 @@ RenderLocalLightCount 1 2048
RenderTransparentWater 1 1
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
RenderDeferredSSAO 1 1
@ -236,6 +243,7 @@ RenderMaxPartCount 1 4096
RenderLocalLightCount 1 4096
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
@ -264,6 +272,7 @@ RenderLocalLightCount 1 8192
RenderMaxPartCount 1 8192
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 3.0
@ -321,3 +330,5 @@ RenderFSAASamples 0 0
RenderReflectionsEnabled 0 0
RenderReflectionProbeDetail 0 0
list TexUnit16orLess
RenderTerrainPBRDetail 1 -1

View File

@ -45,6 +45,7 @@ RenderObjectBump 1 1
RenderLocalLightCount 1 4096
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVBOEnable 1 1
@ -89,6 +90,7 @@ RenderLocalLightCount 1 8
RenderMaxPartCount 1 256
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTerrainPBRPlanarSampleCount 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.5
@ -118,6 +120,7 @@ RenderMaxPartCount 1 2048
RenderLocalLightCount 1 256
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTerrainPBRPlanarSampleCount 1 1
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.5
@ -147,6 +150,7 @@ RenderMaxPartCount 1 4096
RenderLocalLightCount 1 512
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 1
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.5
@ -176,6 +180,7 @@ RenderMaxPartCount 1 4096
RenderLocalLightCount 1 1024
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 1
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
@ -205,6 +210,7 @@ RenderMaxPartCount 1 4096
RenderLocalLightCount 1 2048
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
@ -234,6 +240,7 @@ RenderMaxPartCount 1 4096
RenderLocalLightCount 1 4096
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 2.0
@ -262,6 +269,7 @@ RenderLocalLightCount 1 8192
RenderMaxPartCount 1 8192
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTerrainPBRPlanarSampleCount 1 3
RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 3.0
@ -308,6 +316,9 @@ RenderShadowDetail 0 0
list TexUnit8orLess
RenderDeferredSSAO 0 0
list TexUnit16orLess
RenderTerrainPBRDetail 1 -1
list AMD
RenderDeferredSSAO 1 0

View File

@ -245,6 +245,7 @@
#include "pipeline.h"
#include "llgesturemgr.h"
#include "llsky.h"
#include "llvlcomposition.h"
#include "llvlmanager.h"
#include "llviewercamera.h"
#include "lldrawpoolbump.h"

View File

@ -567,14 +567,19 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text
void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
{
if (params.mModelMatrix != gGLLastMatrix)
applyModelMatrix(params.mModelMatrix);
}
void LLRenderPass::applyModelMatrix(const LLMatrix4* model_matrix)
{
if (model_matrix != gGLLastMatrix)
{
gGLLastMatrix = params.mModelMatrix;
gGLLastMatrix = model_matrix;
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.loadMatrix(gGLModelView);
if (params.mModelMatrix)
if (model_matrix)
{
gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix);
gGL.multMatrix((GLfloat*) model_matrix->mMatrix);
}
gPipeline.mMatrixOpCount++;
}
@ -746,6 +751,7 @@ void LLRenderPass::pushUntexturedGLTFBatches(U32 type)
}
}
// static
void LLRenderPass::pushGLTFBatch(LLDrawInfo& params)
{
auto& mat = params.mGLTFMaterial;
@ -764,6 +770,7 @@ void LLRenderPass::pushGLTFBatch(LLDrawInfo& params)
teardown_texture_matrix(params);
}
// static
void LLRenderPass::pushUntexturedGLTFBatch(LLDrawInfo& params)
{
auto& mat = params.mGLTFMaterial;
@ -825,6 +832,7 @@ void LLRenderPass::pushUntexturedRiggedGLTFBatches(U32 type)
}
// static
void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId)
{
if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash))
@ -837,6 +845,7 @@ void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvat
pushGLTFBatch(params);
}
// static
void LLRenderPass::pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId)
{
if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash))

View File

@ -58,9 +58,9 @@ public:
POOL_SIMPLE,
POOL_FULLBRIGHT,
POOL_BUMP,
POOL_TERRAIN,
POOL_MATERIALS,
POOL_GLTF_PBR,
POOL_TERRAIN,
POOL_GRASS,
POOL_GLTF_PBR_ALPHA_MASK,
POOL_TREE,
@ -349,8 +349,8 @@ public:
void resetDrawOrders() { }
static void applyModelMatrix(const LLDrawInfo& params);
// Use before a non-GLTF batch if it is interleaved with GLTF batches that share the same shader
static void resetGLTFTextureTransform();
// For rendering that doesn't use LLDrawInfo for some reason
static void applyModelMatrix(const LLMatrix4* model_matrix);
void pushBatches(U32 type, bool texture = true, bool batch_textures = false);
void pushUntexturedBatches(U32 type);
@ -374,10 +374,10 @@ public:
void pushUntexturedRiggedGLTFBatches(U32 type);
// push a single GLTF draw call
void pushGLTFBatch(LLDrawInfo& params);
void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId);
void pushUntexturedGLTFBatch(LLDrawInfo& params);
void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId);
static void pushGLTFBatch(LLDrawInfo& params);
static void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId);
static void pushUntexturedGLTFBatch(LLDrawInfo& params);
static void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId);
void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false);
void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false);

View File

@ -54,8 +54,11 @@
const F32 DETAIL_SCALE = 1.f/16.f;
int DebugDetailMap = 0;
S32 LLDrawPoolTerrain::sDetailMode = 1;
const S32 PBR_DETAIL_EMISSIVE = 0;
S32 LLDrawPoolTerrain::sPBRDetailMode = 0;
F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE;
F32 LLDrawPoolTerrain::sPBRDetailScale = DETAIL_SCALE;
static LLGLSLShader* sShader = NULL;
static LLTrace::BlockTimerStatHandle FTM_SHADOW_TERRAIN("Terrain Shadow");
@ -68,11 +71,14 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
// <FS:PP> Attempt to speed up things a little
// sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale");
// sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
// sPBRDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainPBRScale");
// sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail");
static LLCachedControl<F32> RenderTerrainScale(gSavedSettings, "RenderTerrainScale");
static LLCachedControl<S32> RenderTerrainDetail(gSavedSettings, "RenderTerrainDetail");
static LLCachedControl<F32> RenderTerrainPBRScale(gSavedSettings, "RenderTerrainPBRScale");
static LLCachedControl<S32> RenderTerrainPBRDetail(gSavedSettings, "RenderTerrainPBRDetail");
sDetailScale = 1.f/RenderTerrainScale;
sDetailMode = RenderTerrainDetail();
sPBRDetailScale = 1.f/RenderTerrainPBRScale;
sPBRDetailMode = RenderTerrainPBRDetail();
// </FS:PP>
mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD);
@ -114,18 +120,12 @@ U32 LLDrawPoolTerrain::getVertexDataMask()
void LLDrawPoolTerrain::prerender()
{
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
//sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
static LLCachedControl<S32> renderTerrainDetail(gSavedSettings, "RenderTerrainDetail");
sDetailMode = renderTerrainDetail();
//sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail");
static LLCachedControl<S32> renderTerrainPBRDetail(gSavedSettings, "RenderTerrainPBRDetail");
sPBRDetailMode = renderTerrainPBRDetail();
// </FS:Ansariel>
}
//static
S32 LLDrawPoolTerrain::getDetailMode()
{
return sDetailMode;
}
void LLDrawPoolTerrain::boostTerrainDetailTextures()
{
// Hack! Get the region that this draw pool is rendering from!
@ -133,8 +133,36 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures()
LLVLComposition *compp = regionp->getComposition();
for (S32 i = 0; i < 4; i++)
{
compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
compp->mDetailTextures[i]->addTextureStats(1024.f * 1024.f);
constexpr LLGLTexture::EBoostLevel level = LLGLTexture::BOOST_TERRAIN;
constexpr float stats = 1024.f * 1024.f;
LLPointer<LLViewerFetchedTexture>& tex = compp->mDetailTextures[i];
llassert(tex.notNull());
tex->setBoostLevel(level);
tex->addTextureStats(stats);
LLPointer<LLFetchedGLTFMaterial>& mat = compp->mDetailMaterials[i];
llassert(mat.notNull());
if (mat->mBaseColorTexture)
{
mat->mBaseColorTexture->setBoostLevel(level);
mat->mBaseColorTexture->addTextureStats(stats);
}
if (mat->mNormalTexture)
{
mat->mNormalTexture->setBoostLevel(level);
mat->mNormalTexture->addTextureStats(stats);
}
if (mat->mMetallicRoughnessTexture)
{
mat->mMetallicRoughnessTexture->setBoostLevel(level);
mat->mMetallicRoughnessTexture->addTextureStats(stats);
}
if (mat->mEmissiveTexture)
{
mat->mEmissiveTexture->setBoostLevel(level);
mat->mEmissiveTexture->addTextureStats(stats);
}
}
}
@ -142,10 +170,6 @@ void LLDrawPoolTerrain::beginDeferredPass(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN);
LLFacePool::beginRenderPass(pass);
sShader = &gDeferredTerrainProgram;
sShader->bind();
}
void LLDrawPoolTerrain::endDeferredPass(S32 pass)
@ -220,19 +244,8 @@ void LLDrawPoolTerrain::drawLoop()
{
LLFace *facep = *iter;
LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix);
if (model_matrix != gGLLastMatrix)
{
llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);
gGLLastMatrix = model_matrix;
gGL.loadMatrix(gGLModelView);
if (model_matrix)
{
gGL.multMatrix((GLfloat*) model_matrix->mMatrix);
}
gPipeline.mMatrixOpCount++;
}
llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);
LLRenderPass::applyModelMatrix(&facep->getDrawable()->getRegion()->mRenderMatrix);
facep->renderIndexed();
}
@ -241,9 +254,34 @@ void LLDrawPoolTerrain::drawLoop()
void LLDrawPoolTerrain::renderFullShader()
{
const BOOL use_local_materials = gLocalTerrainMaterials.materialsReady(TRUE);
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::Type::TEXTURE);
if (use_textures)
{
// Use textures
sShader = &gDeferredTerrainProgram;
sShader->bind();
renderFullShaderTextures();
}
else
{
// Use materials
sShader = &gDeferredPBRTerrainProgram;
sShader->bind();
renderFullShaderPBR(use_local_materials);
}
}
void LLDrawPoolTerrain::renderFullShaderTextures()
{
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
LLViewerTexture *detail_texture0p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[0] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
LLViewerTexture *detail_texture1p = (LLPipeline::sRenderTextures) ? compp->mDetailTextures[1] : LLViewerFetchedTexture::sDefaultDiffuseImagep;
@ -344,6 +382,197 @@ void LLDrawPoolTerrain::renderFullShader()
gGL.getTexUnit(detail0)->activate();
}
// *TODO: Investigate use of bindFast for PBR terrain textures
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> (*materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials;
if (local_materials)
{
// Override region terrain with the global local override terrain
materials = &gLocalTerrainMaterials.mDetailMaterials;
}
constexpr U32 terrain_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR;
S32 detail_basecolor[terrain_material_count];
S32 detail_normal[terrain_material_count];
S32 detail_metalrough[terrain_material_count];
S32 detail_emissive[terrain_material_count];
for (U32 i = 0; i < terrain_material_count; ++i)
{
const LLFetchedGLTFMaterial* material = (*materials)[i].get();
LLViewerTexture *detail_basecolor_texturep = material->mBaseColorTexture;
LLViewerTexture *detail_normal_texturep = material->mNormalTexture;
LLViewerTexture *detail_metalrough_texturep = material->mMetallicRoughnessTexture;
LLViewerTexture *detail_emissive_texturep = material->mEmissiveTexture;
detail_basecolor[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i);
if (detail_basecolor_texturep)
{
gGL.getTexUnit(detail_basecolor[i])->bind(detail_basecolor_texturep);
}
else
{
gGL.getTexUnit(detail_basecolor[i])->bind(LLViewerFetchedTexture::sWhiteImagep);
}
gGL.getTexUnit(detail_basecolor[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP);
gGL.getTexUnit(detail_basecolor[i])->activate();
detail_normal[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i);
if (detail_normal_texturep)
{
gGL.getTexUnit(detail_normal[i])->bind(detail_normal_texturep);
}
else
{
gGL.getTexUnit(detail_normal[i])->bind(LLViewerFetchedTexture::sFlatNormalImagep);
}
gGL.getTexUnit(detail_normal[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP);
gGL.getTexUnit(detail_normal[i])->activate();
detail_metalrough[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i);
if (detail_metalrough_texturep)
{
gGL.getTexUnit(detail_metalrough[i])->bind(detail_metalrough_texturep);
}
else
{
gGL.getTexUnit(detail_metalrough[i])->bind(LLViewerFetchedTexture::sWhiteImagep);
}
gGL.getTexUnit(detail_metalrough[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP);
gGL.getTexUnit(detail_metalrough[i])->activate();
if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE)
{
detail_emissive[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i);
if (detail_emissive_texturep)
{
gGL.getTexUnit(detail_emissive[i])->bind(detail_emissive_texturep);
}
else
{
gGL.getTexUnit(detail_emissive[i])->bind(LLViewerFetchedTexture::sWhiteImagep);
}
gGL.getTexUnit(detail_emissive[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP);
gGL.getTexUnit(detail_emissive[i])->activate();
}
}
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
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;
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);
LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
//
// Alpha Ramp
//
S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep);
gGL.getTexUnit(alpha_ramp)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
//
// GLTF uniforms
//
LLColor4 base_color_factors[terrain_material_count];
F32 metallic_factors[terrain_material_count];
F32 roughness_factors[terrain_material_count];
LLColor3 emissive_colors[terrain_material_count];
F32 minimum_alphas[terrain_material_count];
for (U32 i = 0; i < terrain_material_count; ++i)
{
const LLFetchedGLTFMaterial* material = (*materials)[i].get();
base_color_factors[i] = material->mBaseColor;
metallic_factors[i] = material->mMetallicFactor;
roughness_factors[i] = material->mRoughnessFactor;
emissive_colors[i] = material->mEmissiveColor;
// glTF 2.0 Specification 3.9.4. Alpha Coverage
// mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK
// Use 0 here due to GLTF terrain blending (LLGLTFMaterial::bind uses
// -1 for easier debugging)
F32 min_alpha = -0.0f;
if (material->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK)
{
// dividing the alpha cutoff by transparency here allows the shader to compare against
// the alpha value of the texture without needing the transparency value
min_alpha = material->mAlphaCutoff/material->mBaseColor.mV[3];
}
minimum_alphas[i] = min_alpha;
}
shader->uniform4fv(LLShaderMgr::TERRAIN_BASE_COLOR_FACTORS, terrain_material_count, (F32*)base_color_factors);
shader->uniform4f(LLShaderMgr::TERRAIN_METALLIC_FACTORS, metallic_factors[0], metallic_factors[1], metallic_factors[2], metallic_factors[3]);
shader->uniform4f(LLShaderMgr::TERRAIN_ROUGHNESS_FACTORS, roughness_factors[0], roughness_factors[1], roughness_factors[2], roughness_factors[3]);
if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE)
{
shader->uniform3fv(LLShaderMgr::TERRAIN_EMISSIVE_COLORS, terrain_material_count, (F32*)emissive_colors);
}
shader->uniform4f(LLShaderMgr::TERRAIN_MINIMUM_ALPHAS, minimum_alphas[0], minimum_alphas[1], minimum_alphas[2], minimum_alphas[3]);
// GL_BLEND disabled by default
drawLoop();
// Disable multitexture
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(alpha_ramp)->disable();
gGL.getTexUnit(alpha_ramp)->activate();
for (U32 i = 0; i < terrain_material_count; ++i)
{
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i);
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i);
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i);
if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE)
{
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i);
}
gGL.getTexUnit(detail_basecolor[i])->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(detail_basecolor[i])->disable();
gGL.getTexUnit(detail_basecolor[i])->activate();
gGL.getTexUnit(detail_normal[i])->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(detail_normal[i])->disable();
gGL.getTexUnit(detail_normal[i])->activate();
gGL.getTexUnit(detail_metalrough[i])->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(detail_metalrough[i])->disable();
gGL.getTexUnit(detail_metalrough[i])->activate();
if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE)
{
gGL.getTexUnit(detail_emissive[i])->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(detail_emissive[i])->disable();
gGL.getTexUnit(detail_emissive[i])->activate();
}
}
}
void LLDrawPoolTerrain::hilightParcelOwners()
{
{ //use fullbright shader for highlighting

View File

@ -37,13 +37,12 @@ public:
{
VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_NORMAL |
LLVertexBuffer::MAP_TANGENT | // Only PBR terrain uses this currently
LLVertexBuffer::MAP_TEXCOORD0 |
LLVertexBuffer::MAP_TEXCOORD1
};
virtual U32 getVertexDataMask();
static S32 getDetailMode();
LLDrawPoolTerrain(LLViewerTexture *texturep);
virtual ~LLDrawPoolTerrain();
@ -67,8 +66,9 @@ public:
LLPointer<LLViewerTexture> m2DAlphaRampImagep;
LLPointer<LLViewerTexture> mAlphaNoiseImagep;
static S32 sDetailMode;
static F32 sDetailScale; // meters per texture
static S32 sPBRDetailMode;
static F32 sDetailScale; // textures per meter
static F32 sPBRDetailScale; // textures per meter
protected:
void boostTerrainDetailTextures();
@ -79,6 +79,8 @@ protected:
void renderFull2TU();
void renderFull4TU();
void renderFullShader();
void renderFullShaderTextures();
void renderFullShaderPBR(BOOL local_materials = false);
void drawLoop();
private:

View File

@ -91,17 +91,8 @@ void LLDrawPoolTree::renderDeferred(S32 pass)
{
LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix);
if (model_matrix != gGLLastMatrix)
{
gGLLastMatrix = model_matrix;
gGL.loadMatrix(gGLModelView);
if (model_matrix)
{
llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);
gGL.multMatrix((GLfloat*)model_matrix->mMatrix);
}
gPipeline.mMatrixOpCount++;
}
llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);
LLRenderPass::applyModelMatrix(model_matrix);
buff->setBuffer();
buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts() - 1, buff->getNumIndices(), 0);

View File

@ -181,19 +181,26 @@ void LLViewerDynamicTexture::postRender(BOOL success)
//-----------------------------------------------------------------------------
BOOL LLViewerDynamicTexture::updateAllInstances()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
sNumRenders = 0;
if (gGLManager.mIsDisabled)
{
return TRUE;
}
bool use_fbo = gPipeline.mBake.isComplete();
LLRenderTarget& bake_target = gPipeline.mAuxillaryRT.deferredScreen;
if (use_fbo)
{
gPipeline.mBake.bindTarget();
gPipeline.mBake.clear();
}
if (!bake_target.isComplete())
{
llassert(false);
return FALSE;
}
llassert(bake_target.getWidth() >= LLPipeline::MAX_BAKE_WIDTH);
llassert(bake_target.getHeight() >= LLPipeline::MAX_BAKE_WIDTH);
bake_target.bindTarget();
bake_target.clear();
LLGLSLShader::unbind();
LLVertexBuffer::unbind();
@ -211,11 +218,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
if (dynamicTexture->needsRender())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("needsRender");
llassert(dynamicTexture->getFullWidth() <= LLPipeline::MAX_BAKE_WIDTH);
llassert(dynamicTexture->getFullHeight() <= LLPipeline::MAX_BAKE_WIDTH);
glClear(GL_DEPTH_BUFFER_BIT);
gDepthDirty = TRUE;
gGL.color4f(1,1,1,1);
dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr);
dynamicTexture->setBoundTarget(&bake_target);
dynamicTexture->preRender(); // Must be called outside of startRender()
result = FALSE;
{
@ -238,10 +248,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
}
}
if (use_fbo)
{
gPipeline.mBake.flush();
}
bake_target.flush();
gGL.flush();

View File

@ -674,6 +674,10 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("TexUnit8orLess");
}
if (gGLManager.mNumTextureImageUnits <= 16)
{
maskFeatures("TexUnit16orLess");
}
if (gGLManager.mVRAM > 512)
{
maskFeatures("VRAMGT512");

View File

@ -37,8 +37,6 @@
LLFetchedGLTFMaterial::LLFetchedGLTFMaterial()
: LLGLTFMaterial()
, mExpectedFlusTime(0.f)
, mActive(true)
, mFetching(false)
{
}
@ -242,10 +240,11 @@ void LLFetchedGLTFMaterial::onMaterialComplete(std::function<void()> material_co
materialCompleteCallbacks.push_back(material_complete);
}
void LLFetchedGLTFMaterial::materialComplete()
void LLFetchedGLTFMaterial::materialComplete(bool success)
{
llassert(mFetching);
mFetching = false;
mFetchSuccess = success;
for (std::function<void()> material_complete : materialCompleteCallbacks)
{
@ -254,55 +253,3 @@ void LLFetchedGLTFMaterial::materialComplete()
materialCompleteCallbacks.clear();
materialCompleteCallbacks.shrink_to_fit();
}
LLPointer<LLViewerFetchedTexture> LLFetchedGLTFMaterial::getUITexture()
{
if (mFetching)
{
return nullptr;
}
auto fetch_texture_for_ui = [](LLPointer<LLViewerFetchedTexture>& img, const LLUUID& id)
{
if (id.notNull())
{
if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id))
{
LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
if (obj)
{
LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(id);
img = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
}
}
else
{
img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
}
}
if (img)
{
img->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
img->forceToSaveRawImage(0);
}
};
fetch_texture_for_ui(mBaseColorTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
fetch_texture_for_ui(mNormalTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);
fetch_texture_for_ui(mMetallicRoughnessTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);
fetch_texture_for_ui(mEmissiveTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
if ((mBaseColorTexture && (mBaseColorTexture->getRawImageLevel() != 0)) ||
(mNormalTexture && (mNormalTexture->getRawImageLevel() != 0)) ||
(mMetallicRoughnessTexture && (mMetallicRoughnessTexture->getRawImageLevel() != 0)) ||
(mEmissiveTexture && (mEmissiveTexture->getRawImageLevel() != 0)))
{
return nullptr;
}
// *HACK: Use one of the PBR texture components as the preview texture for now
mPreviewTexture = mBaseColorTexture;
return mPreviewTexture;
}

View File

@ -49,8 +49,7 @@ public:
void bind(LLViewerTexture* media_tex = nullptr);
bool isFetching() const { return mFetching; }
LLPointer<LLViewerFetchedTexture> getUITexture();
bool isLoaded() const { return !mFetching && mFetchSuccess; }
void addTextureEntry(LLTextureEntry* te) override;
void removeTextureEntry(LLTextureEntry* te) override;
@ -65,18 +64,16 @@ public:
std::set<LLTextureEntry*> mTextureEntires;
// Texture used for previewing the material in the UI
LLPointer<LLViewerFetchedTexture> mPreviewTexture;
protected:
// Lifetime management
void materialBegin();
void materialComplete();
void materialComplete(bool success);
F64 mExpectedFlusTime; // since epoch in seconds
bool mActive;
bool mFetching;
bool mActive = true;
bool mFetching = false;
bool mFetchSuccess = false;
std::vector<std::function<void()>> materialCompleteCallbacks;
};

View File

@ -653,6 +653,26 @@ LLPanelRegionEnvironment* LLFloaterRegionInfo::getPanelEnvironment()
return panel;
}
enum class TerrainMaterialType
{
TEXTURE,
PBR_MATERIAL,
COUNT
};
TerrainMaterialType material_type_from_index(S32 index)
{
if (index == 0)
{
return TerrainMaterialType::TEXTURE;
}
if (index == 1)
{
return TerrainMaterialType::PBR_MATERIAL;
}
return TerrainMaterialType::COUNT;
}
// static
LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain()
{
@ -1493,6 +1513,17 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data)
BOOL LLPanelRegionTerrainInfo::validateTextureSizes()
{
// *TODO: Don't early-exit in PBR material terrain editing mode, and
// instead do some reasonable checks that the PBR material is compatible
// with the terrain rendering pipeline. Err on the side of permissive.
LLComboBox* material_type_ctrl = getChild<LLComboBox>("terrain_material_type");
if (material_type_ctrl)
{
const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL;
if (is_material_selected) { return TRUE; }
}
static const S32 MAX_TERRAIN_TEXTURE_SIZE = 1024;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
@ -1510,7 +1541,7 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes()
//LL_INFOS() << "texture detail " << i << " is " << width << "x" << height << "x" << components << LL_ENDL;
if (components != 3)
if (components != 3 && components != 4)
{
LLSD args;
args["TEXTURE_NUM"] = i+1;
@ -1566,12 +1597,20 @@ BOOL LLPanelRegionTerrainInfo::postBuild()
initCtrl("terrain_raise_spin");
initCtrl("terrain_lower_spin");
getChild<LLUICtrl>("terrain_material_type")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onSelectMaterialType, this));
std::string buffer;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
initCtrl(buffer);
}
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("material_detail_%d", i);
initCtrl(buffer);
}
for(S32 i = 0; i < CORNER_COUNT; ++i)
{
@ -1591,6 +1630,61 @@ BOOL LLPanelRegionTerrainInfo::postBuild()
return LLPanelRegionInfo::postBuild();
}
// virtual
void LLPanelRegionTerrainInfo::refresh()
{
std::string buffer;
bool has_material_assets = false;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("material_detail_%d", i);
LLTextureCtrl* material_ctrl = getChild<LLTextureCtrl>(buffer);
if (material_ctrl && material_ctrl->getImageAssetID().notNull())
{
has_material_assets = true;
break;
}
}
LLComboBox* material_type_ctrl = getChild<LLComboBox>("terrain_material_type");
if (material_type_ctrl)
{
const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL;
material_type_ctrl->setEnabled(!(is_material_selected && has_material_assets));
}
}
void LLPanelRegionTerrainInfo::onSelectMaterialType()
{
LLComboBox* material_type_ctrl = getChild<LLComboBox>("terrain_material_type");
if (!material_type_ctrl) { return; }
const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
const bool show_texture_controls = material_type == TerrainMaterialType::TEXTURE;
const bool show_material_controls = material_type == TerrainMaterialType::PBR_MATERIAL;
std::string buffer;
LLTextureCtrl* texture_ctrl;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
texture_ctrl = getChild<LLTextureCtrl>(buffer);
if (texture_ctrl)
{
texture_ctrl->setVisible(show_texture_controls);
}
}
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("material_detail_%d", i);
texture_ctrl = getChild<LLTextureCtrl>(buffer);
if (texture_ctrl)
{
texture_ctrl->setVisible(show_material_controls);
}
}
}
// virtual
bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
{
@ -1607,18 +1701,30 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
getChild<LLUICtrl>("region_text")->setValue(LLSD(region->getName()));
LLVLComposition* compp = region->getComposition();
LLTextureCtrl* texture_ctrl;
// Are these 4 texture IDs or 4 material IDs? Who knows! Let's set the IDs on both pickers for now.
LLTextureCtrl* asset_ctrl;
std::string buffer;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
texture_ctrl = getChild<LLTextureCtrl>(buffer);
if(texture_ctrl)
asset_ctrl = getChild<LLTextureCtrl>(buffer);
if(asset_ctrl)
{
LL_DEBUGS() << "Detail Texture " << i << ": "
<< compp->getDetailTextureID(i) << LL_ENDL;
LLUUID tmp_id(compp->getDetailTextureID(i));
texture_ctrl->setImageAssetID(tmp_id);
<< compp->getDetailAssetID(i) << LL_ENDL;
LLUUID tmp_id(compp->getDetailAssetID(i));
asset_ctrl->setImageAssetID(tmp_id);
}
}
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("material_detail_%d", i);
asset_ctrl = getChild<LLTextureCtrl>(buffer);
if(asset_ctrl)
{
LLUUID tmp_id(compp->getDetailAssetID(i));
asset_ctrl->setImageAssetID(tmp_id);
}
}
@ -1694,17 +1800,45 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
}
}
LLTextureCtrl* texture_ctrl;
LLTextureCtrl* asset_ctrl;
std::string id_str;
LLMessageSystem* msg = gMessageSystem;
// Use material IDs instead of texture IDs if all material IDs are set, AND the mode is set to PBR materials.
S32 materials_used = 0;
LLComboBox* material_type_ctrl = getChild<LLComboBox>("terrain_material_type");
if (material_type_ctrl)
{
const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL;
if (is_material_selected)
{
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("material_detail_%d", i);
asset_ctrl = getChild<LLTextureCtrl>(buffer);
if(asset_ctrl && asset_ctrl->getImageAssetID().notNull())
{
++materials_used;
}
}
}
}
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
texture_ctrl = getChild<LLTextureCtrl>(buffer);
if(texture_ctrl)
if (materials_used == TERRAIN_TEXTURE_COUNT)
{
buffer = llformat("material_detail_%d", i);
asset_ctrl = getChild<LLTextureCtrl>(buffer);
}
else
{
buffer = llformat("texture_detail_%d", i);
asset_ctrl = getChild<LLTextureCtrl>(buffer);
}
if(asset_ctrl)
{
LLUUID tmp_id(texture_ctrl->getImageAssetID());
LLUUID tmp_id(asset_ctrl->getImageAssetID());
tmp_id.toString(id_str);
buffer = llformat("%d %s", i, id_str.c_str());
strings.push_back(buffer);

View File

@ -78,9 +78,9 @@ class LLFloaterRegionInfo : public LLFloater
public:
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ BOOL postBuild();
void onOpen(const LLSD& key) override;
void onClose(bool app_quitting) override;
BOOL postBuild() override;
static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
@ -104,7 +104,7 @@ public:
// </FS:CR> Aurora Sim - Region Settings Panel
// from LLPanel
virtual void refresh();
void refresh() override;
void onRegionChanged();
void requestRegionInfo();
@ -150,7 +150,7 @@ public:
virtual bool refreshFromRegion(LLViewerRegion* region);
virtual bool estateUpdate(LLMessageSystem* msg) { return true; }
virtual BOOL postBuild();
BOOL postBuild() override;
virtual void updateChild(LLUICtrl* child_ctrl);
void enableButton(const std::string& btn_name, BOOL enable = TRUE);
@ -210,16 +210,15 @@ public:
: LLPanelRegionInfo() {}
~LLPanelRegionGeneralInfo() {}
virtual bool refreshFromRegion(LLViewerRegion* region);
bool refreshFromRegion(LLViewerRegion* region) override;
// LLPanel
virtual BOOL postBuild();
BOOL postBuild() override;
void onBtnSet();
void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;}
protected:
virtual BOOL sendUpdate();
BOOL sendUpdate() override;
void onClickKick();
void onKickCommit(const uuid_vec_t& ids);
static void onClickKickAll(void* userdata);
@ -240,13 +239,13 @@ public:
LLPanelRegionDebugInfo()
: LLPanelRegionInfo(), mTargetAvatar() {}
~LLPanelRegionDebugInfo() {}
// LLPanel
virtual BOOL postBuild();
BOOL postBuild() override;
virtual bool refreshFromRegion(LLViewerRegion* region);
bool refreshFromRegion(LLViewerRegion* region) override;
protected:
virtual BOOL sendUpdate();
BOOL sendUpdate() override;
void onClickChooseAvatar();
void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
@ -273,9 +272,9 @@ public:
LLPanelRegionTerrainInfo() : LLPanelRegionInfo() {}
~LLPanelRegionTerrainInfo() {}
virtual BOOL postBuild(); // LLPanel
BOOL postBuild() override;
virtual bool refreshFromRegion(LLViewerRegion* region); // refresh local settings from region update from simulator
bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator
void setEnvControls(bool available); // Whether environment settings are available for this region
BOOL validateTextureSizes();
@ -283,7 +282,8 @@ public:
//static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button
virtual BOOL sendUpdate();
void refresh() override;
void onSelectMaterialType();
static void onClickDownloadRaw(void*);
static void onClickUploadRaw(void*);
@ -295,6 +295,9 @@ public:
bool callbackBakeTerrain(const LLSD& notification, const LLSD& response);
bool callbackTextureHeights(const LLSD& notification, const LLSD& response);
protected:
BOOL sendUpdate() override;
private:
bool mConfirmedTextureHeights;
bool mAskedTextureHeights;
@ -333,13 +336,12 @@ public:
static void updateEstateName(const std::string& name);
static void updateEstateOwnerName(const std::string& name);
virtual bool refreshFromRegion(LLViewerRegion* region);
virtual bool estateUpdate(LLMessageSystem* msg);
bool refreshFromRegion(LLViewerRegion* region) override;
bool estateUpdate(LLMessageSystem* msg) override;
// LLPanel
virtual BOOL postBuild();
virtual void updateChild(LLUICtrl* child_ctrl);
virtual void refresh();
BOOL postBuild() override;
void updateChild(LLUICtrl* child_ctrl) override;
void refresh() override;
void refreshFromEstate();
@ -349,7 +351,7 @@ public:
void setOwnerName(const std::string& name);
protected:
virtual BOOL sendUpdate();
BOOL sendUpdate() override;
// confirmation dialog callback
bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response);
@ -369,17 +371,16 @@ public:
LLPanelEstateCovenant();
~LLPanelEstateCovenant() {}
// LLPanel
virtual BOOL postBuild();
virtual void updateChild(LLUICtrl* child_ctrl);
virtual bool refreshFromRegion(LLViewerRegion* region);
virtual bool estateUpdate(LLMessageSystem* msg);
BOOL postBuild() override;
void updateChild(LLUICtrl* child_ctrl) override;
bool refreshFromRegion(LLViewerRegion* region) override;
bool estateUpdate(LLMessageSystem* msg) override;
// LLView overrides
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type,
void *cargo_data, EAcceptance *accept,
std::string& tooltip_msg);
std::string& tooltip_msg) override;
static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response);
static void resetCovenantID(void* userdata);
static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response);
@ -412,7 +413,7 @@ public:
} EAssetStatus;
protected:
virtual BOOL sendUpdate();
BOOL sendUpdate() override;
LLTextBox* mEstateNameText;
LLTextBox* mEstateOwnerText;
LLTextBox* mLastModifiedText;
@ -431,16 +432,19 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
public:
LLPanelRegionExperiences(){}
/*virtual*/ BOOL postBuild();
virtual BOOL sendUpdate();
BOOL postBuild() override;
static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response);
static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id);
static void infoCallback(LLHandle<LLPanelRegionExperiences> handle, const LLSD& content);
bool refreshFromRegion(LLViewerRegion* region);
bool refreshFromRegion(LLViewerRegion* region) override;
void sendPurchaseRequest()const;
void processResponse( const LLSD& content );
protected:
BOOL sendUpdate() override;
private:
void refreshRegionExperiences();
@ -465,8 +469,8 @@ class LLPanelEstateAccess : public LLPanelRegionInfo
public:
LLPanelEstateAccess();
virtual BOOL postBuild();
virtual void updateChild(LLUICtrl* child_ctrl);
BOOL postBuild() override;
void updateChild(LLUICtrl* child_ctrl) override;
void updateControls(LLViewerRegion* region);
void updateLists();
@ -474,7 +478,7 @@ public:
void setPendingUpdate(bool pending) { mPendingUpdate = pending; }
bool getPendingUpdate() { return mPendingUpdate; }
virtual bool refreshFromRegion(LLViewerRegion* region);
bool refreshFromRegion(LLViewerRegion* region) override;
// <FS:Ansariel> Moved to public
static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);

View File

@ -471,7 +471,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp
if (status != LL_ERR_NOERR)
{
LL_WARNS("GLTF") << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL;
asset_data->mMaterial->materialComplete();
asset_data->mMaterial->materialComplete(false);
delete asset_data;
}
else
@ -556,7 +556,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp
LL_DEBUGS("GLTF") << "Failed to get material " << id << LL_ENDL;
}
asset_data->mMaterial->materialComplete();
asset_data->mMaterial->materialComplete(true);
delete asset_data;
});

View File

@ -0,0 +1,555 @@
/**
* @file llgltfmaterialpreviewmgr.cpp
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llgltfmaterialpreviewmgr.h"
#include <memory>
#include <vector>
#include "llavatarappearancedefines.h"
#include "llenvironment.h"
#include "llselectmgr.h"
#include "llviewercamera.h"
#include "llviewerobject.h"
#include "llviewershadermgr.h"
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llvolumemgr.h"
#include "pipeline.h"
LLGLTFMaterialPreviewMgr gGLTFMaterialPreviewMgr;
namespace
{
constexpr S32 FULLY_LOADED = 0;
constexpr S32 NOT_LOADED = 99;
};
LLGLTFPreviewTexture::MaterialLoadLevels::MaterialLoadLevels()
{
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
levels[i] = NOT_LOADED;
}
}
S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i)
{
llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT);
return levels[i];
}
const S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i) const
{
llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT);
return levels[i];
}
bool LLGLTFPreviewTexture::MaterialLoadLevels::operator<(const MaterialLoadLevels& other) const
{
bool less = false;
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (((*this)[i] > other[i])) { return false; }
less = less || ((*this)[i] < other[i]);
}
return less;
}
bool LLGLTFPreviewTexture::MaterialLoadLevels::operator>(const MaterialLoadLevels& other) const
{
bool great = false;
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (((*this)[i] < other[i])) { return false; }
great = great || ((*this)[i] > other[i]);
}
return great;
}
namespace
{
void fetch_texture_for_ui(LLPointer<LLViewerFetchedTexture>& img, const LLUUID& id)
{
if (id.notNull())
{
if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id))
{
LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
if (obj)
{
LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(id);
img = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
}
}
else
{
img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
}
}
if (img)
{
img->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
img->forceToSaveRawImage(0);
}
};
// *NOTE: Does not use the same conventions as texture discard level. Lower is better.
S32 get_texture_load_level(const LLPointer<LLViewerFetchedTexture>& texture)
{
if (!texture) { return FULLY_LOADED; }
const S32 raw_level = texture->getDiscardLevel();
if (raw_level < 0) { return NOT_LOADED; }
return raw_level;
}
LLGLTFPreviewTexture::MaterialLoadLevels get_material_load_levels(LLFetchedGLTFMaterial& material)
{
using MaterialTextures = LLPointer<LLViewerFetchedTexture>*[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT];
MaterialTextures textures;
textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = &material.mBaseColorTexture;
textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = &material.mNormalTexture;
textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = &material.mMetallicRoughnessTexture;
textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = &material.mEmissiveTexture;
LLGLTFPreviewTexture::MaterialLoadLevels levels;
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
fetch_texture_for_ui(*textures[i], material.mTextureId[i]);
levels[i] = get_texture_load_level(*textures[i]);
}
return levels;
}
// Is the material loaded enough to start rendering a preview?
bool is_material_loaded_enough_for_ui(LLFetchedGLTFMaterial& material)
{
if (material.isFetching())
{
return false;
}
LLGLTFPreviewTexture::MaterialLoadLevels levels = get_material_load_levels(material);
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (levels[i] == NOT_LOADED)
{
return false;
}
}
return true;
}
}; // namespace
LLGLTFPreviewTexture::LLGLTFPreviewTexture(LLPointer<LLFetchedGLTFMaterial> material, S32 width)
: LLViewerDynamicTexture(width, width, 4, EOrder::ORDER_MIDDLE, FALSE)
, mGLTFMaterial(material)
{
}
// static
LLPointer<LLGLTFPreviewTexture> LLGLTFPreviewTexture::create(LLPointer<LLFetchedGLTFMaterial> material)
{
return new LLGLTFPreviewTexture(material, LLPipeline::MAX_BAKE_WIDTH);
}
void LLGLTFPreviewTexture::preRender(BOOL clear_depth)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
MaterialLoadLevels current_load = get_material_load_levels(*mGLTFMaterial.get());
if (current_load < mBestLoad)
{
mShouldRender = true;
mBestLoad = current_load;
}
if (!mShouldRender) { return; }
LLViewerDynamicTexture::preRender(clear_depth);
}
namespace {
struct GLTFPreviewModel
{
GLTFPreviewModel(LLPointer<LLDrawInfo>& info, const LLMatrix4& mat)
: mDrawInfo(info)
, mModelMatrix(mat)
{
mDrawInfo->mModelMatrix = &mModelMatrix;
}
GLTFPreviewModel(GLTFPreviewModel&) = delete;
~GLTFPreviewModel()
{
// No model matrix necromancy
llassert(gGLLastMatrix != &mModelMatrix);
gGLLastMatrix = nullptr;
}
LLPointer<LLDrawInfo> mDrawInfo;
LLMatrix4 mModelMatrix; // Referenced by mDrawInfo
};
using PreviewSpherePart = std::unique_ptr<GLTFPreviewModel>;
using PreviewSphere = std::vector<PreviewSpherePart>;
// Like LLVolumeGeometryManager::registerFace but without batching or too-many-indices/vertices checking.
PreviewSphere create_preview_sphere(LLPointer<LLFetchedGLTFMaterial>& material, const LLMatrix4& model_matrix)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
const LLColor4U vertex_color(material->mBaseColor);
LLPrimitive prim;
prim.init_primitive(LL_PCODE_VOLUME);
LLVolumeParams params;
params.setType(LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE);
params.setBeginAndEndS(0.f, 1.f);
params.setBeginAndEndT(0.f, 1.f);
params.setRatio(1, 1);
params.setShear(0, 0);
constexpr auto MAX_LOD = LLVolumeLODGroup::NUM_LODS - 1;
prim.setVolume(params, MAX_LOD);
LLVolume* volume = prim.getVolume();
llassert(volume);
for (LLVolumeFace& face : volume->getVolumeFaces())
{
face.createTangents();
}
PreviewSphere preview_sphere;
preview_sphere.reserve(volume->getNumFaces());
LLPointer<LLVertexBuffer> buf = new LLVertexBuffer(
LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_NORMAL |
LLVertexBuffer::MAP_TEXCOORD0 |
LLVertexBuffer::MAP_COLOR |
LLVertexBuffer::MAP_TANGENT
);
U32 nv = 0;
U32 ni = 0;
for (LLVolumeFace& face : volume->getVolumeFaces())
{
nv += face.mNumVertices;
ni += face.mNumIndices;
}
buf->allocateBuffer(nv, ni);
// UV hacks
// Higher factor helps to see more details on the preview sphere
const LLVector2 uv_factor(2.0f, 2.0f);
// Offset places center of material in center of view
const LLVector2 uv_offset(-0.5f, -0.5f);
LLStrider<U16> indices;
LLStrider<LLVector4a> positions;
LLStrider<LLVector4a> normals;
LLStrider<LLVector2> texcoords;
LLStrider<LLColor4U> colors;
LLStrider<LLVector4a> tangents;
buf->getIndexStrider(indices);
buf->getVertexStrider(positions);
buf->getNormalStrider(normals);
buf->getTexCoord0Strider(texcoords);
buf->getColorStrider(colors);
buf->getTangentStrider(tangents);
U32 index_offset = 0;
U32 vertex_offset = 0;
for (const LLVolumeFace& face : volume->getVolumeFaces())
{
for (S32 i = 0; i < face.mNumIndices; ++i)
{
*indices++ = face.mIndices[i] + vertex_offset;
}
for (S32 v = 0; v < face.mNumVertices; ++v)
{
*positions++ = face.mPositions[v];
*normals++ = face.mNormals[v];
LLVector2 uv(face.mTexCoords[v]);
uv.scaleVec(uv_factor);
uv += uv_offset;
*texcoords++ = uv;
*colors++ = vertex_color;
*tangents++ = face.mTangents[v];
}
constexpr LLViewerTexture* no_media = nullptr;
LLPointer<LLDrawInfo> info = new LLDrawInfo(U16(vertex_offset), U16(vertex_offset + face.mNumVertices - 1), face.mNumIndices, index_offset, no_media, buf.get());
info->mGLTFMaterial = material;
preview_sphere.emplace_back(std::make_unique<GLTFPreviewModel>(info, model_matrix));
index_offset += face.mNumIndices;
vertex_offset += face.mNumVertices;
}
buf->unmapBuffer();
return preview_sphere;
}
void set_preview_sphere_material(PreviewSphere& preview_sphere, LLPointer<LLFetchedGLTFMaterial>& material)
{
llassert(!preview_sphere.empty());
if (preview_sphere.empty()) { return; }
const LLColor4U vertex_color(material->mBaseColor);
// See comments about unmapBuffer in llvertexbuffer.h
for (PreviewSpherePart& part : preview_sphere)
{
LLDrawInfo* info = part->mDrawInfo.get();
info->mGLTFMaterial = material;
LLVertexBuffer* buf = info->mVertexBuffer.get();
LLStrider<LLColor4U> colors;
const S32 count = info->mEnd - info->mStart;
buf->getColorStrider(colors, info->mStart, count);
for (S32 i = 0; i < count; ++i)
{
*colors++ = vertex_color;
}
buf->unmapBuffer();
}
}
PreviewSphere& get_preview_sphere(LLPointer<LLFetchedGLTFMaterial>& material, const LLMatrix4& model_matrix)
{
static PreviewSphere preview_sphere;
if (preview_sphere.empty())
{
preview_sphere = create_preview_sphere(material, model_matrix);
}
else
{
set_preview_sphere_material(preview_sphere, material);
}
return preview_sphere;
}
// Final, direct modifications to shader constants, just before render
void fixup_shader_constants(LLGLSLShader& shader)
{
// Sunlight intensity of 0 no matter what
shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, 1);
shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, LLColor3::white.mV);
shader.uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, 0.0f);
// Ignore sun shadow (if enabled)
for (U32 i = 0; i < 6; i++)
{
const S32 channel = shader.getTextureChannel(LLShaderMgr::DEFERRED_SHADOW0+i);
if (channel != -1)
{
gGL.getTexUnit(channel)->bind(LLViewerFetchedTexture::sWhiteImagep, TRUE);
}
}
}
// Set a variable to a value temporarily, and restor the variable's old value
// when this object leaves scope.
template<typename T>
struct SetTemporarily
{
T* mRef;
T mOldVal;
SetTemporarily(T* var, T temp_val)
{
mRef = var;
mOldVal = *mRef;
*mRef = temp_val;
}
~SetTemporarily()
{
*mRef = mOldVal;
}
};
}; // namespace
BOOL LLGLTFPreviewTexture::render()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (!mShouldRender) { return FALSE; }
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
LLGLDepthTest(GL_FALSE);
LLGLDisable stencil(GL_STENCIL_TEST);
LLGLDisable scissor(GL_SCISSOR_TEST);
SetTemporarily<bool> no_dof(&LLPipeline::RenderDepthOfField, false);
SetTemporarily<bool> no_glow(&LLPipeline::sRenderGlow, false);
SetTemporarily<bool> no_ssr(&LLPipeline::RenderScreenSpaceReflections, false);
SetTemporarily<U32> no_fxaa(&LLPipeline::RenderFSAASamples, U32(0));
SetTemporarily<LLPipeline::RenderTargetPack*> use_auxiliary_render_target(&gPipeline.mRT, &gPipeline.mAuxillaryRT);
LLVector3 light_dir3(1.0f, 1.0f, 1.0f);
light_dir3.normalize();
const LLVector4 light_dir = LLVector4(light_dir3, 0);
SetTemporarily<S32> sun_light_only(&LLPipeline::RenderLocalLightCount, 0);
gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms();
LLViewerCamera camera;
// Calculate the object distance at which the object of a given radius will
// span the partial width of the screen given by fill_ratio.
// Assume the primitive has a scale of 1 (this is the default).
constexpr F32 fill_ratio = 0.8f;
constexpr F32 object_radius = 0.5f;
const F32 object_distance = (object_radius / fill_ratio) * tan(camera.getDefaultFOV());
// Negative coordinate shows the textures on the sphere right-side up, when
// combined with the UV hacks in create_preview_sphere
const LLVector3 object_position(0.0, -object_distance, 0.0);
LLMatrix4 object_transform;
object_transform.translate(object_position);
// Set up camera and viewport
const LLVector3 origin(0.0, 0.0, 0.0);
camera.lookAt(origin, object_position);
camera.setAspect(mFullHeight / mFullWidth);
const LLRect texture_rect(0, mFullHeight, mFullWidth, 0);
camera.setPerspective(NOT_FOR_SELECTION, texture_rect.mLeft, texture_rect.mBottom, texture_rect.getWidth(), texture_rect.getHeight(), FALSE, camera.getNear(), MAX_FAR_CLIP*2.f);
// Generate sphere object on-the-fly. Discard afterwards. (Vertex buffer is
// discarded, but the sphere should be cached in LLVolumeMgr.)
PreviewSphere& preview_sphere = get_preview_sphere(mGLTFMaterial, object_transform);
gPipeline.setupHWLights();
glh::matrix4f mat = copy_matrix(gGLModelView);
glh::vec4f transformed_light_dir(light_dir.mV);
mat.mult_matrix_vec(transformed_light_dir);
SetTemporarily<LLVector4> force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(transformed_light_dir.v));
// Override lights to ensure the sun is always shining from a certain direction (low graphics)
// See also force_sun_direction_high_graphics and fixup_shader_constants
{
LLLightState* light = gGL.getLight(0);
light->setPosition(light_dir);
constexpr bool sun_up = true;
light->setSunPrimary(sun_up);
}
LLRenderTarget& screen = gPipeline.mAuxillaryRT.screen;
// *HACK: Force reset of the model matrix
gGLLastMatrix = nullptr;
#if 0
if (mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_OPAQUE || mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK)
{
// *TODO: Opaque/alpha mask rendering
}
else
#endif
{
// Alpha blend rendering
screen.bindTarget();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
LLGLSLShader& shader = gDeferredPBRAlphaProgram;
gPipeline.bindDeferredShader(shader);
fixup_shader_constants(shader);
for (PreviewSpherePart& part : preview_sphere)
{
LLRenderPass::pushGLTFBatch(*part->mDrawInfo);
}
gPipeline.unbindDeferredShader(shader);
screen.flush();
}
gPipeline.copyScreenSpaceReflections(&screen, &gPipeline.mSceneMap);
gPipeline.generateLuminance(&screen, &gPipeline.mLuminanceMap);
gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap);
gPipeline.gammaCorrect(&screen, &gPipeline.mPostMap);
LLVertexBuffer::unbind();
gPipeline.generateGlow(&gPipeline.mPostMap);
gPipeline.combineGlow(&gPipeline.mPostMap, &screen);
gPipeline.renderDoF(&screen, &gPipeline.mPostMap);
gPipeline.applyFXAA(&gPipeline.mPostMap, &screen);
// Final render
gDeferredPostNoDoFProgram.bind();
// From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems."
gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &screen);
gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true);
{
LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS);
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
}
gDeferredPostNoDoFProgram.unbind();
// Clean up
gPipeline.setupHWLights();
gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(false);
return TRUE;
}
void LLGLTFPreviewTexture::postRender(BOOL success)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (!mShouldRender) { return; }
mShouldRender = false;
LLViewerDynamicTexture::postRender(success);
}
// static
LLPointer<LLViewerTexture> LLGLTFMaterialPreviewMgr::getPreview(LLPointer<LLFetchedGLTFMaterial> &material)
{
if (!material)
{
return nullptr;
}
if (!is_material_loaded_enough_for_ui(*material))
{
return nullptr;
}
return LLGLTFPreviewTexture::create(material);
}

View File

@ -0,0 +1,82 @@
/**
* @file llgltfmaterialpreviewmgr.h
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#pragma once
#include "lldrawpool.h"
#include "lldynamictexture.h"
#include "llfetchedgltfmaterial.h"
#include "llsingleton.h"
#include "lltexture.h"
class LLGLTFPreviewTexture : public LLViewerDynamicTexture
{
protected:
LLGLTFPreviewTexture(LLPointer<LLFetchedGLTFMaterial> material, S32 width);
public:
// Width scales with size of material's textures
static LLPointer<LLGLTFPreviewTexture> create(LLPointer<LLFetchedGLTFMaterial> material);
BOOL needsRender() override { return mNeedsRender; }
void preRender(BOOL clear_depth = TRUE) override;
BOOL render() override;
void postRender(BOOL success) override;
struct MaterialLoadLevels
{
S32 levels[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT];
MaterialLoadLevels();
S32& operator[](size_t i);
const S32& operator[](size_t i) const;
// Less is better
// Returns false if lhs is not strictly less or equal for all levels
bool operator<(const MaterialLoadLevels& other) const;
// Less is better
// Returns false if lhs is not strictly greater or equal for all levels
bool operator>(const MaterialLoadLevels& other) const;
};
private:
LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial;
bool mNeedsRender = true;
bool mShouldRender = true;
MaterialLoadLevels mBestLoad;
};
class LLGLTFMaterialPreviewMgr
{
public:
// Returns null if the material is not loaded yet.
// *NOTE: User should cache the texture if the same material is being previewed
LLPointer<LLViewerTexture> getPreview(LLPointer<LLFetchedGLTFMaterial> &material);
};
extern LLGLTFMaterialPreviewMgr gGLTFMaterialPreviewMgr;

View File

@ -1875,7 +1875,7 @@ static void pack_textures(
if (normal_img)
{
// create a losslessly compressed version of the normal map
normal_j2c = LLViewerTextureList::convertToUploadFile(normal_img, 1024, false, true);
normal_j2c = LLViewerTextureList::convertToUploadFile(normal_img, 2048, false, true);
LL_DEBUGS("MaterialEditor") << "Normal: " << normal_j2c->getDataSize() << LL_ENDL;
}

View File

@ -27,6 +27,9 @@
#include "llviewerprecompiledheaders.h"
#include "llreflectionmapmanager.h"
#include <vector>
#include "llviewercamera.h"
#include "llspatialpartition.h"
#include "llviewerregion.h"
@ -1383,3 +1386,39 @@ void LLReflectionMapManager::doOcclusion()
}
}
}
void LLReflectionMapManager::forceDefaultProbeAndUpdateUniforms(bool force)
{
static std::vector<bool> mProbeWasOccluded;
if (force)
{
llassert(mProbeWasOccluded.empty());
for (size_t i = 0; i < mProbes.size(); ++i)
{
auto& probe = mProbes[i];
mProbeWasOccluded.push_back(probe->mOccluded);
if (probe != nullptr && probe != mDefaultProbe)
{
probe->mOccluded = true;
}
}
updateUniforms();
}
else
{
llassert(mProbes.size() == mProbeWasOccluded.size());
const size_t n = llmin(mProbes.size(), mProbeWasOccluded.size());
for (size_t i = 0; i < n; ++i)
{
auto& probe = mProbes[i];
llassert(probe->mOccluded == (probe != mDefaultProbe));
probe->mOccluded = mProbeWasOccluded[i];
}
mProbeWasOccluded.clear();
mProbeWasOccluded.shrink_to_fit();
}
}

View File

@ -106,6 +106,11 @@ public:
// perform occlusion culling on all active reflection probes
void doOcclusion();
// *HACK: "cull" all reflection probes except the default one. Only call
// this if you don't intend to call updateUniforms directly. Call again
// with false when done.
void forceDefaultProbeAndUpdateUniforms(bool force = true);
private:
friend class LLPipeline;

View File

@ -246,7 +246,9 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
*vertex = pos_agent-mVObjp->getRegion()->getOriginAgent();
LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent();
LLVector3 tex_pos = rel_pos * (1.f/surface_stride);
// *NOTE: Only PBR terrain uses the UVs right now. Texture terrain just ignores it.
// *NOTE: In the future, UVs and horizontal position will no longer have a 1:1 relationship for PBR terrain
LLVector3 tex_pos = rel_pos;
tex0->mV[0] = tex_pos.mV[0];
tex0->mV[1] = tex_pos.mV[1];
tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y);
@ -869,7 +871,7 @@ void LLSurfacePatch::updateGL()
updateCompositionStats();
F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY],
tex_patch_size, tex_patch_size))
{
mSTexUpdate = FALSE;

View File

@ -72,6 +72,7 @@
#include "llradiogroup.h"
#include "llfloaterreg.h"
#include "llgltfmaterialpreviewmgr.h"
#include "lllocalbitmaps.h"
#include "lllocalgltfmaterials.h"
#include "llerror.h"
@ -721,6 +722,7 @@ void LLFloaterTexturePicker::draw()
if( mOwner )
{
mTexturep = NULL;
LLPointer<LLFetchedGLTFMaterial> old_material = mGLTFMaterial;
mGLTFMaterial = NULL;
if (mImageAssetID.notNull())
{
@ -728,10 +730,23 @@ void LLFloaterTexturePicker::draw()
{
mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID);
llassert(mGLTFMaterial == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr);
if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get())))
{
// Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview.
if (mGLTFMaterial.isNull())
{
mGLTFPreview = nullptr;
}
else
{
mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial);
}
}
}
else
{
LLPointer<LLViewerFetchedTexture> texture = NULL;
mGLTFPreview = nullptr;
if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
{
@ -741,7 +756,7 @@ void LLFloaterTexturePicker::draw()
if (obj)
{
LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
}
}
@ -783,27 +798,29 @@ void LLFloaterTexturePicker::draw()
// If the floater is focused, don't apply its alpha to the texture (STORM-677).
const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
LLViewerTexture* texture = nullptr;
LLViewerTexture* preview = nullptr;
if (mGLTFMaterial)
{
texture = mGLTFMaterial->getUITexture();
preview = mGLTFPreview.get();
}
else
{
texture = mTexturep.get();
preview = mTexturep.get();
if (mTexturep)
{
// Pump the priority
mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
}
}
if( texture )
if( preview )
{
if( texture->getComponents() == 4 )
if( preview->getComponents() == 4 )
{
gl_rect_2d_checkerboard( interior, alpha );
}
gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), texture, UI_VERTEX_COLOR % alpha );
// Pump the priority
texture->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha );
}
else if (!mFallbackImage.isNull())
{
@ -1786,7 +1803,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
mShowLoadingPlaceholder( TRUE ),
mOpenTexPreview(!p.enabled), // <FS:Ansariel> For texture preview mode
mBakeTextureEnabled(true),
mInventoryPickType(PICK_TEXTURE),
mInventoryPickType(p.pick_type),
mImageAssetID(p.image_id),
mDefaultImageAssetID(p.default_image_id),
mDefaultImageName(p.default_image_name),
@ -2344,48 +2361,69 @@ void LLTextureCtrl::draw()
{
mBorder->setKeyboardFocusHighlight(hasFocus());
LLPointer<LLViewerTexture> preview = NULL;
if (!mValid)
{
mTexturep = NULL;
mGLTFMaterial = NULL;
mGLTFPreview = NULL;
}
else if (!mImageAssetID.isNull())
{
LLPointer<LLViewerFetchedTexture> texture = NULL;
if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
{
LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
if (obj)
{
LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID);
texture = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
mTexturep = viewerTexture ? dynamic_cast<LLViewerFetchedTexture*>(viewerTexture) : NULL;
mGLTFMaterial = NULL;
mGLTFPreview = NULL;
preview = mTexturep;
}
}
if (texture.isNull())
if (preview.isNull())
{
LLPointer<LLFetchedGLTFMaterial> old_material = mGLTFMaterial;
mGLTFMaterial = NULL;
mTexturep = NULL;
if (mInventoryPickType == PICK_MATERIAL)
{
LLPointer<LLFetchedGLTFMaterial> material = gGLTFMaterialList.getMaterial(mImageAssetID);
if (material)
mGLTFMaterial = gGLTFMaterialList.getMaterial(mImageAssetID);
if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get())))
{
texture = material->getUITexture();
// Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview.
if (mGLTFMaterial.isNull())
{
mGLTFPreview = nullptr;
}
else
{
mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial);
}
}
preview = mGLTFPreview;
}
else
{
texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
texture->forceToSaveRawImage(0);
mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
mTexturep->forceToSaveRawImage(0);
preview = mTexturep;
}
}
mTexturep = texture;
}
else//mImageAssetID == LLUUID::null
{
mTexturep = NULL;
mGLTFMaterial = NULL;
mGLTFPreview = NULL;
}
// Border
@ -2400,15 +2438,18 @@ void LLTextureCtrl::draw()
// If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677).
const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
if( mTexturep )
if( preview )
{
if( mTexturep->getComponents() == 4 )
if( preview->getComponents() == 4 )
{
gl_rect_2d_checkerboard( interior, alpha );
}
gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha);
if (mTexturep)
{
mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
}
// <FS:Ansariel> Mask texture if desired
if (mIsMasked)
{
@ -2594,3 +2635,18 @@ void LLTextureCtrl::updateLabelColor()
mCaption->setReadOnlyColor(mTextDisabledColor.get());
}
// </FS:Zi>
namespace LLInitParam
{
void TypeValues<EPickInventoryType>::declareValues()
{
declare("texture_material", PICK_TEXTURE_MATERIAL);
declare("texture", PICK_TEXTURE);
declare("material", PICK_MATERIAL);
}
}

View File

@ -65,13 +65,6 @@ bool get_is_predefined_texture(LLUUID asset_id);
LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false);
bool get_can_copy_texture(LLUUID image_id);
enum LLPickerSource
{
PICKER_INVENTORY,
PICKER_LOCAL,
PICKER_BAKE,
PICKER_UNKNOWN, // on cancel, default ids
};
typedef enum e_pick_inventory_type
{
@ -80,6 +73,23 @@ typedef enum e_pick_inventory_type
PICK_MATERIAL = 2,
} EPickInventoryType;
namespace LLInitParam
{
template<>
struct TypeValues<EPickInventoryType> : public TypeValuesHelper<EPickInventoryType>
{
static void declareValues();
};
}
enum LLPickerSource
{
PICKER_INVENTORY,
PICKER_LOCAL,
PICKER_BAKE,
PICKER_UNKNOWN, // on cancel, default ids
};
//////////////////////////////////////////////////////////////////////////////////////////
// LLTextureCtrl
@ -101,6 +111,7 @@ public:
Optional<LLUUID> image_id;
Optional<LLUUID> default_image_id;
Optional<std::string> default_image_name;
Optional<EPickInventoryType> pick_type;
Optional<bool> allow_no_texture;
Optional<bool> can_apply_immediately;
Optional<bool> no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty
@ -122,6 +133,7 @@ public:
: image_id("image"),
default_image_id("default_image_id"),
default_image_name("default_image_name"),
pick_type("pick_type", PICK_TEXTURE),
allow_no_texture("allow_no_texture", false),
can_apply_immediately("can_apply_immediately"),
no_commit_on_selection("no_commit_on_selection", false),
@ -266,6 +278,8 @@ private:
commit_callback_t mOnCloseCallback;
texture_selected_callback mOnTextureSelectedCallback;
LLPointer<LLViewerFetchedTexture> mTexturep;
LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial;
LLPointer<LLViewerTexture> mGLTFPreview;
LLUIColor mBorderColor;
LLUUID mImageItemID;
LLUUID mImageAssetID;
@ -411,6 +425,7 @@ protected:
LLPointer<LLViewerTexture> mTexturep;
LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial;
LLPointer<LLViewerTexture> mGLTFPreview;
LLView* mOwner;
LLUUID mImageAssetID; // Currently selected texture

View File

@ -60,6 +60,7 @@
#include "llvotree.h"
#include "llvovolume.h"
#include "llworld.h"
#include "llvlcomposition.h"
#include "pipeline.h"
#include "llviewerjoystick.h"
#include "llviewerobjectlist.h"
@ -197,12 +198,25 @@ static bool handleRenderFarClipChanged(const LLSD& newvalue)
return false;
}
static bool handleTerrainDetailChanged(const LLSD& newvalue)
static bool handleTerrainScaleChanged(const LLSD& newvalue)
{
LLDrawPoolTerrain::sDetailMode = newvalue.asInteger();
F64 scale = newvalue.asReal();
if (scale != 0.0)
{
LLDrawPoolTerrain::sDetailScale = F32(1.0 / scale);
}
return true;
}
static bool handlePBRTerrainScaleChanged(const LLSD& newvalue)
{
F64 scale = newvalue.asReal();
if (scale != 0.0)
{
LLDrawPoolTerrain::sPBRDetailScale = F32(1.0 / scale);
}
return true;
}
static bool handleDebugAvatarJointsChanged(const LLSD& newvalue)
{
@ -1080,6 +1094,16 @@ void handleFPSTuningStrategyChanged(const LLSD& newValue)
LLPerfStats::tunables.userFPSTuningStrategy = newval;
}
void handleLocalTerrainChanged(const LLSD& newValue)
{
for (U32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
{
const auto setting = gSavedSettings.getString(std::string("LocalTerrainAsset") + std::to_string(i + 1));
const LLUUID materialID(setting);
gLocalTerrainMaterials.setDetailAssetID(i, materialID);
}
}
// <FS:Ansariel> FIRE-6809: Quickly moving the bandwidth slider has no effect
void handleBandwidthChanged(const LLSD& newValue)
{
@ -1132,7 +1156,11 @@ void settings_setup_listeners()
{
setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged);
setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRScale", handlePBRTerrainScaleChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRPlanarSampleCount", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRTriplanarBlendFactor", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition);
setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition);
setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition);
@ -1288,6 +1316,10 @@ 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);
setting_setup_signal_listener(gSavedPerAccountSettings, "AvatarHoverOffsetZ", handleAvatarHoverOffsetChanged);

View File

@ -3191,20 +3191,20 @@ void LLViewerRegion::unpackRegionHandshake()
// Get the 4 textures for land
msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id);
changed |= (tmp_id != compp->getDetailTextureID(0));
compp->setDetailTextureID(0, tmp_id);
changed |= (tmp_id != compp->getDetailAssetID(0));
compp->setDetailAssetID(0, tmp_id);
msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id);
changed |= (tmp_id != compp->getDetailTextureID(1));
compp->setDetailTextureID(1, tmp_id);
changed |= (tmp_id != compp->getDetailAssetID(1));
compp->setDetailAssetID(1, tmp_id);
msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id);
changed |= (tmp_id != compp->getDetailTextureID(2));
compp->setDetailTextureID(2, tmp_id);
changed |= (tmp_id != compp->getDetailAssetID(2));
compp->setDetailAssetID(2, tmp_id);
msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id);
changed |= (tmp_id != compp->getDetailTextureID(3));
compp->setDetailTextureID(3, tmp_id);
changed |= (tmp_id != compp->getDetailAssetID(3));
compp->setDetailAssetID(3, tmp_id);
// Get the start altitude and range values for land textures
F32 tmp_f32;

View File

@ -69,6 +69,14 @@ bool LLViewerShaderMgr::sSkipReload = false;
LLVector4 gShinyOrigin;
S32 clamp_terrain_mapping(S32 mapping)
{
// 1 = "flat", 2 not implemented, 3 = triplanar mapping
mapping = llclamp(mapping, 1, 3);
if (mapping == 2) { mapping = 1; }
return mapping;
}
//utility shaders
LLGLSLShader gOcclusionProgram;
LLGLSLShader gSkinnedOcclusionProgram;
@ -218,6 +226,7 @@ LLGLSLShader gDeferredSkinnedPBROpaqueProgram;
LLGLSLShader gHUDPBRAlphaProgram;
LLGLSLShader gDeferredPBRAlphaProgram;
LLGLSLShader gDeferredSkinnedPBRAlphaProgram;
LLGLSLShader gDeferredPBRTerrainProgram;
//helper for making a rigged variant of a given shader
bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader)
@ -275,7 +284,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredEmissiveProgram);
mShaderList.push_back(&gDeferredSkinnedEmissiveProgram);
mShaderList.push_back(&gDeferredAvatarEyesProgram);
mShaderList.push_back(&gDeferredAvatarAlphaProgram);
mShaderList.push_back(&gDeferredAvatarAlphaProgram);
mShaderList.push_back(&gDeferredWLSkyProgram);
mShaderList.push_back(&gDeferredWLCloudProgram);
mShaderList.push_back(&gDeferredWLMoonProgram);
@ -627,6 +636,15 @@ std::string LLViewerShaderMgr::loadBasicShaders()
attribs["REF_SAMPLE_COUNT"] = "32";
}
{ // PBR terrain
const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount"));
attribs["TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT"] = llformat("%d", mapping);
const F32 triplanar_factor = gSavedSettings.getF32("RenderTerrainPBRTriplanarBlendFactor");
attribs["TERRAIN_TRIPLANAR_BLEND_FACTOR"] = llformat("%.2f", triplanar_factor);
S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail");
attribs["TERRAIN_PBR_DETAIL"] = llformat("%d", detail);
}
LLGLSLShader::sGlobalDefines = attribs;
// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
@ -664,6 +682,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) );
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) );
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
@ -968,6 +987,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedPBROpaqueProgram.unload();
gDeferredPBRAlphaProgram.unload();
gDeferredSkinnedPBRAlphaProgram.unload();
gDeferredPBRTerrainProgram.unload();
// [RLVa:KB] - @setsphere
gRlvSphereProgram.unload();
@ -1262,6 +1282,34 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = shader->createShader(NULL, NULL);
llassert(success);
}
if (success)
{
S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail");
detail = llclamp(detail, TERRAIN_PBR_DETAIL_MIN, TERRAIN_PBR_DETAIL_MAX);
const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount"));
gDeferredPBRTerrainProgram.mName = llformat("Deferred PBR Terrain Shader %d %s",
detail,
(mapping == 1 ? "flat" : "triplanar"));
gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true;
gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true;
gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true;
gDeferredPBRTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
gDeferredPBRTerrainProgram.mFeatures.calculatesAtmospherics = true;
gDeferredPBRTerrainProgram.mFeatures.hasAtmospherics = true;
gDeferredPBRTerrainProgram.mFeatures.hasGamma = true;
gDeferredPBRTerrainProgram.mFeatures.hasTransport = true;
gDeferredPBRTerrainProgram.mFeatures.isPBRTerrain = true;
gDeferredPBRTerrainProgram.mShaderFiles.clear();
gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainV.glsl", GL_VERTEX_SHADER));
gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainF.glsl", GL_FRAGMENT_SHADER));
gDeferredPBRTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredPBRTerrainProgram.addPermutation("TERRAIN_PBR_DETAIL", llformat("%d", detail));
gDeferredPBRTerrainProgram.addPermutation("TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT", llformat("%d", mapping));
success = gDeferredPBRTerrainProgram.createShader(NULL, NULL);
llassert(success);
}
if (success)
{
@ -1975,8 +2023,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTerrainProgram.mName = "Deferred Terrain Shader";
gDeferredTerrainProgram.mFeatures.encodesNormal = true;
gDeferredTerrainProgram.mFeatures.hasSrgb = true;
gDeferredTerrainProgram.mFeatures.calculatesLighting = false;
gDeferredTerrainProgram.mFeatures.hasLighting = false;
gDeferredTerrainProgram.mFeatures.isAlphaLighting = true;
gDeferredTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
gDeferredTerrainProgram.mFeatures.calculatesAtmospherics = true;

View File

@ -276,4 +276,16 @@ extern LLGLSLShader gPBRGlowProgram;
extern LLGLSLShader gDeferredPBROpaqueProgram;
extern LLGLSLShader gDeferredPBRAlphaProgram;
extern LLGLSLShader gHUDPBRAlphaProgram;
// Encodes detail level for dropping textures, in accordance with the GLTF spec
// 0 is highest detail, -1 drops emissive, etc
// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures
enum TerrainPBRDetail : S32
{
TERRAIN_PBR_DETAIL_MAX = 0,
TERRAIN_PBR_DETAIL_EMISSIVE = 0,
TERRAIN_PBR_DETAIL_OCCLUSION = -1,
TERRAIN_PBR_DETAIL_MIN = -1,
};
extern LLGLSLShader gDeferredPBRTerrainProgram;
#endif

View File

@ -1775,7 +1775,7 @@ void LLViewerFetchedTexture::processTextureStats()
{
if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
{
mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096
}
else
{
@ -1788,7 +1788,7 @@ void LLViewerFetchedTexture::processTextureStats()
}
else
{
U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096
// <FS:Ansariel> Keep restriction on "fetched" (seems to be HUD) textures as well
if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED)
{
@ -3181,7 +3181,7 @@ void LLViewerLODTexture::processTextureStats()
{
mDesiredDiscardLevel = 0;
if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096
}
else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f)
{
@ -3226,7 +3226,7 @@ void LLViewerLODTexture::processTextureStats()
discard_level = floorf(discard_level);
F32 min_discard = 0.f;
U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096
if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED)
{
desired_size = DESIRED_NORMAL_TEXTURE_SIZE;

View File

@ -34,12 +34,16 @@
#include "lltextureview.h"
#include "llviewertexture.h"
#include "llviewertexturelist.h"
#include "llfetchedgltfmaterial.h"
#include "llgltfmateriallist.h"
#include "llviewerregion.h"
#include "noise.h"
#include "llregionhandle.h" // for from_region_handle
#include "llviewercontrol.h"
static const U32 BASE_SIZE = 128;
F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac)
{
@ -57,18 +61,199 @@ F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F
return result;
}
LLTerrainMaterials::LLTerrainMaterials()
{
for (S32 i = 0; i < ASSET_COUNT; ++i)
{
mMaterialTexturesSet[i] = false;
}
}
LLTerrainMaterials::~LLTerrainMaterials()
{
}
BOOL LLTerrainMaterials::generateMaterials()
{
if (texturesReady(TRUE))
{
return TRUE;
}
if (materialsReady(TRUE))
{
return TRUE;
}
return FALSE;
}
LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset)
{
llassert(mDetailTextures[asset] && mDetailMaterials[asset]);
// *HACK: Assume both the the material and texture were fetched in the same
// way using the same UUID. However, we may not know at this point which
// one will load.
return mDetailTextures[asset]->getID();
}
LLPointer<LLViewerFetchedTexture> fetch_terrain_texture(const LLUUID& id)
{
if (id.isNull())
{
return nullptr;
}
LLPointer<LLViewerFetchedTexture> tex = LLViewerTextureManager::getFetchedTexture(id);
tex->setNoDelete();
return tex;
}
void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id)
{
// This is terrain texture, but we are not setting it as BOOST_TERRAIN
// since we will be manipulating it later as needed.
mDetailTextures[asset] = fetch_terrain_texture(id);
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[asset];
mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id);
mMaterialTexturesSet[asset] = false;
}
LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType()
{
LL_PROFILE_ZONE_SCOPED;
const BOOL use_textures = texturesReady() || !materialsReady();
return use_textures ? Type::TEXTURE : Type::PBR;
}
BOOL LLTerrainMaterials::texturesReady(BOOL boost)
{
BOOL ready = TRUE;
for (S32 i = 0; i < ASSET_COUNT; i++)
{
if (!textureReady(mDetailTextures[i], boost))
{
ready = FALSE;
}
}
return ready;
}
BOOL LLTerrainMaterials::materialsReady(BOOL boost)
{
BOOL ready = TRUE;
for (S32 i = 0; i < ASSET_COUNT; i++)
{
if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost))
{
ready = FALSE;
}
}
return ready;
}
// Boost the texture loading priority
// Return true when ready to use (i.e. texture is sufficiently loaded)
// static
BOOL LLTerrainMaterials::textureReady(LLPointer<LLViewerFetchedTexture>& tex, BOOL boost)
{
llassert(tex.notNull());
if (tex->getDiscardLevel() < 0)
{
if (boost)
{
tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
tex->addTextureStats(BASE_SIZE*BASE_SIZE);
}
return FALSE;
}
if ((tex->getDiscardLevel() != 0 &&
(tex->getWidth() < BASE_SIZE ||
tex->getHeight() < BASE_SIZE)))
{
if (boost)
{
S32 width = tex->getFullWidth();
S32 height = tex->getFullHeight();
S32 min_dim = llmin(width, height);
S32 ddiscard = 0;
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
{
ddiscard++;
min_dim /= 2;
}
tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
tex->setMinDiscardLevel(ddiscard);
tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority
}
return FALSE;
}
if (tex->getComponents() == 0)
{
return FALSE;
}
return TRUE;
}
// Boost the loading priority of every known texture in the material
// Return true when ready to use (i.e. material and all textures within are sufficiently loaded)
// static
BOOL LLTerrainMaterials::materialReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, BOOL boost)
{
if (!mat || !mat->isLoaded())
{
return FALSE;
}
// Material is loaded, but textures may not be
if (!textures_set)
{
// *NOTE: These can sometimes be set to to nullptr due to
// updateTEMaterialTextures. For the sake of robustness, we emulate
// that fetching behavior by setting textures of null IDs to nullptr.
mat->mBaseColorTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
mat->mNormalTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);
mat->mMetallicRoughnessTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);
mat->mEmissiveTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
textures_set = true;
return FALSE;
}
if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && !textureReady(mat->mBaseColorTexture, boost))
{
return FALSE;
}
if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && !textureReady(mat->mNormalTexture, boost))
{
return FALSE;
}
if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && !textureReady(mat->mMetallicRoughnessTexture, boost))
{
return FALSE;
}
if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && !textureReady(mat->mEmissiveTexture, boost))
{
return FALSE;
}
return TRUE;
}
LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
LLViewerLayer(width, scale),
mParamsReady(FALSE)
LLTerrainMaterials(),
LLViewerLayer(width, scale)
{
mSurfacep = surfacep;
// Load Terrain Textures - Original ones
setDetailTextureID(0, TERRAIN_DIRT_DETAIL);
setDetailTextureID(1, TERRAIN_GRASS_DETAIL);
setDetailTextureID(2, TERRAIN_MOUNTAIN_DETAIL);
setDetailTextureID(3, TERRAIN_ROCK_DETAIL);
setDetailAssetID(0, TERRAIN_DIRT_DETAIL);
setDetailAssetID(1, TERRAIN_GRASS_DETAIL);
setDetailAssetID(2, TERRAIN_MOUNTAIN_DETAIL);
setDetailAssetID(3, TERRAIN_ROCK_DETAIL);
mSurfacep = surfacep;
// Initialize the texture matrix to defaults.
for (S32 i = 0; i < CORNER_COUNT; ++i)
@ -76,14 +261,12 @@ LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32
mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight");
mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange");
}
mTexScaleX = 16.f;
mTexScaleY = 16.f;
mTexturesLoaded = FALSE;
}
LLVLComposition::~LLVLComposition()
{
LLTerrainMaterials::~LLTerrainMaterials();
}
@ -92,20 +275,6 @@ void LLVLComposition::setSurface(LLSurface *surfacep)
mSurfacep = surfacep;
}
void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id)
{
if(id.isNull())
{
return;
}
// This is terrain texture, but we are not setting it as BOOST_TERRAIN
// since we will be manipulating it later as needed.
mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id);
mDetailTextures[corner]->setNoDelete() ;
mRawImages[corner] = NULL;
}
BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
const F32 width, const F32 height)
{
@ -149,10 +318,6 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus
// simple height)
// Heights map into textures as 0-1 = first, 1-2 = second, etc.
// So we need to compress heights into this range.
const S32 NUM_TEXTURES = 4;
const F32 xyScaleInv = (1.f / xyScale);
const F32 zScaleInv = (1.f / zScale);
@ -202,7 +367,7 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component
twiddle *= noise_magnitude;
F32 scaled_noisy_height = (height + twiddle - start_height) * F32(NUM_TEXTURES) / height_range;
F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range;
scaled_noisy_height = llmax(0.f, scaled_noisy_height);
scaled_noisy_height = llmin(3.f, scaled_noisy_height);
@ -212,49 +377,20 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
return TRUE;
}
static const U32 BASE_SIZE = 128;
LLTerrainMaterials gLocalTerrainMaterials;
BOOL LLVLComposition::generateComposition()
{
if (!mParamsReady)
{
// All the parameters haven't been set yet (we haven't gotten the message from the sim)
return FALSE;
}
for (S32 i = 0; i < 4; i++)
{
if (mDetailTextures[i]->getDiscardLevel() < 0)
{
mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE);
return FALSE;
}
if ((mDetailTextures[i]->getDiscardLevel() != 0 &&
(mDetailTextures[i]->getWidth() < BASE_SIZE ||
mDetailTextures[i]->getHeight() < BASE_SIZE)))
{
S32 width = mDetailTextures[i]->getFullWidth();
S32 height = mDetailTextures[i]->getFullHeight();
S32 min_dim = llmin(width, height);
S32 ddiscard = 0;
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
{
ddiscard++;
min_dim /= 2;
}
mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
mDetailTextures[i]->setMinDiscardLevel(ddiscard);
mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); // priority
return FALSE;
}
}
return TRUE;
return LLTerrainMaterials::generateMaterials();
}
BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
const F32 width, const F32 height)
{
LL_PROFILE_ZONE_SCOPED
@ -262,8 +398,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
llassert(x >= 0.f);
llassert(y >= 0.f);
LLTimer gen_timer;
///////////////////////////
//
// Generate raw data arrays for surface textures
@ -271,15 +405,61 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
//
// These have already been validated by generateComposition.
U8* st_data[4];
S32 st_data_size[4]; // for debugging
U8* st_data[ASSET_COUNT];
S32 st_data_size[ASSET_COUNT]; // for debugging
for (S32 i = 0; i < 4; i++)
const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR;
// *TODO: Remove this as it is reduandant computation (first and foremost
// because getMaterialType() does something similar, but also... shouldn't
// the textures/materials already be loaded by now?)
if (use_textures)
{
if (!texturesReady()) { return FALSE; }
}
else
{
if (!materialsReady()) { return FALSE; }
}
for (S32 i = 0; i < ASSET_COUNT; i++)
{
if (mRawImages[i].isNull())
{
// Read back a raw image for this discard level, if it exists
S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight());
LLViewerFetchedTexture* tex;
LLViewerFetchedTexture* tex_emissive; // Can be null
bool has_base_color_factor;
bool has_emissive_factor;
LLColor3 base_color_factor;
LLColor3 emissive_factor;
if (use_textures)
{
tex = mDetailTextures[i];
tex_emissive = nullptr;
has_base_color_factor = false;
has_emissive_factor = false;
llassert(tex);
}
else
{
tex = mDetailMaterials[i]->mBaseColorTexture;
tex_emissive = mDetailMaterials[i]->mEmissiveTexture;
base_color_factor = LLColor3(mDetailMaterials[i]->mBaseColor);
// *HACK: Treat alpha as black
base_color_factor *= (mDetailMaterials[i]->mBaseColor.mV[VW]);
emissive_factor = mDetailMaterials[i]->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);
}
if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; }
// tex_emissive can be null, and then will be ignored
S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight());
S32 ddiscard = 0;
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
{
@ -287,31 +467,80 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
min_dim /= 2;
}
BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ;
if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL) ;
if(tex->getRawImageLevel() != ddiscard)
{
if (mDetailTextures[i]->getFetchPriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage())
// Raw image is not ready, will enter here again later.
if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage())
{
mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_MAP);
mDetailTextures[i]->forceToRefetchTexture(ddiscard);
tex->setBoostLevel(LLGLTexture::BOOST_MAP);
tex->forceToRefetchTexture(ddiscard);
}
if(delete_raw)
{
mDetailTextures[i]->destroyRawImage() ;
tex->destroyRawImage() ;
}
LL_DEBUGS("Terrain") << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << " Discard: " << ddiscard << LL_ENDL;
return FALSE;
}
if (tex_emissive)
{
if(tex_emissive->getRawImageLevel() != ddiscard)
{
// Raw image is not ready, will enter here again later.
if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage())
{
tex_emissive->setBoostLevel(LLGLTexture::BOOST_MAP);
tex_emissive->forceToRefetchTexture(ddiscard);
}
mRawImages[i] = mDetailTextures[i]->getRawImage() ;
if(delete_raw)
{
tex_emissive->destroyRawImage() ;
}
return FALSE;
}
}
mRawImages[i] = tex->getRawImage() ;
if(delete_raw)
{
mDetailTextures[i]->destroyRawImage() ;
tex->destroyRawImage() ;
}
if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE ||
mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE ||
mDetailTextures[i]->getComponents() != 3)
// *TODO: This isn't quite right for PBR:
// 1) It does not convert the color images from SRGB to linear
// before mixing (which will always require copying the image).
// 2) It mixes emissive and base color before mixing terrain
// materials, but it should be the other way around
// 3) The composite function used to put emissive into base color
// is not an alpha blend.
// Long-term, we should consider a method that is more
// maintainable. Shaders, perhaps? Bake shaders to textures?
LLPointer<LLImageRaw> raw_emissive;
if (tex_emissive)
{
raw_emissive = tex_emissive->getRawImage();
if (has_emissive_factor ||
tex_emissive->getWidth(ddiscard) != BASE_SIZE ||
tex_emissive->getHeight(ddiscard) != BASE_SIZE ||
tex_emissive->getComponents() != 4)
{
LLPointer<LLImageRaw> newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4);
// Copy RGB, leave alpha alone (set to opaque by default)
newraw_emissive->copy(mRawImages[i]);
if (has_emissive_factor)
{
newraw_emissive->tint(emissive_factor);
}
raw_emissive = newraw_emissive; // deletes old
}
}
if (has_base_color_factor ||
raw_emissive ||
tex->getWidth(ddiscard) != BASE_SIZE ||
tex->getHeight(ddiscard) != BASE_SIZE ||
tex->getComponents() != 3)
{
LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
//<FS:Beq> guard against bad alloc here that leads to crash in composite
@ -323,6 +552,15 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
}
// </FS:Beq>
newraw->composite(mRawImages[i]);
if (has_base_color_factor)
{
newraw->tint(base_color_factor);
}
// Apply emissive texture
if (raw_emissive)
{
newraw->composite(raw_emissive);
}
mRawImages[i] = newraw; // deletes old
}
}
@ -344,12 +582,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
if (x_end > mWidth)
{
LL_WARNS("Terrain") << "x end > width" << LL_ENDL;
llassert(false);
x_end = mWidth;
}
if (y_end > mWidth)
{
LL_WARNS("Terrain") << "y end > width" << LL_ENDL;
llassert(false);
y_end = mWidth;
}
@ -379,7 +617,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
if (tex_comps != st_comps)
{
LL_WARNS("Terrain") << "Base texture comps != input texture comps" << LL_ENDL;
llassert(false);
return FALSE;
}
@ -470,7 +708,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
}
texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
for (S32 i = 0; i < 4; i++)
for (S32 i = 0; i < ASSET_COUNT; i++)
{
// Un-boost detatil textures (will get re-boosted if rendering in high detail)
mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_NONE);
@ -480,21 +718,21 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
return TRUE;
}
LLUUID LLVLComposition::getDetailTextureID(S32 corner)
{
return mDetailTextures[corner]->getID();
}
LLViewerFetchedTexture* LLVLComposition::getDetailTexture(S32 corner)
{
return mDetailTextures[corner];
}
F32 LLVLComposition::getStartHeight(S32 corner)
{
return mStartHeight[corner];
}
void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id)
{
if (id.isNull())
{
return;
}
LLTerrainMaterials::setDetailAssetID(asset, id);
mRawImages[asset] = NULL;
}
void LLVLComposition::setStartHeight(S32 corner, const F32 start_height)
{
mStartHeight[corner] = start_height;

View File

@ -28,11 +28,54 @@
#define LL_LLVLCOMPOSITION_H
#include "llviewerlayer.h"
#include "llviewertexture.h"
#include "llpointer.h"
#include "llimage.h"
class LLSurface;
class LLVLComposition : public LLViewerLayer
class LLViewerFetchedTexture;
class LLFetchedGLTFMaterial;
class LLTerrainMaterials
{
public:
friend class LLDrawPoolTerrain;
LLTerrainMaterials();
virtual ~LLTerrainMaterials();
// Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
// So we need to compress heights into this range.
static const S32 ASSET_COUNT = 4;
enum class Type
{
TEXTURE,
PBR,
COUNT
};
BOOL generateMaterials();
LLUUID getDetailAssetID(S32 asset);
virtual void setDetailAssetID(S32 asset, const LLUUID& id);
Type getMaterialType();
BOOL texturesReady(BOOL boost = FALSE);
BOOL materialsReady(BOOL boost = FALSE);
protected:
static BOOL textureReady(LLPointer<LLViewerFetchedTexture>& tex, BOOL boost = FALSE);
static BOOL materialReady(LLPointer<LLFetchedGLTFMaterial>& mat, bool& textures_set, BOOL boost = FALSE);
LLPointer<LLViewerFetchedTexture> mDetailTextures[ASSET_COUNT];
LLPointer<LLFetchedGLTFMaterial> mDetailMaterials[ASSET_COUNT];
bool mMaterialTexturesSet[ASSET_COUNT];
};
// Local materials to override all regions
extern LLTerrainMaterials gLocalTerrainMaterials;
class LLVLComposition : public LLTerrainMaterials, public LLViewerLayer
{
public:
LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale);
@ -44,7 +87,11 @@ public:
BOOL generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
BOOL generateComposition();
// Generate texture from composition values.
BOOL generateTexture(const F32 x, const F32 y, const F32 width, const F32 height);
BOOL generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
// Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
// So we need to compress heights into this range.
static const S32 ASSET_COUNT = 4;
// Use these as indeces ito the get/setters below that use 'corner'
enum ECorner
@ -55,12 +102,11 @@ public:
NORTHEAST = 3,
CORNER_COUNT = 4
};
LLUUID getDetailTextureID(S32 corner);
LLViewerFetchedTexture* getDetailTexture(S32 corner);
void setDetailAssetID(S32 asset, const LLUUID& id) override;
F32 getStartHeight(S32 corner);
F32 getHeightRange(S32 corner);
void setDetailTextureID(S32 corner, const LLUUID& id);
void setStartHeight(S32 corner, F32 start_height);
void setHeightRange(S32 corner, F32 range);
@ -68,19 +114,21 @@ public:
friend class LLDrawPoolTerrain;
void setParamsReady() { mParamsReady = TRUE; }
BOOL getParamsReady() const { return mParamsReady; }
protected:
BOOL mParamsReady;
LLSurface *mSurfacep;
BOOL mTexturesLoaded;
LLPointer<LLViewerFetchedTexture> mDetailTextures[CORNER_COUNT];
LLPointer<LLImageRaw> mRawImages[CORNER_COUNT];
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;
LLPointer<LLImageRaw> mRawImages[LLTerrainMaterials::ASSET_COUNT];
F32 mStartHeight[CORNER_COUNT];
F32 mHeightRange[CORNER_COUNT];
F32 mTexScaleX;
F32 mTexScaleY;
F32 mTexScaleX = 16.f;
F32 mTexScaleY = 16.f;
};
#endif //LL_LLVLCOMPOSITION_H

View File

@ -39,6 +39,7 @@
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llvlcomposition.h"
#include "llvolume.h"
#include "llvovolume.h"
#include "pipeline.h"
#include "llspatialpartition.h"
@ -241,48 +242,50 @@ BOOL LLVOSurfacePatch::updateLOD()
return TRUE;
}
void LLVOSurfacePatch::getGeometry(LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp)
void LLVOSurfacePatch::getTerrainGeometry(LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp)
{
LLFace* facep = mDrawable->getFace(0);
if (facep)
{
U32 index_offset = facep->getGeomIndex();
if (!facep)
{
return;
}
updateMainGeometry(facep,
verticesp,
normalsp,
texCoords0p,
texCoords1p,
indicesp,
index_offset);
updateNorthGeometry(facep,
verticesp,
normalsp,
texCoords0p,
texCoords1p,
indicesp,
index_offset);
updateEastGeometry(facep,
verticesp,
normalsp,
texCoords0p,
texCoords1p,
indicesp,
index_offset);
}
U32 index_offset = facep->getGeomIndex();
updateMainGeometry(facep,
verticesp,
normalsp,
texCoords0p,
texCoords1p,
indicesp,
index_offset);
updateNorthGeometry(facep,
verticesp,
normalsp,
texCoords0p,
texCoords1p,
indicesp,
index_offset);
updateEastGeometry(facep,
verticesp,
normalsp,
texCoords0p,
texCoords1p,
indicesp,
index_offset);
}
void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
{
S32 i, j, x, y;
@ -381,12 +384,12 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
{
S32 i, x, y;
@ -571,12 +574,12 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
}
void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
{
S32 i, x, y;
@ -982,6 +985,49 @@ LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp)
mPartitionType = LLViewerRegion::PARTITION_TERRAIN;
}
// Do not add vertices; honor strict vertex count specified by strider_vertex_count
void gen_terrain_tangents(U16 strider_vertex_count,
U32 strider_index_count,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector4a> &tangentsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<U16> &indicesp)
{
LL_PROFILE_ZONE_SCOPED
LLVector4a *vertices = new LLVector4a[strider_vertex_count];
LLVector4a *normals = new LLVector4a[strider_vertex_count];
LLVector4a *tangents = new LLVector4a[strider_vertex_count];
std::vector<LLVector2> texcoords(strider_vertex_count);
std::vector<U16> indices(strider_index_count);
for (U16 v = 0; v < strider_vertex_count; ++v)
{
F32 *vert = verticesp[v].mV;
vertices[v] = LLVector4a(vert[0], vert[1], vert[2], 1.f);
F32 *n = normalsp[v].mV;
normals[v] = LLVector4a(n[0], n[1], n[2], 1.f);
tangents[v] = tangentsp[v];
texcoords[v] = texCoords0p[v];
}
for (U32 i = 0; i < strider_index_count; ++i)
{
indices[i] = indicesp[i];
}
LLCalculateTangentArray(strider_vertex_count, vertices, normals, texcoords.data(), strider_index_count / 3, indices.data(), tangents);
for (U16 v = 0; v < strider_vertex_count; ++v)
{
tangentsp[v] = tangents[v];
}
delete[] vertices;
delete[] normals;
delete[] tangents;
}
void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED;
@ -989,35 +1035,57 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
LLVertexBuffer* buffer = group->mVertexBuffer;
//get vertex buffer striders
LLStrider<LLVector3> vertices;
LLStrider<LLVector3> normals;
LLStrider<LLVector2> texcoords2;
LLStrider<LLVector2> texcoords;
LLStrider<U16> indices;
LLStrider<LLVector3> vertices_start;
LLStrider<LLVector3> normals_start;
LLStrider<LLVector4a> tangents_start;
LLStrider<LLVector2> texcoords_start;
LLStrider<LLVector2> texcoords2_start;
LLStrider<U16> indices_start;
llassert_always(buffer->getVertexStrider(vertices));
llassert_always(buffer->getNormalStrider(normals));
llassert_always(buffer->getTexCoord0Strider(texcoords));
llassert_always(buffer->getTexCoord1Strider(texcoords2));
llassert_always(buffer->getIndexStrider(indices));
llassert_always(buffer->getVertexStrider(vertices_start));
llassert_always(buffer->getNormalStrider(normals_start));
llassert_always(buffer->getTangentStrider(tangents_start));
llassert_always(buffer->getTexCoord0Strider(texcoords_start));
llassert_always(buffer->getTexCoord1Strider(texcoords2_start));
llassert_always(buffer->getIndexStrider(indices_start));
U32 indices_index = 0;
U32 index_offset = 0;
U32 indices_index = 0;
U32 index_offset = 0;
for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
{
LLFace* facep = *i;
{
LLStrider<LLVector3> vertices = vertices_start;
LLStrider<LLVector3> normals = normals_start;
LLStrider<LLVector2> texcoords = texcoords_start;
LLStrider<LLVector2> texcoords2 = texcoords2_start;
LLStrider<U16> indices = indices_start;
facep->setIndicesIndex(indices_index);
facep->setGeomIndex(index_offset);
facep->setVertexBuffer(buffer);
for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
{
LLFace* facep = *i;
LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject();
patchp->getGeometry(vertices, normals, texcoords, texcoords2, indices);
facep->setIndicesIndex(indices_index);
facep->setGeomIndex(index_offset);
facep->setVertexBuffer(buffer);
indices_index += facep->getIndicesCount();
index_offset += facep->getGeomCount();
}
LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject();
patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2, indices);
indices_index += facep->getIndicesCount();
index_offset += facep->getGeomCount();
}
}
const bool has_tangents = tangents_start.get() != nullptr;
if (has_tangents)
{
LLStrider<LLVector3> vertices = vertices_start;
LLStrider<LLVector3> normals = normals_start;
LLStrider<LLVector4a> tangents = tangents_start;
LLStrider<LLVector2> texcoords = texcoords_start;
LLStrider<U16> indices = indices_start;
gen_terrain_tangents(index_offset, indices_index, vertices, normals, tangents, texcoords, indices);
}
buffer->unmapBuffer();
mFaceList.clear();

View File

@ -63,11 +63,11 @@ public:
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ BOOL updateLOD();
/*virtual*/ void updateFaceSize(S32 idx);
void getGeometry(LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp);
void getTerrainGeometry(LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp);
/*virtual*/ void updateTextures();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area

View File

@ -177,6 +177,7 @@ F32 LLPipeline::CameraFocusTransitionTime;
F32 LLPipeline::CameraFNumber;
F32 LLPipeline::CameraFocalLength;
F32 LLPipeline::CameraFieldOfView;
S32 LLPipeline::RenderLocalLightCount;
F32 LLPipeline::RenderShadowNoise;
F32 LLPipeline::RenderShadowBlurSize;
F32 LLPipeline::RenderSSAOScale;
@ -215,6 +216,8 @@ S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples;
S32 LLPipeline::RenderBufferVisualization;
LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize");
const U32 LLPipeline::MAX_BAKE_WIDTH = 512;
const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
const F32 ALPHA_BLEND_CUTOFF = 0.598f;
@ -560,6 +563,7 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("CameraFNumber");
connectRefreshCachedSettingsSafe("CameraFocalLength");
connectRefreshCachedSettingsSafe("CameraFieldOfView");
connectRefreshCachedSettingsSafe("RenderLocalLightCount");
connectRefreshCachedSettingsSafe("RenderShadowNoise");
connectRefreshCachedSettingsSafe("RenderShadowBlurSize");
connectRefreshCachedSettingsSafe("RenderSSAOScale");
@ -830,10 +834,13 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (mRT == &mMainRT && sReflectionProbesEnabled)
if (mRT == &mMainRT)
{ // hacky -- allocate auxillary buffer
gCubeSnapshot = TRUE;
mReflectionMapManager.initReflectionMaps();
if (sReflectionProbesEnabled)
{
gCubeSnapshot = TRUE;
mReflectionMapManager.initReflectionMaps();
}
mRT = &mAuxillaryRT;
U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled
allocateScreenBuffer(res, res, samples);
@ -1109,6 +1116,7 @@ void LLPipeline::refreshCachedSettings()
CameraFNumber = gSavedSettings.getF32("CameraFNumber");
CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView");
RenderLocalLightCount = gSavedSettings.getS32("RenderLocalLightCount");
RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise");
RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize");
RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale");
@ -1174,7 +1182,6 @@ void LLPipeline::releaseGLBuffers()
releaseLUTBuffers();
mWaterDis.release();
mBake.release();
mSceneMap.release();
@ -1253,12 +1260,6 @@ void LLPipeline::createGLBuffers()
stop_glerror();
assertInitialized();
// Use FBO for bake tex
// <FS:Ansariel> Allow higher resolution rendering in mesh render preview
//mBake.allocate(512, 512, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview
mBake.allocate(1024, 1024, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview
// <FS:Ansariel>
stop_glerror();
GLuint resX = gViewerWindow->getWorldViewWidthRaw();
@ -5369,7 +5370,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
return;
}
static LLCachedControl<S32> local_light_count(gSavedSettings, "RenderLocalLightCount", 256);
const S32 local_light_count = LLPipeline::RenderLocalLightCount;
if (local_light_count >= 1)
{
@ -5638,7 +5639,7 @@ void LLPipeline::setupHWLights()
mLightMovingMask = 0;
static LLCachedControl<S32> local_light_count(gSavedSettings, "RenderLocalLightCount", 256);
const S32 local_light_count = LLPipeline::RenderLocalLightCount;
if (local_light_count >= 1)
{
@ -6678,7 +6679,7 @@ void LLPipeline::renderAlphaObjects(bool rigged)
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
mSimplePool->pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId);
LLRenderPass::pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId);
}
else
{
@ -6704,7 +6705,7 @@ void LLPipeline::renderAlphaObjects(bool rigged)
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
mSimplePool->pushGLTFBatch(*pparams);
LLRenderPass::pushGLTFBatch(*pparams);
}
else
{
@ -8145,7 +8146,7 @@ void LLPipeline::renderDeferredLighting()
unbindDeferredShader(gDeferredSoftenProgram);
}
static LLCachedControl<S32> local_light_count(gSavedSettings, "RenderLocalLightCount", 256);
const S32 local_light_count = LLPipeline::RenderLocalLightCount;
if (local_light_count > 0)
{

View File

@ -707,6 +707,7 @@ public:
RenderTargetPack mMainRT;
// auxillary 512x512 render target pack
// used by reflection probes and dynamic texture bakes
RenderTargetPack mAuxillaryRT;
// currently used render target pack
@ -767,7 +768,7 @@ public:
//water distortion texture (refraction)
LLRenderTarget mWaterDis;
LLRenderTarget mBake;
static const U32 MAX_BAKE_WIDTH;
//texture for making the glow
LLRenderTarget mGlow[3];
@ -1038,6 +1039,7 @@ public:
static F32 CameraFNumber;
static F32 CameraFocalLength;
static F32 CameraFieldOfView;
static S32 RenderLocalLightCount;
static F32 RenderShadowNoise;
static F32 RenderShadowBlurSize;
static F32 RenderSSAOScale;

View File

@ -4139,7 +4139,7 @@ Are you sure you want to return objects owned by [USER_NAME]?
Could not set region textures:
Terrain texture [TEXTURE_NUM] has an invalid bit depth of [TEXTURE_BIT_DEPTH].
Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller image then click &quot;Apply&quot; again.
Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image then click &quot;Apply&quot; again.
<tag>fail</tag>
</notification>
@ -4150,7 +4150,7 @@ Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller ima
Could not set region textures:
Terrain texture [TEXTURE_NUM] is too large at [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y].
Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller image then click &quot;Apply&quot; again.
Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image then click &quot;Apply&quot; again.
</notification>
<notification

View File

@ -76,29 +76,47 @@
left="8"
top="30"
width="460" />
<combo_box
layout="topleft"
left="10"
top="105"
follows="left|top"
name="terrain_material_type"
width="170">
<combo_box.item
label="Terrain Textures"
name="Textures"
value="Textures" />
<combo_box.item
label="Terrain PBR Materials"
name="PBRMaterials"
value="PBRMaterials" />
</combo_box>
<text
type="string"
length="1"
halign="left"
valign="center"
follows="left|top"
height="20"
layout="topleft"
left="10"
top_delta="0"
left_delta="180"
name="detail_texture_text"
top="110"
width="450">
Terrain Textures (1024x1024, 24 bit .tga files)
width="200">
Maximum size: 1024x1024
</text>
<texture_picker
follows="left|top"
height="100"
layout="topleft"
left_delta="0"
left="10"
name="texture_detail_0"
default_image_id="0bc58228-74a0-7e83-89bc-5c23464bcec5"
top_delta="20"
top_delta="30"
width="100" />
<texture_picker
follows="left|top"
follows="top"
height="100"
layout="topleft"
left_pad="10"
@ -124,6 +142,50 @@
default_image_id="53a2f406-4895-1d13-d541-d2e3b86bc19c"
top_delta="0"
width="100" />
<texture_picker
visible="false"
follows="left|top"
height="100"
layout="topleft"
left="10"
name="material_detail_0"
pick_type="material"
allow_no_texture="true"
top_delta="0"
width="100" />
<texture_picker
visible="false"
follows="left|top"
height="100"
layout="topleft"
left_pad="10"
name="material_detail_1"
pick_type="material"
allow_no_texture="true"
top_delta="0"
width="100" />
<texture_picker
visible="false"
follows="left|top"
height="100"
layout="topleft"
left_pad="10"
name="material_detail_2"
pick_type="material"
allow_no_texture="true"
top_delta="0"
width="100" />
<texture_picker
visible="false"
follows="left|top"
height="100"
layout="topleft"
left_pad="10"
name="material_detail_3"
pick_type="material"
allow_no_texture="true"
top_delta="0"
width="100" />
<text
type="string"
length="1"