Merge branch 'release/materials_featurette' into release/gltf-maint2
commit
846337483c
|
|
@ -0,0 +1,22 @@
|
|||
# PBR Terrain Feature Gating
|
||||
|
||||
PBR terrain should have lower detail on lower graphics settings. PBR terrain will also not show emissive textures on some machines (like Macs) which do not support more than 16 textures.
|
||||
|
||||
## Triplanar Mapping
|
||||
|
||||
Triplanar mapping improves the texture repeats on the sides of terrain slopes.
|
||||
|
||||
Availability of Triplanar mapping:
|
||||
|
||||
- Medium-High and below: No triplanar mapping
|
||||
- High and above: Triplanar mapping
|
||||
|
||||
## PBR Textures
|
||||
|
||||
At the highest graphics support level, PBR terrain supports all PBR textures.
|
||||
|
||||
Availability of PBR textures varies by machine and graphics setting:
|
||||
|
||||
- Low: Base color only (looks similar to texture terrain)
|
||||
- Medium-Low, and machines that do not support greater than 16 textures such as Macs: All PBR textures enabled except emissive textures.
|
||||
- Medium: All PBR textures enabled
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
- Texture terrain should load
|
||||
- PBR terrain should load if enabled
|
||||
- Related subsystem: A change to the PBR terrain loading system may affect the texture terrain loading system and vice-versa
|
||||
- Related subsystem: Minimaps should load if terrain loads (may take longer)
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "llmath.h"
|
||||
#include "v4coloru.h"
|
||||
#include "v3color.h"
|
||||
|
||||
#include "llimagebmp.h"
|
||||
#include "llimagetga.h"
|
||||
|
|
@ -1026,6 +1027,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
|
||||
|
|
@ -1110,7 +1139,7 @@ void LLImageRaw::composite( LLImageRaw* src )
|
|||
return;
|
||||
}
|
||||
|
||||
llassert(3 == src->getComponents());
|
||||
llassert((3 == src->getComponents()) || (4 == src->getComponents()));
|
||||
llassert(3 == dst->getComponents());
|
||||
|
||||
if( 3 == dst->getComponents() )
|
||||
|
|
@ -1268,6 +1297,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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -212,6 +213,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);
|
||||
|
|
@ -225,6 +228,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.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ class LLCamera
|
|||
: public LLCoordFrame
|
||||
{
|
||||
public:
|
||||
|
||||
LLCamera(const LLCamera& rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
|
|
|
|||
|
|
@ -6465,9 +6465,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;
|
||||
|
|
@ -6485,7 +6482,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++)
|
||||
|
|
@ -7195,7 +7192,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
|
||||
|
|
|
|||
|
|
@ -1142,6 +1142,8 @@ public:
|
|||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ void LLPluginProcessParent::idle(void)
|
|||
params.args.add("-e");
|
||||
params.args.add("tell application \"Terminal\"");
|
||||
params.args.add("-e");
|
||||
params.args.add(STRINGIZE("set win to do script \"gdb -pid "
|
||||
params.args.add(STRINGIZE("set win to do script \"lldb -pid "
|
||||
<< mProcess->getProcessID() << "\""));
|
||||
params.args.add("-e");
|
||||
params.args.add("do script \"continue\" in win");
|
||||
|
|
|
|||
|
|
@ -1934,6 +1934,19 @@ void LLReflectionProbeParams::setIsDynamic(bool is_dynamic)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLReflectionProbeParams::setIsMirror(bool is_mirror)
|
||||
{
|
||||
if (is_mirror)
|
||||
{
|
||||
mFlags |= FLAG_MIRROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
mFlags &= ~FLAG_MIRROR;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
LLFlexibleObjectData::LLFlexibleObjectData()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ public:
|
|||
{
|
||||
FLAG_BOX_VOLUME = 0x01, // use a box influence volume
|
||||
FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe
|
||||
FLAG_MIRROR = 0x04, // This probe is used for reflections on realtime mirrors.
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
@ -209,11 +210,13 @@ public:
|
|||
void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); }
|
||||
void setIsBox(bool is_box);
|
||||
void setIsDynamic(bool is_dynamic);
|
||||
void setIsMirror(bool is_mirror);
|
||||
|
||||
F32 getAmbiance() const { return mAmbiance; }
|
||||
F32 getClipDistance() const { return mClipDistance; }
|
||||
bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; }
|
||||
bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; }
|
||||
bool getIsMirror() const { return (mFlags & FLAG_MIRROR) != 0; }
|
||||
};
|
||||
|
||||
//-------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -685,6 +685,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
|
|||
mMaterialUpdatePending = true;
|
||||
}
|
||||
mMaterial = pMaterialParams;
|
||||
|
||||
return TEM_CHANGE_TEXTURE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public:
|
|||
S32 setGlow(F32 glow);
|
||||
S32 setMaterialID(const LLMaterialID& pMaterialID);
|
||||
S32 setMaterialParams(const LLMaterialPtr pMaterialParams);
|
||||
|
||||
|
||||
virtual const LLUUID &getID() const { return mID; }
|
||||
const LLColor4 &getColor() const { return mColor; }
|
||||
const F32 getAlpha() const { return mColor.mV[VALPHA]; }
|
||||
|
|
|
|||
|
|
@ -1184,12 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const
|
|||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
S32 index = mTexture[uniform];
|
||||
if (index != -1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ public:
|
|||
bool hasAlphaMask = false;
|
||||
bool hasReflectionProbes = false;
|
||||
bool attachNothing = false;
|
||||
bool hasHeroProbes = false;
|
||||
bool isPBRTerrain = false;
|
||||
};
|
||||
|
||||
// ============= Structure for caching shader uniforms ===============
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class LLGLTexture : public LLTexture
|
|||
public:
|
||||
enum
|
||||
{
|
||||
MAX_IMAGE_SIZE_DEFAULT = 1024,
|
||||
MAX_IMAGE_SIZE_DEFAULT = 2048,
|
||||
INVALID_DISCARD_LEVEL = 0x7fff
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ using std::make_pair;
|
|||
using std::string;
|
||||
|
||||
LLShaderMgr * LLShaderMgr::sInstance = NULL;
|
||||
bool LLShaderMgr::sMirrorsEnabled = false;
|
||||
|
||||
LLShaderMgr::LLShaderMgr()
|
||||
{
|
||||
|
|
@ -183,7 +184,13 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
// Attach Fragment Shader Features Next
|
||||
///////////////////////////////////////
|
||||
|
||||
// NOTE order of shader object attaching is VERY IMPORTANT!!!
|
||||
// NOTE order of shader object attaching is VERY IMPORTANT!!!
|
||||
|
||||
if (!shader->attachFragmentObject("deferred/globalF.glsl"))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred)
|
||||
{
|
||||
if (!shader->attachFragmentObject("environment/srgbF.glsl"))
|
||||
|
|
@ -277,6 +284,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)
|
||||
{
|
||||
|
|
@ -572,21 +587,38 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
}
|
||||
else
|
||||
{
|
||||
//set version to 1.40
|
||||
shader_code_text[shader_code_count++] = strdup("#version 140\n");
|
||||
//some implementations of GLSL 1.30 require integer precision be explicitly declared
|
||||
extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
|
||||
extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
|
||||
if (type == GL_GEOMETRY_SHADER)
|
||||
{
|
||||
//set version to 1.50
|
||||
shader_code_text[shader_code_count++] = strdup("#version 150\n");
|
||||
//some implementations of GLSL 1.30 require integer precision be explicitly declared
|
||||
extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
|
||||
extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//set version to 1.40
|
||||
shader_code_text[shader_code_count++] = strdup("#version 140\n");
|
||||
//some implementations of GLSL 1.30 require integer precision be explicitly declared
|
||||
extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
|
||||
extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
|
||||
}
|
||||
}
|
||||
|
||||
extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
|
||||
}
|
||||
|
||||
if (sMirrorsEnabled)
|
||||
{
|
||||
extra_code_text[extra_code_count++] = strdup("#define HERO_PROBES 1\n");
|
||||
}
|
||||
|
||||
// Use alpha float to store bit flags
|
||||
// See: C++: addDeferredAttachment(), shader: frag_data[2]
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_MIRROR 1.0\n"); // bit 2
|
||||
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
|
||||
|
||||
if (defines)
|
||||
|
|
@ -1192,6 +1224,9 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("emissiveColor");
|
||||
mReservedUniforms.push_back("metallicFactor");
|
||||
mReservedUniforms.push_back("roughnessFactor");
|
||||
mReservedUniforms.push_back("mirror_flag");
|
||||
mReservedUniforms.push_back("clipPlane");
|
||||
mReservedUniforms.push_back("clipSign");
|
||||
|
||||
mReservedUniforms.push_back("diffuseMap");
|
||||
mReservedUniforms.push_back("altDiffuseMap");
|
||||
|
|
@ -1204,6 +1239,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("sceneDepth");
|
||||
mReservedUniforms.push_back("reflectionProbes");
|
||||
mReservedUniforms.push_back("irradianceProbes");
|
||||
mReservedUniforms.push_back("heroProbes");
|
||||
mReservedUniforms.push_back("cloud_noise_texture");
|
||||
mReservedUniforms.push_back("cloud_noise_texture_next");
|
||||
mReservedUniforms.push_back("fullbright");
|
||||
|
|
@ -1374,8 +1410,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");
|
||||
|
||||
|
|
@ -1397,6 +1457,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("cloud_variance");
|
||||
mReservedUniforms.push_back("reflection_probe_ambiance");
|
||||
mReservedUniforms.push_back("max_probe_lod");
|
||||
mReservedUniforms.push_back("probe_strength");
|
||||
|
||||
mReservedUniforms.push_back("sh_input_r");
|
||||
mReservedUniforms.push_back("sh_input_g");
|
||||
|
|
@ -1407,6 +1468,8 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("sun_up_factor");
|
||||
mReservedUniforms.push_back("moonlight_color");
|
||||
|
||||
mReservedUniforms.push_back("debug_normal_draw_length");
|
||||
|
||||
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
|
||||
|
||||
std::set<std::string> dupe_check;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ public:
|
|||
EMISSIVE_COLOR, // "emissiveColor"
|
||||
METALLIC_FACTOR, // "metallicFactor"
|
||||
ROUGHNESS_FACTOR, // "roughnessFactor"
|
||||
MIRROR_FLAG, // "mirror_flag"
|
||||
CLIP_PLANE, // "clipPlane"
|
||||
CLIP_SIGN, // "clipSign"
|
||||
DIFFUSE_MAP, // "diffuseMap"
|
||||
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
|
||||
SPECULAR_MAP, // "specularMap"
|
||||
|
|
@ -96,6 +99,7 @@ public:
|
|||
SCENE_DEPTH, // "sceneDepth"
|
||||
REFLECTION_PROBES, // "reflectionProbes"
|
||||
IRRADIANCE_PROBES, // "irradianceProbes"
|
||||
HERO_PROBE, // "heroProbes"
|
||||
CLOUD_NOISE_MAP, // "cloud_noise_texture"
|
||||
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
|
||||
FULLBRIGHT, // "fullbright"
|
||||
|
|
@ -251,8 +255,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"
|
||||
|
||||
|
|
@ -279,6 +307,7 @@ public:
|
|||
|
||||
REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
|
||||
REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
|
||||
REFLECTION_PROBE_STRENGTH, // "probe_strength"
|
||||
SH_INPUT_L1R, // "sh_input_r"
|
||||
SH_INPUT_L1G, // "sh_input_g"
|
||||
SH_INPUT_L1B, // "sh_input_b"
|
||||
|
|
@ -287,6 +316,9 @@ public:
|
|||
WATER_EDGE_FACTOR, // "water_edge"
|
||||
SUN_UP_FACTOR, // "sun_up_factor"
|
||||
MOONLIGHT_COLOR, // "moonlight_color"
|
||||
|
||||
DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length"
|
||||
|
||||
END_RESERVED_UNIFORMS
|
||||
} eGLSLReservedUniforms;
|
||||
// clang-format on
|
||||
|
|
@ -336,6 +368,7 @@ public:
|
|||
bool mShaderCacheInitialized = false;
|
||||
bool mShaderCacheEnabled = false;
|
||||
std::string mShaderCacheDir;
|
||||
static bool sMirrorsEnabled;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -1319,6 +1319,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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -187,10 +188,6 @@ public:
|
|||
bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);
|
||||
bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
|
||||
bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ set(viewer_SOURCE_FILES
|
|||
llgiveinventory.cpp
|
||||
llglsandbox.cpp
|
||||
llgltfmateriallist.cpp
|
||||
llgltfmaterialpreviewmgr.cpp
|
||||
llgroupactions.cpp
|
||||
llgroupiconctrl.cpp
|
||||
llgrouplist.cpp
|
||||
|
|
@ -519,6 +520,7 @@ set(viewer_SOURCE_FILES
|
|||
llrecentpeople.cpp
|
||||
llreflectionmap.cpp
|
||||
llreflectionmapmanager.cpp
|
||||
llheroprobemanager.cpp
|
||||
llregioninfomodel.cpp
|
||||
llregionposition.cpp
|
||||
llremoteparcelrequest.cpp
|
||||
|
|
@ -963,6 +965,7 @@ set(viewer_HEADER_FILES
|
|||
llgesturemgr.h
|
||||
llgiveinventory.h
|
||||
llgltfmateriallist.h
|
||||
llgltfmaterialpreviewmgr.h
|
||||
llgroupactions.h
|
||||
llgroupiconctrl.h
|
||||
llgrouplist.h
|
||||
|
|
@ -1158,6 +1161,7 @@ set(viewer_HEADER_FILES
|
|||
llrecentpeople.h
|
||||
llreflectionmap.h
|
||||
llreflectionmapmanager.h
|
||||
llheroprobemanager.h
|
||||
llregioninfomodel.h
|
||||
llregionposition.h
|
||||
llremoteparcelrequest.h
|
||||
|
|
|
|||
|
|
@ -9153,6 +9153,17 @@
|
|||
<real>0.00</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>RenderMirrors</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Renders realtime mirrors.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderScreenSpaceReflections</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -10357,6 +10368,28 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderHeroProbeResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Resolution to render hero probes used for mirrors, water, etc.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
<key>RenderHeroProbeDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Distance in meters for hero probes to render out to.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>8</real>
|
||||
</map>
|
||||
<key>RenderReflectionProbeVolumes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -10781,7 +10814,7 @@
|
|||
<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>
|
||||
|
|
@ -10789,6 +10822,83 @@
|
|||
<key>Value</key>
|
||||
<real>12.0</real>
|
||||
</map>
|
||||
<key>RenderTerrainPBREnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>EXPERIMENTAL: Enable PBR Terrain features. Requires restart.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderTerrainPBRForce</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Force-load PBR terrain if enabled</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</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 when possible, which reduces the number of texture binds.</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>RenderTerrainPBRNormalsEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>EXPERIMENTAL: Change normal gen for PBR Terrain.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderTrackerBeacon</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -13719,6 +13829,17 @@
|
|||
<key>Value</key>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
<key>UIPreviewMaterial</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether or not PBR material swatch is enabled</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<real>0</real>
|
||||
</map>
|
||||
<key>UIResizeBarHeight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -15634,7 +15755,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>2048</integer>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
<key>max_texture_dimension_Y</key>
|
||||
<map>
|
||||
|
|
@ -15645,7 +15766,7 @@
|
|||
<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>
|
||||
|
|
@ -16520,6 +16641,50 @@
|
|||
<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>
|
||||
|
|
|
|||
|
|
@ -33,11 +33,15 @@ uniform float minimum_alpha;
|
|||
|
||||
in vec3 vary_normal;
|
||||
in vec2 vary_texcoord0;
|
||||
in vec3 vary_position;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec4 diff = texture(diffuseMap, vary_texcoord0.xy);
|
||||
|
||||
if (diff.a < minimum_alpha)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ in vec4 weight;
|
|||
|
||||
out vec3 vary_normal;
|
||||
out vec2 vary_texcoord0;
|
||||
out vec3 vary_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -57,6 +58,7 @@ void main()
|
|||
|
||||
vary_normal = norm;
|
||||
|
||||
vary_position = pos.xyz;
|
||||
gl_Position = projection_matrix * pos;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,11 +37,15 @@ in vec3 vary_mat2;
|
|||
|
||||
in vec4 vertex_color;
|
||||
in vec2 vary_texcoord0;
|
||||
in vec3 vary_position;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec4 col = texture(diffuseMap, vary_texcoord0.xy);
|
||||
|
||||
if(col.a < minimum_alpha)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat3 normal_matrix;
|
||||
uniform mat4 texture_matrix0;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
|
@ -38,11 +39,11 @@ out vec3 vary_mat1;
|
|||
out vec3 vary_mat2;
|
||||
out vec4 vertex_color;
|
||||
out vec2 vary_texcoord0;
|
||||
out vec3 vary_position;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
|
|
@ -52,11 +53,13 @@ void main()
|
|||
mat4 mat = getObjectSkinnedTransform();
|
||||
mat = modelview_matrix * mat;
|
||||
vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
|
||||
vary_position = pos;
|
||||
gl_Position = projection_matrix*vec4(pos, 1.0);
|
||||
|
||||
vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz);
|
||||
vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz);
|
||||
#else
|
||||
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
vec3 n = normalize(normal_matrix * normal);
|
||||
vec3 t = normalize(normal_matrix * tangent.xyz);
|
||||
|
|
|
|||
|
|
@ -31,14 +31,20 @@ uniform float minimum_alpha;
|
|||
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
in vec3 vary_position;
|
||||
|
||||
in vec3 vary_normal;
|
||||
in vec4 vertex_color;
|
||||
in vec2 vary_texcoord0;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color;
|
||||
|
||||
if (col.a < minimum_alpha)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
out vec4 frag_data[4];
|
||||
|
||||
in vec3 vary_normal;
|
||||
in vec3 vary_position;
|
||||
|
||||
uniform float minimum_alpha;
|
||||
|
||||
|
|
@ -36,8 +37,12 @@ in vec2 vary_texcoord0;
|
|||
|
||||
vec2 encode_normal(vec3 n);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color;
|
||||
|
||||
if (col.a < minimum_alpha)
|
||||
|
|
|
|||
|
|
@ -32,11 +32,14 @@ uniform sampler2D diffuseMap;
|
|||
in vec3 vary_normal;
|
||||
in vec4 vertex_color;
|
||||
in vec2 vary_texcoord0;
|
||||
in vec3 vary_position;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb;
|
||||
frag_data[0] = vec4(col, 0.0);
|
||||
frag_data[1] = vertex_color.aaaa; // spec
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@ out vec4 frag_data[4];
|
|||
in vec3 vary_normal;
|
||||
in vec4 vertex_color;
|
||||
in vec2 vary_texcoord0;
|
||||
in vec3 vary_position;
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
vec2 encode_normal(vec3 n);
|
||||
vec3 linear_to_srgb(vec3 c);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
|
||||
|
||||
vec3 spec;
|
||||
|
|
|
|||
|
|
@ -36,13 +36,16 @@ out vec3 vary_normal;
|
|||
|
||||
out vec4 vertex_color;
|
||||
out vec2 vary_texcoord0;
|
||||
out vec3 vary_position;
|
||||
|
||||
void passTextureIndex();
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
#endif
|
||||
|
||||
void main()
|
||||
|
|
@ -51,9 +54,11 @@ void main()
|
|||
mat4 mat = getObjectSkinnedTransform();
|
||||
mat = modelview_matrix * mat;
|
||||
vec4 pos = mat * vec4(position.xyz, 1.0);
|
||||
vary_position = pos.xyz;
|
||||
gl_Position = projection_matrix * pos;
|
||||
vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
|
||||
#else
|
||||
vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
|
||||
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
vary_normal = normalize(normal_matrix * normal);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,9 +50,11 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
|
|||
vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color);
|
||||
#endif
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
mirrorClip(vary_position);
|
||||
#ifdef IS_ALPHA
|
||||
waterClip(vary_position.xyz);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file class1/deferred/globalF.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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$
|
||||
*/
|
||||
|
||||
|
||||
// Global helper functions included in every fragment shader
|
||||
// DO NOT declare sampler uniforms here as OS X doesn't compile
|
||||
// them out
|
||||
|
||||
uniform float mirror_flag;
|
||||
uniform vec4 clipPlane;
|
||||
uniform float clipSign;
|
||||
|
||||
void mirrorClip(vec3 pos)
|
||||
{
|
||||
if (mirror_flag > 0)
|
||||
{
|
||||
if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -28,25 +28,18 @@
|
|||
#define DIFFUSE_ALPHA_MODE_MASK 2
|
||||
#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
#else
|
||||
uniform mat3 normal_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
#endif
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
|
||||
#if !defined(HAS_SKIN)
|
||||
uniform mat4 modelview_matrix;
|
||||
#endif
|
||||
|
||||
out vec3 vary_position;
|
||||
|
||||
#endif
|
||||
|
||||
uniform mat4 texture_matrix0;
|
||||
|
||||
in vec3 position;
|
||||
|
|
@ -85,9 +78,7 @@ void main()
|
|||
|
||||
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
vary_position = pos;
|
||||
#endif
|
||||
|
||||
gl_Position = projection_matrix*vec4(pos,1.0);
|
||||
|
||||
|
|
@ -133,10 +124,8 @@ void main()
|
|||
|
||||
vertex_color = diffuse_color;
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
#if !defined(HAS_SKIN)
|
||||
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,10 +58,17 @@ vec2 encode_normal(vec3 n);
|
|||
vec3 linear_to_srgb(vec3 c);
|
||||
vec3 srgb_to_linear(vec3 c);
|
||||
|
||||
uniform vec4 clipPlane;
|
||||
uniform float clipSign;
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
uniform mat3 normal_matrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
|
||||
if (basecolor.a < minimum_alpha)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,8 +28,9 @@
|
|||
|
||||
//deferred opaque implementation
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
uniform mat4 projection_matrix;
|
||||
mat4 getObjectSkinnedTransform();
|
||||
#else
|
||||
|
|
@ -59,6 +60,7 @@ out vec4 vertex_color;
|
|||
out vec3 vary_tangent;
|
||||
flat out float vary_sign;
|
||||
out vec3 vary_normal;
|
||||
out vec3 vary_position;
|
||||
|
||||
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);
|
||||
|
|
@ -71,10 +73,11 @@ void main()
|
|||
mat = modelview_matrix * mat;
|
||||
|
||||
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
|
||||
|
||||
vary_position = pos;
|
||||
gl_Position = projection_matrix*vec4(pos,1.0);
|
||||
|
||||
#else
|
||||
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
//transform vertex
|
||||
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,344 @@
|
|||
/**
|
||||
* @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
|
||||
#define TERRAIN_PBR_DETAIL_OCCLUSION -1
|
||||
#define TERRAIN_PBR_DETAIL_NORMAL -2
|
||||
#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
|
||||
|
||||
#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
|
||||
|
||||
struct TerrainMix
|
||||
{
|
||||
vec4 weight;
|
||||
int type;
|
||||
};
|
||||
|
||||
TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal);
|
||||
|
||||
struct PBRMix
|
||||
{
|
||||
vec4 col; // RGB color with alpha, linear space
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
vec3 orm; // Occlusion, roughness, metallic
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
vec2 rm; // Roughness, metallic
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
vec3 vNt; // Unpacked normal texture sample, vector
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, sampler2D tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, sampler2D tex_vNt
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, sampler2D tex_emissive
|
||||
#endif
|
||||
, vec4 factor_col
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, vec3 factor_orm
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, vec2 factor_rm
|
||||
#endif
|
||||
#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;
|
||||
|
||||
// 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;
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
uniform sampler2D detail_0_normal;
|
||||
uniform sampler2D detail_1_normal;
|
||||
uniform sampler2D detail_2_normal;
|
||||
uniform sampler2D detail_3_normal;
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
uniform sampler2D detail_0_metallic_roughness;
|
||||
uniform sampler2D detail_1_metallic_roughness;
|
||||
uniform sampler2D detail_2_metallic_roughness;
|
||||
uniform sampler2D detail_3_metallic_roughness;
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
uniform vec4 metallicFactors;
|
||||
uniform vec4 roughnessFactors;
|
||||
#endif
|
||||
#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);
|
||||
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
// 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);
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
vec2[4] rm_factors;
|
||||
rm_factors[0] = vec2(roughnessFactors.x, metallicFactors.x);
|
||||
rm_factors[1] = vec2(roughnessFactors.y, metallicFactors.y);
|
||||
rm_factors[2] = vec2(roughnessFactors.z, metallicFactors.z);
|
||||
rm_factors[3] = vec2(roughnessFactors.w, metallicFactors.w);
|
||||
#endif
|
||||
|
||||
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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, detail_0_metallic_roughness
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, detail_0_normal
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, detail_0_emissive
|
||||
#endif
|
||||
, baseColorFactors[0]
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, orm_factors[0]
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, rm_factors[0]
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, detail_1_metallic_roughness
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, detail_1_normal
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, detail_1_emissive
|
||||
#endif
|
||||
, baseColorFactors[1]
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, orm_factors[1]
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, rm_factors[1]
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, detail_2_metallic_roughness
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, detail_2_normal
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, detail_2_emissive
|
||||
#endif
|
||||
, baseColorFactors[2]
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, orm_factors[2]
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, rm_factors[2]
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, detail_3_metallic_roughness
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, detail_3_normal
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, detail_3_emissive
|
||||
#endif
|
||||
, baseColorFactors[3]
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, orm_factors[3]
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, rm_factors[3]
|
||||
#endif
|
||||
#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));
|
||||
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
// from mikktspace.com
|
||||
vec3 vNt = mix.vNt;
|
||||
vec3 vN = vary_normal;
|
||||
vec3 vT = vary_tangent.xyz;
|
||||
|
||||
vec3 vB = vary_sign * cross(vN, vT);
|
||||
vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
|
||||
|
||||
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
|
||||
#else
|
||||
vec3 tnorm = vary_normal;
|
||||
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
|
||||
#endif
|
||||
|
||||
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
#define emissive mix.emissive
|
||||
#else
|
||||
#define emissive vec3(0)
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
#define orm mix.orm
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
#define orm vec3(1.0, mix.rm)
|
||||
#else
|
||||
// Matte plastic potato terrain
|
||||
#define orm vec3(1.0, 1.0, 0.0)
|
||||
#endif
|
||||
frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse
|
||||
frag_data[1] = max(vec4(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
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,473 @@
|
|||
/**
|
||||
* @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
|
||||
#define TERRAIN_PBR_DETAIL_OCCLUSION -1
|
||||
#define TERRAIN_PBR_DETAIL_NORMAL -2
|
||||
#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
|
||||
|
||||
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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
vec3 orm; // Occlusion, roughness, metallic
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
vec2 rm; // Roughness, metallic
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
vec3 vNt; // Unpacked normal texture sample, vector
|
||||
#endif
|
||||
#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);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
mix.orm = vec3(0);
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
mix.rm = vec2(0);
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix.vNt = vec3(0);
|
||||
#endif
|
||||
#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);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
mix.orm = mix1.orm + (mix2.orm * mix2_weight);
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
mix.rm = mix1.rm + (mix2.rm * mix2_weight);
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix.vNt = mix1.vNt + (mix2.vNt * mix2_weight);
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, sampler2D tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, sampler2D tex_vNt
|
||||
#endif
|
||||
#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);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
mix.orm = texture(tex_orm, uv).xyz;
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
mix.rm = texture(tex_orm, uv).yz;
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
mix.vNt = texture(tex_vNt, uv).xyz*2.0-1.0;
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, sampler2D tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, sampler2D tex_vNt
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, tex_vNt
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, tex_emissive
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
// Triplanar-specific normal texture fix
|
||||
mix_x.vNt = _t_normal_post_x(mix_x.vNt);
|
||||
#endif
|
||||
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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, tex_vNt
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, tex_emissive
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
// Triplanar-specific normal texture fix
|
||||
mix_y.vNt = _t_normal_post_y(mix_y.vNt);
|
||||
#endif
|
||||
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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, tex_vNt
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, tex_emissive
|
||||
#endif
|
||||
);
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
// Triplanar-specific normal texture fix
|
||||
// *NOTE: Bottom face has not been tested
|
||||
mix_z.vNt = _t_normal_post_z(mix_z.vNt);
|
||||
#endif
|
||||
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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, vec3 factor_orm
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, vec2 factor_rm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, vec3 factor_emissive
|
||||
#endif
|
||||
)
|
||||
{
|
||||
PBRMix mix = mix_in;
|
||||
mix.col *= factor_col;
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
mix.orm *= factor_orm;
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
mix.rm *= factor_rm;
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, sampler2D tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, sampler2D tex_vNt
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, sampler2D tex_emissive
|
||||
#endif
|
||||
, vec4 factor_col
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, vec3 factor_orm
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, vec2 factor_rm
|
||||
#endif
|
||||
#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
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, tex_orm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
, tex_vNt
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, tex_emissive
|
||||
#endif
|
||||
);
|
||||
|
||||
mix = multiply_factors_pbr(mix
|
||||
, factor_col
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
|
||||
, factor_orm
|
||||
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
, factor_rm
|
||||
#endif
|
||||
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
|
||||
, factor_emissive
|
||||
#endif
|
||||
);
|
||||
|
||||
return mix;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -39,9 +39,11 @@ in vec4 vary_texcoord0;
|
|||
in vec4 vary_texcoord1;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
void mirrorClip(vec3 position);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(pos);
|
||||
/// Note: This should duplicate the blending functionality currently used for the terrain rendering.
|
||||
|
||||
vec4 color0 = texture(detail_0, vary_texcoord0.xy);
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
|
||||
uniform mat3 normal_matrix;
|
||||
uniform mat4 texture_matrix0;
|
||||
uniform mat4 modelview_matrix;
|
||||
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 +41,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()
|
||||
|
|
@ -62,12 +60,12 @@ void main()
|
|||
vec4 t_pos = modelview_projection_matrix * pre_pos;
|
||||
|
||||
gl_Position = t_pos;
|
||||
pos = t_pos.xyz;
|
||||
pos = (modelview_matrix*pre_pos).xyz;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -32,13 +32,16 @@ uniform sampler2D diffuseMap;
|
|||
in vec4 vertex_color;
|
||||
in vec3 vary_normal;
|
||||
in vec2 vary_texcoord0;
|
||||
in vec3 vary_position;
|
||||
|
||||
uniform float minimum_alpha;
|
||||
|
||||
vec2 encode_normal(vec3 n);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vec4 col = texture(diffuseMap, vary_texcoord0.xy);
|
||||
if (col.a < minimum_alpha)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
uniform mat4 texture_matrix0;
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
uniform mat3 normal_matrix;
|
||||
|
||||
|
|
@ -34,11 +35,14 @@ in vec2 texcoord0;
|
|||
out vec3 vary_normal;
|
||||
out vec4 vertex_color;
|
||||
out vec2 vary_texcoord0;
|
||||
out vec3 vary_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
//transform vertex
|
||||
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
|
||||
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
|
||||
|
||||
vary_normal = normalize(normal_matrix * normal);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* @file normaldebugF.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$
|
||||
*/
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
in vec4 vertex_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
frag_color = max(vertex_color, vec4(0));
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* @file normaldebugG.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$
|
||||
*/
|
||||
|
||||
// *NOTE: Geometry shaders have a reputation for being slow. Consider using
|
||||
// compute shaders instead, which have a reputation for being fast. This
|
||||
// geometry shader in particular seems to run fine on my machine, but I won't
|
||||
// vouch for this in performance-critical areas.
|
||||
// -Cosmic,2023-09-28
|
||||
|
||||
out vec4 vertex_color;
|
||||
|
||||
in vec4 normal_g[];
|
||||
#if HAS_ATTRIBUTE_TANGENT == 1
|
||||
in vec4 tangent_g[];
|
||||
#endif
|
||||
|
||||
layout(TRIANGLES) in;
|
||||
#if HAS_ATTRIBUTE_TANGENT == 1
|
||||
layout(LINE_STRIP, max_vertices = 12) out;
|
||||
#else
|
||||
layout(LINE_STRIP, max_vertices = 6) out;
|
||||
#endif
|
||||
|
||||
void triangle_normal_debug(int i)
|
||||
{
|
||||
// Normal
|
||||
vec4 normal_color = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
vertex_color = normal_color;
|
||||
EmitVertex();
|
||||
gl_Position = normal_g[i];
|
||||
vertex_color = normal_color;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
|
||||
#if HAS_ATTRIBUTE_TANGENT == 1
|
||||
// Tangent
|
||||
vec4 tangent_color = vec4(0.0, 1.0, 1.0, 1.0);
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
vertex_color = tangent_color;
|
||||
EmitVertex();
|
||||
gl_Position = tangent_g[i];
|
||||
vertex_color = tangent_color;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
#endif
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
triangle_normal_debug(0);
|
||||
triangle_normal_debug(1);
|
||||
triangle_normal_debug(2);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file normaldebugV.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$
|
||||
*/
|
||||
|
||||
in vec3 position;
|
||||
in vec3 normal;
|
||||
out vec4 normal_g;
|
||||
#if HAS_ATTRIBUTE_TANGENT == 1
|
||||
in vec4 tangent;
|
||||
out vec4 tangent_g;
|
||||
#endif
|
||||
|
||||
uniform float debug_normal_draw_length;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
#else
|
||||
uniform mat3 normal_matrix;
|
||||
#endif
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
// *NOTE: Should use the modelview_projection_matrix here in the non-skinned
|
||||
// case for efficiency, but opting for the simplier implementation for now as
|
||||
// this is debug code. Also, the skinned version hasn't beeen tested yet.
|
||||
// world_pos = mat * vec4(position.xyz, 1.0)
|
||||
vec4 get_screen_normal(vec3 position, vec4 world_pos, vec3 normal, mat4 mat)
|
||||
{
|
||||
vec4 world_norm = mat * vec4((position + normal), 1.0);
|
||||
world_norm.xyz -= world_pos.xyz;
|
||||
world_norm.xyz = debug_normal_draw_length * normalize(world_norm.xyz);
|
||||
world_norm.xyz += world_pos.xyz;
|
||||
return projection_matrix * world_norm;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef HAS_SKIN
|
||||
mat4 mat = getObjectSkinnedTransform();
|
||||
mat = modelview_matrix * mat;
|
||||
#else
|
||||
#define mat modelview_matrix
|
||||
#endif
|
||||
|
||||
vec4 world_pos = mat * vec4(position.xyz,1.0);
|
||||
|
||||
gl_Position = projection_matrix * world_pos;
|
||||
normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat);
|
||||
#if HAS_ATTRIBUTE_TANGENT == 1
|
||||
tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -38,6 +38,7 @@ in vec3 vary_dir;
|
|||
uniform float mipLevel;
|
||||
uniform int u_width;
|
||||
uniform float max_probe_lod;
|
||||
uniform float probe_strength;
|
||||
|
||||
|
||||
// =============================================================================================================
|
||||
|
|
@ -129,7 +130,7 @@ vec4 prefilterEnvMap(vec3 R)
|
|||
float totalWeight = 0.0;
|
||||
float envMapDim = float(textureSize(reflectionProbes, 0).s);
|
||||
float roughness = mipLevel/max_probe_lod;
|
||||
int numSamples = max(int(32*roughness), 1);
|
||||
int numSamples = max(int(PROBE_FILTER_SAMPLES*roughness), 1);
|
||||
|
||||
float numMips = max_probe_lod+1;
|
||||
|
||||
|
|
@ -163,5 +164,6 @@ void main()
|
|||
{
|
||||
vec3 N = normalize(vary_dir);
|
||||
frag_color = max(prefilterEnvMap(N), vec4(0));
|
||||
frag_color.a *= probe_strength;
|
||||
}
|
||||
// =============================================================================================================
|
||||
|
|
|
|||
|
|
@ -30,9 +30,13 @@ uniform sampler2D texture1;
|
|||
|
||||
in vec2 vary_texcoord0;
|
||||
in vec2 vary_texcoord1;
|
||||
in vec3 vary_position;
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
float tex0 = texture(texture0, vary_texcoord0.xy).a;
|
||||
float tex1 = texture(texture1, vary_texcoord1.xy).a;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 texture_matrix0;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
|
|
@ -32,11 +33,11 @@ in vec2 texcoord1;
|
|||
|
||||
out vec2 vary_texcoord0;
|
||||
out vec2 vary_texcoord1;
|
||||
out vec3 vary_position;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
|
|
@ -46,8 +47,10 @@ void main()
|
|||
mat4 mat = getObjectSkinnedTransform();
|
||||
mat = modelview_matrix * mat;
|
||||
vec4 pos = mat * vec4(position.xyz, 1.0);
|
||||
vary_position = pos.xyz;
|
||||
gl_Position = projection_matrix * pos;
|
||||
#else
|
||||
vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
|
||||
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
|
||||
#endif
|
||||
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
|
|||
|
||||
float getAmbientClamp();
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
|
||||
|
||||
|
|
@ -167,6 +169,8 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec
|
|||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
|
||||
|
||||
vec4 pos = vec4(vary_position, 1.0);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
|
|||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
void waterClip(vec3 pos);
|
||||
|
||||
void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor);
|
||||
|
|
@ -156,6 +157,8 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
|
|||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vec3 color = vec3(0,0,0);
|
||||
|
||||
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
|
||||
|
|
|
|||
|
|
@ -53,8 +53,11 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
|
|||
|
||||
void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
#ifdef HAS_DIFFUSE_LOOKUP
|
||||
vec4 color = diffuseLookup(vary_texcoord0.xy);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -45,6 +45,13 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float
|
|||
vec3 srgb_to_linear(vec3 cs);
|
||||
vec3 linear_to_srgb(vec3 cs);
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat3 normal_matrix;
|
||||
|
||||
in vec3 vary_position;
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
|
||||
out vec4 frag_color;
|
||||
|
|
@ -66,12 +73,12 @@ uniform vec4 morphFactor;
|
|||
uniform vec3 camPosLocal;
|
||||
uniform mat3 env_mat;
|
||||
|
||||
uniform float is_mirror;
|
||||
|
||||
uniform vec3 sun_dir;
|
||||
uniform vec3 moon_dir;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
in vec3 vary_position;
|
||||
|
||||
uniform mat4 proj_mat;
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
|
|
@ -285,12 +292,12 @@ float getShadow(vec3 pos, vec3 norm)
|
|||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
waterClip();
|
||||
|
||||
// diffcol == diffuse map combined with vertex color
|
||||
vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy);
|
||||
diffcol.rgb *= vertex_color.rgb;
|
||||
|
||||
alphaMask(diffcol.a);
|
||||
|
||||
// spec == specular map combined with specular color
|
||||
|
|
@ -407,9 +414,12 @@ void main()
|
|||
|
||||
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
|
||||
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
|
||||
|
||||
float flag = GBUFFER_FLAG_HAS_ATMOS;
|
||||
|
||||
frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials
|
||||
frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent.
|
||||
frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
|
||||
frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
|
||||
frag_data[3] = vec4(0);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n,
|
|||
|
||||
uniform samplerCubeArray reflectionProbes;
|
||||
uniform samplerCubeArray irradianceProbes;
|
||||
|
||||
uniform sampler2D sceneMap;
|
||||
uniform int cube_snapshot;
|
||||
uniform float max_probe_lod;
|
||||
|
|
@ -681,6 +682,35 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
|
|||
return col[1]+col[0];
|
||||
}
|
||||
|
||||
|
||||
#if defined(HERO_PROBES)
|
||||
|
||||
uniform vec4 clipPlane;
|
||||
uniform samplerCubeArray heroProbes;
|
||||
|
||||
void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
|
||||
{
|
||||
float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w;
|
||||
if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8)
|
||||
{
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0)
|
||||
{
|
||||
glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit)
|
||||
{
|
||||
|
|
@ -712,6 +742,8 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
|
|||
glossenv = mix(glossenv, ssr.rgb, ssr.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
tapHeroProbe(glossenv, pos, norm, glossiness);
|
||||
}
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
|
|
@ -799,6 +831,7 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
|
|||
{
|
||||
float lod = (1.0-glossiness)*reflection_lods;
|
||||
glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
|
||||
|
||||
}
|
||||
|
||||
if (envIntensity > 0.0)
|
||||
|
|
@ -826,6 +859,9 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
|
|||
}
|
||||
#endif
|
||||
|
||||
tapHeroProbe(glossenv, pos, norm, glossiness);
|
||||
tapHeroProbe(legacyenv, pos, norm, 1.0);
|
||||
|
||||
glossenv = clamp(glossenv, vec3(0), vec3(10));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,16 @@ uniform sampler2D specularRect;
|
|||
uniform sampler2D normalMap;
|
||||
uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
|
||||
|
||||
uniform samplerCubeArray heroProbes;
|
||||
|
||||
#if defined(HERO_PROBES)
|
||||
layout (std140) uniform HeroProbeData
|
||||
{
|
||||
vec4 heroPosition[1];
|
||||
int heroProbeCount;
|
||||
};
|
||||
#endif
|
||||
|
||||
const float M_PI = 3.14159265;
|
||||
|
||||
#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
|
||||
|
|
@ -50,6 +60,7 @@ uniform float ssao_irradiance_max;
|
|||
#endif
|
||||
|
||||
// Inputs
|
||||
uniform vec4 clipPlane;
|
||||
uniform mat3 env_mat;
|
||||
uniform mat3 ssao_effect_mat;
|
||||
uniform vec3 sun_dir;
|
||||
|
|
@ -178,7 +189,7 @@ void main()
|
|||
float gloss = 1.0 - perceptualRoughness;
|
||||
|
||||
sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss, false, amblit_linear);
|
||||
|
||||
|
||||
adjustIrradiance(irradiance, ambocc);
|
||||
|
||||
vec3 diffuseColor;
|
||||
|
|
@ -209,7 +220,7 @@ void main()
|
|||
vec3 legacyenv = vec3(0);
|
||||
|
||||
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity, false, amblit_linear);
|
||||
|
||||
|
||||
adjustIrradiance(irradiance, ambocc);
|
||||
|
||||
// apply lambertian IBL only (see pbrIbl)
|
||||
|
|
@ -244,6 +255,7 @@ void main()
|
|||
|
||||
// add radiance map
|
||||
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
|
||||
|
||||
}
|
||||
|
||||
color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a);
|
||||
|
|
|
|||
|
|
@ -55,9 +55,11 @@ in vec4 view;
|
|||
in vec3 vary_position;
|
||||
|
||||
vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color);
|
||||
void mirrorClip(vec3 position);
|
||||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vec4 color;
|
||||
|
||||
//get detail normals
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ vec3 scaleSoftClipFragLinear(vec3 l);
|
|||
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
|
||||
vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
||||
// PBR interface
|
||||
vec2 BRDF(float NoV, float roughness);
|
||||
|
||||
|
|
@ -129,6 +131,7 @@ vec3 getPositionWithNDC(vec3 ndc);
|
|||
|
||||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vN = vary_normal;
|
||||
vT = vary_tangent;
|
||||
vB = cross(vN, vT);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version 59
|
||||
version 60
|
||||
// The version number above should be incremented IF AND ONLY IF some
|
||||
// change has been made that is sufficiently important to justify
|
||||
// resetting the graphics preferences of all users to the recommended
|
||||
|
|
@ -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,8 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderTerrainDetail 1 0
|
||||
RenderTerrainLODFactor 1 1
|
||||
RenderTerrainPBRDetail 1 -4
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTreeLODFactor 1 0
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
RenderDeferredSSAO 1 0
|
||||
|
|
@ -123,6 +127,8 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 1.0
|
||||
RenderTerrainPBRDetail 1 -1
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
RenderDeferredSSAO 1 0
|
||||
|
|
@ -150,6 +156,8 @@ RenderLocalLightCount 1 512
|
|||
RenderTransparentWater 1 0
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.25
|
||||
RenderDeferredSSAO 1 0
|
||||
|
|
@ -179,6 +187,8 @@ RenderLocalLightCount 1 1024
|
|||
RenderTransparentWater 1 1
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.375
|
||||
RenderDeferredSSAO 1 0
|
||||
|
|
@ -208,6 +218,8 @@ RenderLocalLightCount 1 2048
|
|||
RenderTransparentWater 1 1
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.5
|
||||
RenderDeferredSSAO 1 1
|
||||
|
|
@ -236,6 +248,8 @@ RenderMaxPartCount 1 4096
|
|||
RenderLocalLightCount 1 4096
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.75
|
||||
|
|
@ -264,6 +278,8 @@ RenderLocalLightCount 1 8192
|
|||
RenderMaxPartCount 1 8192
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 1.0
|
||||
RenderVolumeLODFactor 1 2.0
|
||||
|
|
@ -321,3 +337,5 @@ RenderFSAASamples 0 0
|
|||
RenderReflectionsEnabled 0 0
|
||||
RenderReflectionProbeDetail 0 0
|
||||
|
||||
list TexUnit16orLess
|
||||
RenderTerrainPBRDetail 1 -1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version 56
|
||||
version 57
|
||||
// The version number above should be incremented IF AND ONLY IF some
|
||||
// change has been made that is sufficiently important to justify
|
||||
// resetting the graphics preferences of all users to the recommended
|
||||
|
|
@ -45,6 +45,8 @@ RenderObjectBump 1 1
|
|||
RenderLocalLightCount 1 4096
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 1.0
|
||||
RenderVBOEnable 1 1
|
||||
|
|
@ -89,6 +91,8 @@ RenderLocalLightCount 1 8
|
|||
RenderMaxPartCount 1 0
|
||||
RenderTerrainDetail 1 0
|
||||
RenderTerrainLODFactor 1 1
|
||||
RenderTerrainPBRDetail 1 -4
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTransparentWater 1 0
|
||||
RenderTreeLODFactor 1 0
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
|
|
@ -118,6 +122,8 @@ RenderMaxPartCount 1 2048
|
|||
RenderLocalLightCount 1 256
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 1.0
|
||||
RenderTerrainPBRDetail 1 -1
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
|
|
@ -147,6 +153,8 @@ RenderMaxPartCount 1 4096
|
|||
RenderLocalLightCount 1 512
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.25
|
||||
|
|
@ -176,6 +184,8 @@ RenderMaxPartCount 1 4096
|
|||
RenderLocalLightCount 1 1024
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 1
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.375
|
||||
|
|
@ -205,6 +215,8 @@ RenderMaxPartCount 1 4096
|
|||
RenderLocalLightCount 1 2048
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.5
|
||||
|
|
@ -234,6 +246,8 @@ RenderMaxPartCount 1 4096
|
|||
RenderLocalLightCount 1 4096
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 0.5
|
||||
RenderVolumeLODFactor 1 1.75
|
||||
|
|
@ -262,6 +276,8 @@ RenderLocalLightCount 1 8192
|
|||
RenderMaxPartCount 1 8192
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTerrainPBRDetail 1 0
|
||||
RenderTerrainPBRPlanarSampleCount 1 3
|
||||
RenderTransparentWater 1 1
|
||||
RenderTreeLODFactor 1 1.0
|
||||
RenderVolumeLODFactor 1 2.0
|
||||
|
|
@ -308,6 +324,9 @@ RenderShadowDetail 0 0
|
|||
list TexUnit8orLess
|
||||
RenderDeferredSSAO 0 0
|
||||
|
||||
list TexUnit16orLess
|
||||
RenderTerrainPBRDetail 1 -1
|
||||
|
||||
list AMD
|
||||
RenderDeferredSSAO 1 0
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@
|
|||
#include "pipeline.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include "llsky.h"
|
||||
#include "llvlcomposition.h"
|
||||
#include "llvlmanager.h"
|
||||
#include "llviewercamera.h"
|
||||
#include "lldrawpoolbump.h"
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ public:
|
|||
ANIMATED_CHILD = 0x01000000,
|
||||
ACTIVE_CHILD = 0x02000000,
|
||||
FOR_UNLOAD = 0x04000000, //should be unload from memory
|
||||
MIRROR = 0x08000000, // Used as a mirror, needs a hero probe position to be calculated.
|
||||
} EDrawableFlags;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -54,8 +54,9 @@
|
|||
const F32 DETAIL_SCALE = 1.f/16.f;
|
||||
int DebugDetailMap = 0;
|
||||
|
||||
S32 LLDrawPoolTerrain::sDetailMode = 1;
|
||||
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");
|
||||
|
||||
|
|
@ -66,7 +67,8 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
|
|||
{
|
||||
// Hack!
|
||||
sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale");
|
||||
sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
|
||||
sPBRDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainPBRScale");
|
||||
sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail");
|
||||
mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD);
|
||||
|
||||
//gGL.getTexUnit(0)->bind(mAlphaRampImagep.get());
|
||||
|
|
@ -105,13 +107,7 @@ U32 LLDrawPoolTerrain::getVertexDataMask()
|
|||
|
||||
void LLDrawPoolTerrain::prerender()
|
||||
{
|
||||
sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
|
||||
}
|
||||
|
||||
//static
|
||||
S32 LLDrawPoolTerrain::getDetailMode()
|
||||
{
|
||||
return sDetailMode;
|
||||
sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail");
|
||||
}
|
||||
|
||||
void LLDrawPoolTerrain::boostTerrainDetailTextures()
|
||||
|
|
@ -121,8 +117,38 @@ 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>& fetched_material = compp->mDetailMaterials[i];
|
||||
if (fetched_material)
|
||||
{
|
||||
if (fetched_material->mBaseColorTexture)
|
||||
{
|
||||
fetched_material->mBaseColorTexture->setBoostLevel(level);
|
||||
fetched_material->mBaseColorTexture->addTextureStats(stats);
|
||||
}
|
||||
if (fetched_material->mNormalTexture)
|
||||
{
|
||||
fetched_material->mNormalTexture->setBoostLevel(level);
|
||||
fetched_material->mNormalTexture->addTextureStats(stats);
|
||||
}
|
||||
if (fetched_material->mMetallicRoughnessTexture)
|
||||
{
|
||||
fetched_material->mMetallicRoughnessTexture->setBoostLevel(level);
|
||||
fetched_material->mMetallicRoughnessTexture->addTextureStats(stats);
|
||||
}
|
||||
if (fetched_material->mEmissiveTexture)
|
||||
{
|
||||
fetched_material->mEmissiveTexture->setBoostLevel(level);
|
||||
fetched_material->mEmissiveTexture->addTextureStats(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,10 +156,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)
|
||||
|
|
@ -204,19 +226,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();
|
||||
}
|
||||
|
|
@ -225,9 +236,34 @@ void LLDrawPoolTerrain::drawLoop()
|
|||
|
||||
void LLDrawPoolTerrain::renderFullShader()
|
||||
{
|
||||
const BOOL use_local_materials = gLocalTerrainMaterials.materialsReady(true, false);
|
||||
// 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();
|
||||
|
||||
LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
|
||||
LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
|
||||
LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
|
||||
|
|
@ -322,6 +358,236 @@ 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> (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials;
|
||||
|
||||
constexpr U32 terrain_material_count = LLVLComposition::ASSET_COUNT;
|
||||
#ifdef SHOW_ASSERT
|
||||
constexpr U32 shader_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR;
|
||||
llassert(shader_material_count == terrain_material_count);
|
||||
#endif
|
||||
|
||||
if (local_materials)
|
||||
{
|
||||
// Override region terrain with the global local override terrain
|
||||
fetched_materials = &gLocalTerrainMaterials.mDetailMaterials;
|
||||
}
|
||||
const LLGLTFMaterial* materials[terrain_material_count];
|
||||
for (U32 i = 0; i < terrain_material_count; ++i)
|
||||
{
|
||||
materials[i] = (*fetched_materials)[i].get();
|
||||
if (!materials[i]) { materials[i] = &LLGLTFMaterial::sDefault; }
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
LLViewerTexture* detail_basecolor_texturep = nullptr;
|
||||
LLViewerTexture* detail_normal_texturep = nullptr;
|
||||
LLViewerTexture* detail_metalrough_texturep = nullptr;
|
||||
LLViewerTexture* detail_emissive_texturep = nullptr;
|
||||
|
||||
const LLFetchedGLTFMaterial* fetched_material = (*fetched_materials)[i].get();
|
||||
if (fetched_material)
|
||||
{
|
||||
detail_basecolor_texturep = fetched_material->mBaseColorTexture;
|
||||
detail_normal_texturep = fetched_material->mNormalTexture;
|
||||
detail_metalrough_texturep = fetched_material->mMetallicRoughnessTexture;
|
||||
detail_emissive_texturep = fetched_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();
|
||||
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
{
|
||||
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 >= TERRAIN_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 LLGLTFMaterial* material = materials[i];
|
||||
|
||||
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);
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
{
|
||||
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 >= TERRAIN_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);
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
{
|
||||
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i);
|
||||
}
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
{
|
||||
sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i);
|
||||
}
|
||||
if (sPBRDetailMode >= TERRAIN_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();
|
||||
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_NORMAL)
|
||||
{
|
||||
gGL.getTexUnit(detail_normal[i])->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(detail_normal[i])->disable();
|
||||
gGL.getTexUnit(detail_normal[i])->activate();
|
||||
}
|
||||
|
||||
if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
|
||||
{
|
||||
gGL.getTexUnit(detail_metalrough[i])->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(detail_metalrough[i])->disable();
|
||||
gGL.getTexUnit(detail_metalrough[i])->activate();
|
||||
}
|
||||
|
||||
if (sPBRDetailMode >= TERRAIN_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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -85,17 +85,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);
|
||||
|
|
|
|||
|
|
@ -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() && !gGLManager.mIsAMD;
|
||||
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();
|
||||
|
|
@ -208,11 +215,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
|
|||
LLViewerDynamicTexture *dynamicTexture = *iter;
|
||||
if (dynamicTexture->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;
|
||||
if (dynamicTexture->render())
|
||||
|
|
@ -229,10 +239,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
|
|||
}
|
||||
}
|
||||
|
||||
if (use_fbo)
|
||||
{
|
||||
gPipeline.mBake.flush();
|
||||
}
|
||||
bake_target.flush();
|
||||
|
||||
gGL.flush();
|
||||
|
||||
|
|
|
|||
|
|
@ -1675,8 +1675,6 @@ void LLEnvironment::update(const LLViewerCamera * cam)
|
|||
|
||||
updateSettingsUniforms();
|
||||
|
||||
// *TODO: potential optimization - this block may only need to be
|
||||
// executed some of the time. For example for water shaders only.
|
||||
{
|
||||
LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
|
||||
end_shaders = LLViewerShaderMgr::instance()->endShaders();
|
||||
|
|
@ -1687,6 +1685,10 @@ void LLEnvironment::update(const LLViewerCamera * cam)
|
|||
|| shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
|
||||
{
|
||||
shaders_iter->mUniformsDirty = TRUE;
|
||||
if (shaders_iter->mRiggedVariant)
|
||||
{
|
||||
shaders_iter->mRiggedVariant->mUniformsDirty = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1889,7 +1889,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
F32* normals = (F32*) norm.get();
|
||||
LLVector4a* src = vf.mNormals;
|
||||
LLVector4a* end = src+num_vertices;
|
||||
|
||||
|
||||
while (src < end)
|
||||
{
|
||||
LLVector4a normal;
|
||||
|
|
|
|||
|
|
@ -664,6 +664,10 @@ void LLFeatureManager::applyBaseMasks()
|
|||
{
|
||||
maskFeatures("TexUnit8orLess");
|
||||
}
|
||||
if (gGLManager.mNumTextureImageUnits <= 16)
|
||||
{
|
||||
maskFeatures("TexUnit16orLess");
|
||||
}
|
||||
if (gGLManager.mVRAM > 512)
|
||||
{
|
||||
maskFeatures("VRAMGT512");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ public:
|
|||
virtual ~LLFetchedGLTFMaterial();
|
||||
|
||||
LLFetchedGLTFMaterial& operator=(const LLFetchedGLTFMaterial& rhs);
|
||||
// LLGLTFMaterial::operator== is defined, but LLFetchedGLTFMaterial::operator== is not.
|
||||
bool operator==(const LLGLTFMaterial& rhs) const = delete;
|
||||
|
||||
// If this material is loaded, fire the given function
|
||||
void onMaterialComplete(std::function<void()> material_complete);
|
||||
|
|
@ -49,8 +51,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 +66,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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -605,6 +605,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()
|
||||
{
|
||||
|
|
@ -1307,6 +1327,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)
|
||||
{
|
||||
|
|
@ -1324,7 +1355,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;
|
||||
|
|
@ -1380,12 +1411,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)
|
||||
{
|
||||
|
|
@ -1402,9 +1441,77 @@ BOOL LLPanelRegionTerrainInfo::postBuild()
|
|||
mAskedTextureHeights = false;
|
||||
mConfirmedTextureHeights = false;
|
||||
|
||||
refresh();
|
||||
|
||||
return LLPanelRegionInfo::postBuild();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLPanelRegionTerrainInfo::refresh()
|
||||
{
|
||||
// For simplicity, require restart
|
||||
static BOOL feature_pbr_terrain_enabled = gSavedSettings.getBOOL("RenderTerrainPBREnabled");
|
||||
|
||||
LLTextBox* texture_text = getChild<LLTextBox>("detail_texture_text");
|
||||
if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); }
|
||||
|
||||
LLComboBox* material_type_ctrl = getChild<LLComboBox>("terrain_material_type");
|
||||
if (material_type_ctrl)
|
||||
{
|
||||
material_type_ctrl->setVisible(feature_pbr_terrain_enabled);
|
||||
|
||||
bool has_material_assets = false;
|
||||
|
||||
std::string buffer;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
|
||||
|
||||
if (!feature_pbr_terrain_enabled) { material_type = TerrainMaterialType::TEXTURE; }
|
||||
|
||||
const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL;
|
||||
material_type_ctrl->setEnabled(feature_pbr_terrain_enabled && !(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)
|
||||
{
|
||||
|
|
@ -1421,18 +1528,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1499,17 +1618,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);
|
||||
|
|
|
|||
|
|
@ -75,9 +75,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**);
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ public:
|
|||
static LLPanelRegionEnvironment* getPanelEnvironment();
|
||||
|
||||
// from LLPanel
|
||||
virtual void refresh();
|
||||
void refresh() override;
|
||||
|
||||
void onRegionChanged();
|
||||
void requestRegionInfo();
|
||||
|
|
@ -144,7 +144,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);
|
||||
|
|
@ -184,16 +184,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);
|
||||
|
|
@ -214,13 +213,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);
|
||||
|
|
@ -247,9 +246,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();
|
||||
|
|
@ -257,7 +256,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*);
|
||||
|
|
@ -265,6 +265,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;
|
||||
|
|
@ -303,13 +306,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();
|
||||
|
||||
|
|
@ -319,7 +321,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);
|
||||
|
||||
|
|
@ -339,17 +341,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);
|
||||
|
|
@ -382,7 +383,7 @@ public:
|
|||
} EAssetStatus;
|
||||
|
||||
protected:
|
||||
virtual BOOL sendUpdate();
|
||||
BOOL sendUpdate() override;
|
||||
LLTextBox* mEstateNameText;
|
||||
LLTextBox* mEstateOwnerText;
|
||||
LLTextBox* mLastModifiedText;
|
||||
|
|
@ -401,16 +402,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();
|
||||
|
||||
|
|
@ -435,8 +439,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();
|
||||
|
|
@ -444,7 +448,7 @@ public:
|
|||
void setPendingUpdate(bool pending) { mPendingUpdate = pending; }
|
||||
bool getPendingUpdate() { return mPendingUpdate; }
|
||||
|
||||
virtual bool refreshFromRegion(LLViewerRegion* region);
|
||||
bool refreshFromRegion(LLViewerRegion* region) override;
|
||||
|
||||
private:
|
||||
void onClickAddAllowedAgent();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,566 @@
|
|||
/**
|
||||
* @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 "llviewercontrol.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 (!img && 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)
|
||||
{
|
||||
llassert(!material.isFetching());
|
||||
|
||||
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 + 1;
|
||||
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);
|
||||
const S32 old_local_light_count = gSavedSettings.get<S32>("RenderLocalLightCount");
|
||||
gSavedSettings.set<S32>("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);
|
||||
gSavedSettings.set<S32>("RenderLocalLightCount", old_local_light_count);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLGLTFPreviewTexture::postRender(BOOL success)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
|
||||
|
||||
if (!mShouldRender) { return; }
|
||||
mShouldRender = false;
|
||||
|
||||
LLViewerDynamicTexture::postRender(success);
|
||||
}
|
||||
|
||||
LLPointer<LLViewerTexture> LLGLTFMaterialPreviewMgr::getPreview(LLPointer<LLFetchedGLTFMaterial> &material)
|
||||
{
|
||||
if (!material)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LLCachedControl<bool> sUIPreviewMaterial(gSavedSettings, "UIPreviewMaterial", false);
|
||||
if (!sUIPreviewMaterial)
|
||||
{
|
||||
fetch_texture_for_ui(material->mBaseColorTexture, material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
|
||||
return material->mBaseColorTexture;
|
||||
}
|
||||
|
||||
if (!is_material_loaded_enough_for_ui(*material))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return LLGLTFPreviewTexture::create(material);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,559 @@
|
|||
/**
|
||||
* @file LLHeroProbeManager.cpp
|
||||
* @brief LLHeroProbeManager class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, 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 "llheroprobemanager.h"
|
||||
#include "llreflectionmapmanager.h"
|
||||
#include "llviewercamera.h"
|
||||
#include "llspatialpartition.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llenvironment.h"
|
||||
#include "llstartup.h"
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llviewerjoystick.h"
|
||||
#include "llviewermediafocus.h"
|
||||
|
||||
extern BOOL gCubeSnapshot;
|
||||
extern BOOL gTeleportDisplay;
|
||||
|
||||
// get the next highest power of two of v (or v if v is already a power of two)
|
||||
//defined in llvertexbuffer.cpp
|
||||
extern U32 nhpo2(U32 v);
|
||||
|
||||
static void touch_default_probe(LLReflectionMap* probe)
|
||||
{
|
||||
if (LLViewerCamera::getInstance())
|
||||
{
|
||||
LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
|
||||
origin.mV[2] += 64.f;
|
||||
|
||||
probe->mOrigin.load3(origin.mV);
|
||||
}
|
||||
}
|
||||
|
||||
LLHeroProbeManager::LLHeroProbeManager()
|
||||
{
|
||||
}
|
||||
|
||||
// helper class to seed octree with probes
|
||||
void LLHeroProbeManager::update()
|
||||
{
|
||||
if (!LLPipeline::RenderMirrors || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
llassert(!gCubeSnapshot); // assert a snapshot is not in progress
|
||||
if (LLAppViewer::instance()->logoutRequestSent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
initReflectionMaps();
|
||||
|
||||
if (!mRenderTarget.isComplete())
|
||||
{
|
||||
U32 color_fmt = GL_RGBA16F;
|
||||
U32 targetRes = mProbeResolution; // super sample
|
||||
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
|
||||
}
|
||||
|
||||
if (mMipChain.empty())
|
||||
{
|
||||
U32 res = mProbeResolution;
|
||||
U32 count = log2((F32)res) + 0.5f;
|
||||
|
||||
mMipChain.resize(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
mMipChain[i].allocate(res, res, GL_RGBA16F);
|
||||
res /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
llassert(mProbes[0] == mDefaultProbe);
|
||||
|
||||
LLVector4a probe_pos;
|
||||
LLVector3 camera_pos = LLViewerCamera::instance().mOrigin;
|
||||
F32 near_clip = 0.1f;
|
||||
if (mHeroVOList.size() > 0)
|
||||
{
|
||||
// Find our nearest hero candidate.
|
||||
|
||||
float last_distance = 99999.f;
|
||||
|
||||
for (auto vo : mHeroVOList)
|
||||
{
|
||||
if (vo && !vo->isDead())
|
||||
{
|
||||
if (vo->mDrawable.notNull())
|
||||
{
|
||||
if (vo->mDrawable->mDistanceWRTCamera < last_distance)
|
||||
{
|
||||
mNearestHero = vo;
|
||||
last_distance = vo->mDrawable->mDistanceWRTCamera;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Valid drawables only please. Unregister this one.
|
||||
unregisterViewerObject(vo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unregisterViewerObject(vo);
|
||||
}
|
||||
}
|
||||
|
||||
if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull())
|
||||
{
|
||||
LLVector3 hero_pos = mNearestHero->getPositionAgent();
|
||||
LLVector3 face_normal = LLVector3(0, 0, 1);
|
||||
|
||||
face_normal *= mNearestHero->mDrawable->getXform()->getWorldRotation();
|
||||
face_normal.normalize();
|
||||
|
||||
LLVector3 offset = camera_pos - hero_pos;
|
||||
LLVector3 project = face_normal * (offset * face_normal);
|
||||
LLVector3 reject = offset - project;
|
||||
LLVector3 point = (reject - project) + hero_pos;
|
||||
|
||||
mCurrentClipPlane.setVec(hero_pos, face_normal);
|
||||
mMirrorPosition = hero_pos;
|
||||
mMirrorNormal = face_normal;
|
||||
|
||||
|
||||
probe_pos.load3(point.mV);
|
||||
}
|
||||
else
|
||||
{
|
||||
mNearestHero = nullptr;
|
||||
}
|
||||
|
||||
mHeroProbeStrength = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
probe_pos.load3(camera_pos.mV);
|
||||
}
|
||||
|
||||
|
||||
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1);
|
||||
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3);
|
||||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime");
|
||||
// Probe 0 is always our mirror probe.
|
||||
mProbes[0]->mOrigin = probe_pos;
|
||||
|
||||
bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass();
|
||||
|
||||
gPipeline.mReflectionMapManager.mRadiancePass = true;
|
||||
mRenderingMirror = true;
|
||||
for (U32 j = 0; j < mProbes.size(); j++)
|
||||
{
|
||||
for (U32 i = 0; i < 6; ++i)
|
||||
{
|
||||
updateProbeFace(mProbes[j], i, near_clip);
|
||||
}
|
||||
}
|
||||
mRenderingMirror = false;
|
||||
|
||||
gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the reflection map update render passes.
|
||||
// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated
|
||||
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
|
||||
// a simple mip chain (not convolution filter).
|
||||
// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe
|
||||
// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
|
||||
// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe.
|
||||
// In effect this simulates single-bounce lighting.
|
||||
void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip)
|
||||
{
|
||||
// hacky hot-swap of camera specific render targets
|
||||
gPipeline.mRT = &gPipeline.mHeroProbeRT;
|
||||
|
||||
probe->update(mRenderTarget.getWidth(), face, true, near_clip);
|
||||
|
||||
gPipeline.mRT = &gPipeline.mMainRT;
|
||||
|
||||
S32 sourceIdx = mReflectionProbeCount;
|
||||
|
||||
|
||||
// Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes.
|
||||
sourceIdx += 1;
|
||||
|
||||
gGL.setColorMask(true, true);
|
||||
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
|
||||
LLGLDisable cull(GL_CULL_FACE);
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
|
||||
// downsample to placeholder map
|
||||
{
|
||||
gGL.matrixMode(gGL.MM_MODELVIEW);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadIdentity();
|
||||
|
||||
gGL.matrixMode(gGL.MM_PROJECTION);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadIdentity();
|
||||
|
||||
gGL.flush();
|
||||
U32 res = mProbeResolution * 2;
|
||||
|
||||
static LLStaticHashedString resScale("resScale");
|
||||
static LLStaticHashedString direction("direction");
|
||||
static LLStaticHashedString znear("znear");
|
||||
static LLStaticHashedString zfar("zfar");
|
||||
|
||||
LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen;
|
||||
LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen;
|
||||
|
||||
// perform a gaussian blur on the super sampled render before downsampling
|
||||
{
|
||||
gGaussianProgram.bind();
|
||||
gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2));
|
||||
S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
|
||||
|
||||
// horizontal
|
||||
gGaussianProgram.uniform2f(direction, 1.f, 0.f);
|
||||
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
|
||||
mRenderTarget.bindTarget();
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
mRenderTarget.flush();
|
||||
|
||||
// vertical
|
||||
gGaussianProgram.uniform2f(direction, 0.f, 1.f);
|
||||
gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);
|
||||
screen_rt->bindTarget();
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
screen_rt->flush();
|
||||
gGaussianProgram.unbind();
|
||||
}
|
||||
|
||||
S32 mips = log2((F32)mProbeResolution) + 0.5f;
|
||||
|
||||
gReflectionMipProgram.bind();
|
||||
S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
|
||||
S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE);
|
||||
|
||||
for (int i = 0; i < mMipChain.size(); ++i)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("probe mip");
|
||||
mMipChain[i].bindTarget();
|
||||
if (i == 0)
|
||||
{
|
||||
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
|
||||
}
|
||||
|
||||
gGL.getTexUnit(depthChannel)->bind(depth_rt, true);
|
||||
|
||||
gReflectionMipProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2));
|
||||
gReflectionMipProgram.uniform1f(znear, probe->getNearClip());
|
||||
gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP);
|
||||
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
|
||||
res /= 2;
|
||||
|
||||
S32 mip = i - (mMipChain.size() - mips);
|
||||
|
||||
if (mip >= 0)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("probe mip copy");
|
||||
mTexture->bind(0);
|
||||
|
||||
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res);
|
||||
|
||||
mTexture->unbind();
|
||||
}
|
||||
mMipChain[i].flush();
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(gGL.MM_MODELVIEW);
|
||||
gGL.popMatrix();
|
||||
|
||||
gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gReflectionMipProgram.unbind();
|
||||
}
|
||||
|
||||
if (face == 5)
|
||||
{
|
||||
mMipChain[0].bindTarget();
|
||||
static LLStaticHashedString sSourceIdx("sourceIdx");
|
||||
|
||||
{
|
||||
//generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
|
||||
gHeroRadianceGenProgram.bind();
|
||||
mVertexBuffer->setBuffer();
|
||||
|
||||
S32 channel = gHeroRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
|
||||
mTexture->bind(channel);
|
||||
gHeroRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
|
||||
gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
|
||||
gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength);
|
||||
|
||||
U32 res = mMipChain[0].getWidth();
|
||||
|
||||
for (int i = 0; i < mMipChain.size(); ++i)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("probe radiance gen");
|
||||
static LLStaticHashedString sMipLevel("mipLevel");
|
||||
static LLStaticHashedString sRoughness("roughness");
|
||||
static LLStaticHashedString sWidth("u_width");
|
||||
static LLStaticHashedString sStrength("probe_strength");
|
||||
|
||||
gHeroRadianceGenProgram.uniform1f(sRoughness, (F32) i / (F32) (mMipChain.size() - 1));
|
||||
gHeroRadianceGenProgram.uniform1f(sMipLevel, i);
|
||||
gHeroRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
|
||||
gHeroRadianceGenProgram.uniform1f(sStrength, 1);
|
||||
|
||||
for (int cf = 0; cf < 6; ++cf)
|
||||
{ // for each cube face
|
||||
LLCoordFrame frame;
|
||||
frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
|
||||
|
||||
F32 mat[16];
|
||||
frame.getOpenGLRotation(mat);
|
||||
gGL.loadMatrix(mat);
|
||||
|
||||
mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
|
||||
}
|
||||
|
||||
if (i != mMipChain.size() - 1)
|
||||
{
|
||||
res /= 2;
|
||||
glViewport(0, 0, res, res);
|
||||
}
|
||||
}
|
||||
|
||||
gHeroRadianceGenProgram.unbind();
|
||||
}
|
||||
|
||||
mMipChain[0].flush();
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::updateUniforms()
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
|
||||
struct HeroProbeData
|
||||
{
|
||||
LLVector4 heroPosition[1];
|
||||
GLint heroProbeCount = 1;
|
||||
};
|
||||
|
||||
HeroProbeData hpd;
|
||||
|
||||
LLMatrix4a modelview;
|
||||
modelview.loadu(gGLModelView);
|
||||
LLVector4a oa; // scratch space for transformed origin
|
||||
oa.set(0, 0, 0, 0);
|
||||
hpd.heroProbeCount = 1;
|
||||
modelview.affineTransform(mProbes[0]->mOrigin, oa);
|
||||
hpd.heroPosition[0].set(oa.getF32ptr());
|
||||
|
||||
//copy rpd into uniform buffer object
|
||||
if (mUBO == 0)
|
||||
{
|
||||
glGenBuffers(1, &mUBO);
|
||||
}
|
||||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mUBO);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::setUniforms()
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mUBO == 0)
|
||||
{
|
||||
updateUniforms();
|
||||
}
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::renderDebug()
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
renderReflectionProbe(probe);
|
||||
}
|
||||
|
||||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::initReflectionMaps()
|
||||
{
|
||||
U32 count = LL_MAX_HERO_PROBE_COUNT;
|
||||
|
||||
if (mTexture.isNull() || mReflectionProbeCount != count || mReset)
|
||||
{
|
||||
mReset = false;
|
||||
mReflectionProbeCount = count;
|
||||
mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution");
|
||||
mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1
|
||||
|
||||
mTexture = new LLCubeMapArray();
|
||||
|
||||
// store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source)
|
||||
mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2);
|
||||
|
||||
if (mDefaultProbe.isNull())
|
||||
{
|
||||
llassert(mProbes.empty()); // default probe MUST be the first probe created
|
||||
mDefaultProbe = new LLReflectionMap();
|
||||
mProbes.push_back(mDefaultProbe);
|
||||
}
|
||||
|
||||
llassert(mProbes[0] == mDefaultProbe);
|
||||
|
||||
// For hero probes, we treat this as the main mirror probe.
|
||||
|
||||
mDefaultProbe->mCubeIndex = 0;
|
||||
mDefaultProbe->mCubeArray = mTexture;
|
||||
mDefaultProbe->mDistance = gSavedSettings.getF32("RenderHeroProbeDistance");
|
||||
mDefaultProbe->mRadius = 4096.f;
|
||||
mDefaultProbe->mProbeIndex = 0;
|
||||
touch_default_probe(mDefaultProbe);
|
||||
|
||||
mProbes.push_back(mDefaultProbe);
|
||||
}
|
||||
|
||||
if (mVertexBuffer.isNull())
|
||||
{
|
||||
U32 mask = LLVertexBuffer::MAP_VERTEX;
|
||||
LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask);
|
||||
buff->allocateBuffer(4, 0);
|
||||
|
||||
LLStrider<LLVector3> v;
|
||||
|
||||
buff->getVertexStrider(v);
|
||||
|
||||
v[0] = LLVector3(-1, -1, -1);
|
||||
v[1] = LLVector3(1, -1, -1);
|
||||
v[2] = LLVector3(-1, 1, -1);
|
||||
v[3] = LLVector3(1, 1, -1);
|
||||
|
||||
buff->unmapBuffer();
|
||||
|
||||
mVertexBuffer = buff;
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::cleanup()
|
||||
{
|
||||
mVertexBuffer = nullptr;
|
||||
mRenderTarget.release();
|
||||
mHeroRenderTarget.release();
|
||||
|
||||
mMipChain.clear();
|
||||
|
||||
mTexture = nullptr;
|
||||
|
||||
mProbes.clear();
|
||||
|
||||
mReflectionMaps.clear();
|
||||
|
||||
mDefaultProbe = nullptr;
|
||||
mUpdatingProbe = nullptr;
|
||||
|
||||
glDeleteBuffers(1, &mUBO);
|
||||
mUBO = 0;
|
||||
|
||||
mHeroVOList.clear();
|
||||
mNearestHero = nullptr;
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::doOcclusion()
|
||||
{
|
||||
LLVector4a eye;
|
||||
eye.load3(LLViewerCamera::instance().getOrigin().mV);
|
||||
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
if (probe != nullptr && probe != mDefaultProbe)
|
||||
{
|
||||
probe->doOcclusion(eye);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep)
|
||||
{
|
||||
llassert(drawablep != nullptr);
|
||||
|
||||
if (mHeroVOList.find(drawablep) == mHeroVOList.end())
|
||||
{
|
||||
// Probe isn't in our list for consideration. Add it.
|
||||
mHeroVOList.insert(drawablep);
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep)
|
||||
{
|
||||
if (mHeroVOList.find(drawablep) != mHeroVOList.end())
|
||||
{
|
||||
mHeroVOList.erase(drawablep);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* @file llheroprobemanager.h
|
||||
* @brief LLHeroProbeManager class declaration
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, 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 "llreflectionmap.h"
|
||||
#include "llrendertarget.h"
|
||||
#include "llcubemaparray.h"
|
||||
#include "llcubemap.h"
|
||||
#include "lldrawable.h"
|
||||
|
||||
class LLSpatialGroup;
|
||||
class LLViewerObject;
|
||||
|
||||
// number of reflection probes to keep in vram
|
||||
#define LL_MAX_HERO_PROBE_COUNT 2
|
||||
|
||||
class alignas(16) LLHeroProbeManager
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
enum class DetailLevel
|
||||
{
|
||||
STATIC_ONLY = 0,
|
||||
STATIC_AND_DYNAMIC,
|
||||
REALTIME = 2
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
LLHeroProbeManager();
|
||||
|
||||
// release any GL state
|
||||
void cleanup();
|
||||
|
||||
// maintain reflection probes
|
||||
void update();
|
||||
|
||||
// debug display, called from llspatialpartition if reflection
|
||||
// probe debug display is active
|
||||
void renderDebug();
|
||||
|
||||
// call once at startup to allocate cubemap arrays
|
||||
void initReflectionMaps();
|
||||
|
||||
// perform occlusion culling on all active reflection probes
|
||||
void doOcclusion();
|
||||
|
||||
void registerViewerObject(LLVOVolume *drawablep);
|
||||
void unregisterViewerObject(LLVOVolume* drawablep);
|
||||
|
||||
bool isMirrorPass() const { return mRenderingMirror; }
|
||||
|
||||
LLVector3 mMirrorPosition;
|
||||
LLVector3 mMirrorNormal;
|
||||
|
||||
private:
|
||||
friend class LLPipeline;
|
||||
|
||||
// update UBO used for rendering (call only once per render pipe flush)
|
||||
void updateUniforms();
|
||||
|
||||
// bind UBO used for rendering
|
||||
void setUniforms();
|
||||
|
||||
// render target for cube snapshots
|
||||
// used to generate mipmaps without doing a copy-to-texture
|
||||
LLRenderTarget mRenderTarget;
|
||||
|
||||
LLRenderTarget mHeroRenderTarget;
|
||||
|
||||
std::vector<LLRenderTarget> mMipChain;
|
||||
|
||||
// storage for reflection probe radiance maps (plus two scratch space cubemaps)
|
||||
LLPointer<LLCubeMapArray> mTexture;
|
||||
|
||||
// vertex buffer for pushing verts to filter shaders
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
|
||||
LLPlane mCurrentClipPlane;
|
||||
|
||||
|
||||
// update the specified face of the specified probe
|
||||
void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip);
|
||||
|
||||
// list of active reflection maps
|
||||
std::vector<LLPointer<LLReflectionMap> > mProbes;
|
||||
|
||||
// handle to UBO
|
||||
U32 mUBO = 0;
|
||||
|
||||
// list of maps being used for rendering
|
||||
std::vector<LLReflectionMap*> mReflectionMaps;
|
||||
|
||||
LLReflectionMap* mUpdatingProbe = nullptr;
|
||||
|
||||
LLPointer<LLReflectionMap> mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0)
|
||||
|
||||
// number of reflection probes to use for rendering
|
||||
U32 mReflectionProbeCount;
|
||||
|
||||
// resolution of reflection probes
|
||||
U32 mProbeResolution = 1024;
|
||||
|
||||
// maximum LoD of reflection probes (mip levels - 1)
|
||||
F32 mMaxProbeLOD = 6.f;
|
||||
|
||||
F32 mHeroProbeStrength = 1.f;
|
||||
bool mIsInTransition = false;
|
||||
|
||||
// if true, reset all probe render state on the next update (for teleports and sky changes)
|
||||
bool mReset = false;
|
||||
|
||||
bool mRenderingMirror = false;
|
||||
|
||||
std::set<LLPointer<LLVOVolume>> mHeroVOList;
|
||||
LLPointer<LLVOVolume> mNearestHero;
|
||||
};
|
||||
|
||||
|
|
@ -1870,7 +1870,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1793,6 +1793,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
|
|||
getChild<LLUICtrl>("shinyOffsetV")->setValue(offset_y);
|
||||
getChild<LLUICtrl>("glossiness")->setValue(material->getSpecularLightExponent());
|
||||
getChild<LLUICtrl>("environment")->setValue(material->getEnvironmentIntensity());
|
||||
getChild<LLUICtrl>("mirror")->setValue(material->getEnvironmentIntensity());
|
||||
|
||||
updateShinyControls(!material->getSpecularID().isNull(), true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ protected:
|
|||
void sendTexGen(); // applies and sends bump map
|
||||
void sendShiny(U32 shininess); // applies and sends shininess
|
||||
void sendFullbright(); // applies and sends full bright
|
||||
|
||||
void sendGlow();
|
||||
void alignTestureLayer();
|
||||
|
||||
|
|
@ -234,7 +235,7 @@ protected:
|
|||
static void onCommitShiny( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitFullbright( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
|
||||
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
|
||||
static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo);
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ BOOL LLPanelVolume::postBuild()
|
|||
// REFLECTION PROBE Parameters
|
||||
{
|
||||
childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this);
|
||||
childSetCommitCallback("Probe Dynamic", onCommitProbe, this);
|
||||
childSetCommitCallback("Probe Update Type", onCommitProbe, this);
|
||||
childSetCommitCallback("Probe Volume Type", onCommitProbe, this);
|
||||
childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
|
||||
childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
|
||||
|
|
@ -304,7 +304,7 @@ void LLPanelVolume::getState( )
|
|||
getChildView("select_single")->setVisible(true);
|
||||
getChildView("select_single")->setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
// Light properties
|
||||
BOOL is_light = volobjp && volobjp->getIsLight();
|
||||
getChild<LLUICtrl>("Light Checkbox Ctrl")->setValue(is_light);
|
||||
|
|
@ -392,17 +392,25 @@ void LLPanelVolume::getState( )
|
|||
|
||||
bool probe_enabled = is_probe && editable && single_volume;
|
||||
|
||||
bool mirrors_enabled = LLPipeline::RenderMirrors;
|
||||
|
||||
getChildView("Probe Update Type")->setVisible(mirrors_enabled);
|
||||
getChildView("Probe Update Label")->setVisible(mirrors_enabled);
|
||||
getChildView("Probe Dynamic")->setVisible(!mirrors_enabled);
|
||||
|
||||
getChildView("Probe Dynamic")->setEnabled(probe_enabled);
|
||||
getChildView("Probe Update Type")->setEnabled(probe_enabled);
|
||||
getChildView("Probe Volume Type")->setEnabled(probe_enabled);
|
||||
getChildView("Probe Ambiance")->setEnabled(probe_enabled);
|
||||
getChildView("Probe Near Clip")->setEnabled(probe_enabled);
|
||||
getChildView("Probe Update Label")->setEnabled(probe_enabled);
|
||||
|
||||
if (!probe_enabled)
|
||||
{
|
||||
getChild<LLComboBox>("Probe Volume Type", true)->clear();
|
||||
getChild<LLSpinCtrl>("Probe Ambiance", true)->clear();
|
||||
getChild<LLSpinCtrl>("Probe Near Clip", true)->clear();
|
||||
getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->clear();
|
||||
getChild<LLComboBox>("Probe Update Type", true)->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -416,10 +424,28 @@ void LLPanelVolume::getState( )
|
|||
volume_type = "Sphere";
|
||||
}
|
||||
|
||||
std::string update_type;
|
||||
if (volobjp->getReflectionProbeIsDynamic())
|
||||
{
|
||||
update_type = "Dynamic";
|
||||
}
|
||||
else if (volobjp->getReflectionProbeIsMirror())
|
||||
{
|
||||
update_type = "Mirror";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
update_type = "Static";
|
||||
}
|
||||
|
||||
getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror");
|
||||
getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror");
|
||||
|
||||
getChild<LLComboBox>("Probe Volume Type", true)->setValue(volume_type);
|
||||
getChild<LLSpinCtrl>("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
|
||||
getChild<LLSpinCtrl>("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
|
||||
getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic());
|
||||
getChild<LLComboBox>("Probe Update Type", true)->setValue(update_type);
|
||||
}
|
||||
|
||||
// Animated Mesh
|
||||
|
|
@ -706,7 +732,7 @@ void LLPanelVolume::clearCtrls()
|
|||
|
||||
getChildView("Reflection Probe")->setEnabled(false);;
|
||||
getChildView("Probe Volume Type")->setEnabled(false);
|
||||
getChildView("Probe Dynamic")->setEnabled(false);
|
||||
getChildView("Probe Update Type")->setEnabled(false);
|
||||
getChildView("Probe Ambiance")->setEnabled(false);
|
||||
getChildView("Probe Near Clip")->setEnabled(false);
|
||||
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);
|
||||
|
|
@ -1399,7 +1425,14 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
|
|||
|
||||
volobjp->setReflectionProbeAmbiance((F32)self->getChild<LLUICtrl>("Probe Ambiance")->getValue().asReal());
|
||||
volobjp->setReflectionProbeNearClip((F32)self->getChild<LLUICtrl>("Probe Near Clip")->getValue().asReal());
|
||||
volobjp->setReflectionProbeIsDynamic(self->getChild<LLUICtrl>("Probe Dynamic")->getValue().asBoolean());
|
||||
|
||||
std::string update_type = self->getChild<LLUICtrl>("Probe Update Type")->getValue().asString();
|
||||
|
||||
volobjp->setReflectionProbeIsDynamic(update_type == "Dynamic");
|
||||
volobjp->setReflectionProbeIsMirror(update_type == "Mirror");
|
||||
|
||||
self->getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror");
|
||||
self->getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror");
|
||||
|
||||
std::string shape_type = self->getChild<LLUICtrl>("Probe Volume Type")->getValue().asString();
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
void refresh();
|
||||
|
||||
void sendIsLight();
|
||||
|
||||
|
||||
// when an object is becoming a refleciton probe, present a dialog asking for confirmation
|
||||
// otherwise, send the reflection probe update immediately
|
||||
void sendIsReflectionProbe();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap()
|
|||
}
|
||||
}
|
||||
|
||||
void LLReflectionMap::update(U32 resolution, U32 face)
|
||||
void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
mLastUpdateTime = gFrameTimeSeconds;
|
||||
|
|
@ -63,7 +63,10 @@ void LLReflectionMap::update(U32 resolution, U32 face)
|
|||
{
|
||||
resolution /= 2;
|
||||
}
|
||||
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic());
|
||||
|
||||
F32 clip = (near_clip > 0) ? near_clip : getNearClip();
|
||||
|
||||
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane);
|
||||
}
|
||||
|
||||
void LLReflectionMap::autoAdjustOrigin()
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@ class alignas(16) LLReflectionMap : public LLRefCount
|
|||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
|
||||
enum class ProbeType
|
||||
{
|
||||
ALL = 0,
|
||||
RADIANCE,
|
||||
IRRADIANCE,
|
||||
REFLECTION
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
LLReflectionMap();
|
||||
|
||||
|
|
@ -43,7 +52,7 @@ public:
|
|||
|
||||
// update this environment map
|
||||
// resolution - size of cube map to generate
|
||||
void update(U32 resolution, U32 face);
|
||||
void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f, bool useClipPlane = false, LLPlane clipPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1)));
|
||||
|
||||
// for volume partition probes, try to place this probe in the best spot
|
||||
void autoAdjustOrigin();
|
||||
|
|
@ -127,5 +136,7 @@ public:
|
|||
GLuint mOcclusionQuery = 0;
|
||||
bool mOccluded = false;
|
||||
U32 mOcclusionPendingFrames = 0;
|
||||
|
||||
ProbeType mType;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llreflectionmapmanager.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "llviewercamera.h"
|
||||
#include "llspatialpartition.h"
|
||||
#include "llviewerregion.h"
|
||||
|
|
@ -306,8 +309,8 @@ void LLReflectionMapManager::update()
|
|||
}
|
||||
}
|
||||
|
||||
if (realtime &&
|
||||
closestDynamic == nullptr &&
|
||||
if (realtime &&
|
||||
closestDynamic == nullptr &&
|
||||
probe->mCubeIndex != -1 &&
|
||||
probe->getIsDynamic())
|
||||
{
|
||||
|
|
@ -322,7 +325,7 @@ void LLReflectionMapManager::update()
|
|||
// should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames
|
||||
closestDynamic->autoAdjustOrigin();
|
||||
|
||||
// store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set
|
||||
// store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set
|
||||
// lighting values etc
|
||||
bool radiance_pass = isRadiancePass();
|
||||
mRadiancePass = mRealtimeRadiancePass;
|
||||
|
|
@ -573,7 +576,7 @@ void LLReflectionMapManager::doProbeUpdate()
|
|||
|
||||
// Do the reflection map update render passes.
|
||||
// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated
|
||||
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
|
||||
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
|
||||
// a simple mip chain (not convolution filter).
|
||||
// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe
|
||||
// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
|
||||
|
|
@ -734,6 +737,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
|
|||
mTexture->bind(channel);
|
||||
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
|
||||
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
|
||||
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f);
|
||||
|
||||
U32 res = mMipChain[0].getWidth();
|
||||
|
||||
|
|
@ -898,14 +902,14 @@ void LLReflectionMapManager::updateUniforms()
|
|||
// see class3/deferred/reflectionProbeF.glsl
|
||||
struct ReflectionProbeData
|
||||
{
|
||||
// for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of
|
||||
// for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of
|
||||
// the box probe
|
||||
LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
// for sphere probes, origin (xyz) and radius (w) of refmaps in clip space
|
||||
LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
// extra parameters
|
||||
// extra parameters
|
||||
// x - irradiance scale
|
||||
// y - radiance scale
|
||||
// z - fade in
|
||||
|
|
@ -917,14 +921,14 @@ void LLReflectionMapManager::updateUniforms()
|
|||
// [i][1] - index into "refNeighbor" for probes that intersect this probe
|
||||
// [i][2] - number of probes that intersect this probe, or -1 for no neighbors
|
||||
// [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes)
|
||||
GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];
|
||||
GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];
|
||||
|
||||
// list of neighbor indices
|
||||
GLint refNeighbor[4096];
|
||||
GLint refNeighbor[4096];
|
||||
|
||||
GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
|
||||
// numbrer of active refmaps
|
||||
GLint refmapCount;
|
||||
GLint refmapCount;
|
||||
};
|
||||
|
||||
mReflectionMaps.resize(mReflectionProbeCount);
|
||||
|
|
@ -1152,7 +1156,7 @@ void LLReflectionMapManager::setUniforms()
|
|||
}
|
||||
|
||||
if (mUBO == 0)
|
||||
{
|
||||
{
|
||||
updateUniforms();
|
||||
}
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
|
||||
|
|
@ -1343,8 +1347,8 @@ void LLReflectionMapManager::initReflectionMaps()
|
|||
}
|
||||
}
|
||||
|
||||
void LLReflectionMapManager::cleanup()
|
||||
{
|
||||
void LLReflectionMapManager::cleanup()
|
||||
{
|
||||
mVertexBuffer = nullptr;
|
||||
mRenderTarget.release();
|
||||
|
||||
|
|
@ -1383,3 +1387,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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,21 +43,23 @@ class LLViewerObject;
|
|||
// reflection probe mininum scale
|
||||
#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f;
|
||||
|
||||
void renderReflectionProbe(LLReflectionMap* probe);
|
||||
|
||||
class alignas(16) LLReflectionMapManager
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
enum class DetailLevel
|
||||
enum class DetailLevel
|
||||
{
|
||||
STATIC_ONLY = 0,
|
||||
STATIC_AND_DYNAMIC,
|
||||
REALTIME = 2
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
// allocate an environment map of the given resolution
|
||||
LLReflectionMapManager();
|
||||
|
||||
// release any GL state
|
||||
// release any GL state
|
||||
void cleanup();
|
||||
|
||||
// maintain reflection probes
|
||||
|
|
@ -106,8 +108,14 @@ 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;
|
||||
friend class LLHeroProbeManager;
|
||||
|
||||
// initialize mCubeFree array to default values
|
||||
void initCubeFree();
|
||||
|
|
@ -119,7 +127,7 @@ private:
|
|||
// returns -1 if allocation failed
|
||||
S32 allocateCubeIndex();
|
||||
|
||||
// update the neighbors of the given probe
|
||||
// update the neighbors of the given probe
|
||||
void updateNeighbors(LLReflectionMap* probe);
|
||||
|
||||
// update UBO used for rendering (call only once per render pipe flush)
|
||||
|
|
|
|||
|
|
@ -718,11 +718,11 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
|
|||
LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
|
||||
|
||||
// TODO -- make these getters return vec3s
|
||||
LLVector3 sunDiffuse = LLVector3(psky->getSunlightColor().mV);
|
||||
LLVector3 moonDiffuse = LLVector3(psky->getMoonlightColor().mV);
|
||||
LLVector3 sun_light_color = LLVector3(psky->getSunlightColor().mV);
|
||||
LLVector3 moon_light_color = LLVector3(psky->getMoonlightColor().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse);
|
||||
shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse);
|
||||
shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_light_color);
|
||||
shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, moon_light_color);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::CLOUD_COLOR, LLVector3(psky->getCloudColor().mV));
|
||||
|
||||
|
|
@ -765,9 +765,9 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
|
|||
shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, auto_adjust_hdr_scale);
|
||||
LLColor3 blue_horizon = getBlueHorizon() * auto_adjust_blue_horizon_scale;
|
||||
LLColor3 blue_density = getBlueDensity() * auto_adjust_blue_density_scale;
|
||||
LLColor3 sun_diffuse = getSunDiffuse() * auto_adjust_sun_color_scale;
|
||||
sun_light_color = sun_light_color * auto_adjust_sun_color_scale;
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_diffuse.mV);
|
||||
shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_light_color.mV);
|
||||
shader->uniform3fv(LLShaderMgr::BLUE_DENSITY, blue_density.mV);
|
||||
shader->uniform3fv(LLShaderMgr::BLUE_HORIZON, blue_horizon.mV);
|
||||
|
||||
|
|
@ -1009,6 +1009,7 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force)
|
|||
|
||||
glh::matrix4f mat(modelView);
|
||||
glh::matrix4f invtrans = mat.inverse().transpose();
|
||||
invtrans.m[3] = invtrans.m[7] = invtrans.m[11] = 0.f;
|
||||
glh::vec3f enorm;
|
||||
glh::vec3f ep;
|
||||
invtrans.mult_matrix_vec(norm, enorm);
|
||||
|
|
@ -1017,12 +1018,29 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force)
|
|||
|
||||
LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
|
||||
|
||||
norm = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorNormal.mV);
|
||||
p = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorPosition.mV);
|
||||
invtrans.mult_matrix_vec(norm, enorm);
|
||||
enorm.normalize();
|
||||
mat.mult_matrix_vec(p, ep);
|
||||
|
||||
LLVector4 mirrorPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
|
||||
|
||||
LLDrawPoolAlpha::sWaterPlane = waterPlane;
|
||||
|
||||
shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, waterPlane.mV);
|
||||
|
||||
shader->uniform4fv(LLShaderMgr::CLIP_PLANE, mirrorPlane.mV);
|
||||
LLVector4 light_direction = env.getClampedLightNorm();
|
||||
|
||||
if (gPipeline.mHeroProbeManager.isMirrorPass())
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0);
|
||||
}
|
||||
|
||||
F32 waterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP);
|
||||
|
||||
shader->uniform1f(LLShaderMgr::WATER_FOGKS, waterFogKS);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "pipeline.h"
|
||||
#include "llmeshrepository.h"
|
||||
#include "llrender.h"
|
||||
#include "lldrawpool.h"
|
||||
#include "lloctree.h"
|
||||
#include "llphysicsshapebuilderutil.h"
|
||||
#include "llvoavatar.h"
|
||||
|
|
@ -2000,7 +2001,11 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
|
|||
drawBoxOutline(pos,size);
|
||||
}
|
||||
}
|
||||
|
||||
// *TODO: LLDrawables which are not part of LLVOVolumes fall into a different
|
||||
// code path which uses a shader - it was tested to be faster than mapping a
|
||||
// vertex buffer in the terrain case. Consider using it for LLVOVolumes as well
|
||||
// to simplify and speed up this debug code. Alternatively, a compute shader is
|
||||
// likely faster. -Cosmic,2023-09-28
|
||||
void renderNormals(LLDrawable *drawablep)
|
||||
{
|
||||
if (!drawablep->isVisible())
|
||||
|
|
@ -2008,11 +2013,13 @@ void renderNormals(LLDrawable *drawablep)
|
|||
|
||||
LLVertexBuffer::unbind();
|
||||
|
||||
LLViewerObject* obj = drawablep->getVObj();
|
||||
LLVOVolume *vol = drawablep->getVOVolume();
|
||||
|
||||
if (vol)
|
||||
if (obj)
|
||||
{
|
||||
LLVolume *volume = vol->getVolume();
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
LLGLDepthTest gl_depth(GL_TRUE, GL_FALSE);
|
||||
|
||||
// Drawable's normals & tangents are stored in model space, i.e. before any scaling is applied.
|
||||
//
|
||||
|
|
@ -2021,68 +2028,136 @@ void renderNormals(LLDrawable *drawablep)
|
|||
// transform. We get that effect here by pre-applying the inverse scale (twice, because
|
||||
// one forward scale will be re-applied via the MVP in the vertex shader)
|
||||
|
||||
LLVector3 scale_v3 = vol->getScale();
|
||||
float scale_len = scale_v3.length();
|
||||
LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]);
|
||||
obj_scale.normalize3();
|
||||
LLVector4a inv_scale;
|
||||
float scale_len;
|
||||
if (vol)
|
||||
{
|
||||
LLVector3 scale_v3 = vol->getScale();
|
||||
LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]);
|
||||
obj_scale.normalize3();
|
||||
|
||||
// Create inverse-scale vector for normals
|
||||
inv_scale.set(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ], 0.0);
|
||||
inv_scale.mul(inv_scale); // Squared, to apply inverse scale twice
|
||||
|
||||
inv_scale.normalize3fast();
|
||||
scale_len = scale_v3.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
inv_scale.set(1.0, 1.0, 1.0, 0.0);
|
||||
scale_len = 1.0;
|
||||
}
|
||||
|
||||
gGL.pushMatrix();
|
||||
if (vol)
|
||||
{
|
||||
gGL.multMatrix((F32 *) vol->getRelativeXform().mMatrix);
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
// Normals &tangent line segments get scaled along with the object. Divide by scale length
|
||||
// to keep the as-viewed lengths (relatively) constant with the debug setting length
|
||||
float draw_length = gSavedSettings.getF32("RenderDebugNormalScale") / scale_len;
|
||||
|
||||
// Create inverse-scale vector for normals
|
||||
LLVector4a inv_scale(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ]);
|
||||
inv_scale.mul(inv_scale); // Squared, to apply inverse scale twice
|
||||
inv_scale.normalize3fast();
|
||||
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix((F32 *) vol->getRelativeXform().mMatrix);
|
||||
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
|
||||
std::vector<LLVolumeFace>* faces = nullptr;
|
||||
std::vector<LLFace*>* drawable_faces = nullptr;
|
||||
if (vol)
|
||||
{
|
||||
const LLVolumeFace &face = volume->getVolumeFace(i);
|
||||
|
||||
gGL.flush();
|
||||
gGL.diffuseColor4f(1, 1, 0, 1);
|
||||
gGL.begin(LLRender::LINES);
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
LLVector4a n, p;
|
||||
|
||||
n.setMul(face.mNormals[j], 1.0);
|
||||
n.mul(inv_scale); // Pre-scale normal, so it's left with an inverse-transpose xform after MVP
|
||||
n.normalize3fast();
|
||||
n.mul(draw_length);
|
||||
p.setAdd(face.mPositions[j], n);
|
||||
|
||||
gGL.vertex3fv(face.mPositions[j].getF32ptr());
|
||||
gGL.vertex3fv(p.getF32ptr());
|
||||
}
|
||||
gGL.end();
|
||||
|
||||
// Tangents are simple vectors and do not require reorientation via pre-scaling
|
||||
if (face.mTangents)
|
||||
{
|
||||
gGL.flush();
|
||||
gGL.diffuseColor4f(0, 1, 1, 1);
|
||||
gGL.begin(LLRender::LINES);
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
LLVector4a t, p;
|
||||
|
||||
t.setMul(face.mTangents[j], 1.0f);
|
||||
t.normalize3fast();
|
||||
t.mul(draw_length);
|
||||
p.setAdd(face.mPositions[j], t);
|
||||
|
||||
gGL.vertex3fv(face.mPositions[j].getF32ptr());
|
||||
gGL.vertex3fv(p.getF32ptr());
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
LLVolume* volume = vol->getVolume();
|
||||
faces = &volume->getVolumeFaces();
|
||||
}
|
||||
else
|
||||
{
|
||||
drawable_faces = &drawablep->getFaces();
|
||||
}
|
||||
|
||||
if (faces)
|
||||
{
|
||||
for (auto it = faces->begin(); it != faces->end(); ++it)
|
||||
{
|
||||
const LLVolumeFace& face = *it;
|
||||
|
||||
gGL.flush();
|
||||
gGL.diffuseColor4f(1, 1, 0, 1);
|
||||
gGL.begin(LLRender::LINES);
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
LLVector4a n, p;
|
||||
|
||||
n.setMul(face.mNormals[j], 1.0);
|
||||
n.mul(inv_scale); // Pre-scale normal, so it's left with an inverse-transpose xform after MVP
|
||||
n.normalize3fast();
|
||||
n.mul(draw_length);
|
||||
p.setAdd(face.mPositions[j], n);
|
||||
|
||||
gGL.vertex3fv(face.mPositions[j].getF32ptr());
|
||||
gGL.vertex3fv(p.getF32ptr());
|
||||
}
|
||||
gGL.end();
|
||||
|
||||
// Tangents are simple vectors and do not require reorientation via pre-scaling
|
||||
if (face.mTangents)
|
||||
{
|
||||
gGL.flush();
|
||||
gGL.diffuseColor4f(0, 1, 1, 1);
|
||||
gGL.begin(LLRender::LINES);
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
LLVector4a t, p;
|
||||
|
||||
t.setMul(face.mTangents[j], 1.0f);
|
||||
t.normalize3fast();
|
||||
t.mul(draw_length);
|
||||
p.setAdd(face.mPositions[j], t);
|
||||
|
||||
gGL.vertex3fv(face.mPositions[j].getF32ptr());
|
||||
gGL.vertex3fv(p.getF32ptr());
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (drawable_faces)
|
||||
{
|
||||
// *HACK: Prepare to restore previous shader as other debug code depends on a simpler shader being present
|
||||
llassert(LLGLSLShader::sCurBoundShaderPtr == &gDebugProgram);
|
||||
LLGLSLShader* prev_shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
for (auto it = drawable_faces->begin(); it != drawable_faces->end(); ++it)
|
||||
{
|
||||
LLFace* facep = *it;
|
||||
LLFace& face = **it;
|
||||
LLVertexBuffer* buf = face.getVertexBuffer();
|
||||
if (!buf) { continue; }
|
||||
U32 mask_vn = LLVertexBuffer::TYPE_VERTEX | LLVertexBuffer::TYPE_NORMAL;
|
||||
if ((buf->getTypeMask() & mask_vn) != mask_vn) { continue; }
|
||||
|
||||
LLGLSLShader* shader;
|
||||
if ((buf->getTypeMask() & LLVertexBuffer::TYPE_TANGENT) != LLVertexBuffer::TYPE_TANGENT)
|
||||
{
|
||||
shader = &gNormalDebugProgram[NORMAL_DEBUG_SHADER_DEFAULT];
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gNormalDebugProgram[NORMAL_DEBUG_SHADER_WITH_TANGENTS];
|
||||
}
|
||||
shader->bind();
|
||||
|
||||
shader->uniform1f(LLShaderMgr::DEBUG_NORMAL_DRAW_LENGTH, draw_length);
|
||||
|
||||
LLRenderPass::applyModelMatrix(&facep->getDrawable()->getRegion()->mRenderMatrix);
|
||||
|
||||
buf->setBuffer();
|
||||
// *NOTE: The render type in the vertex shader is TRIANGLES, but gets converted to LINES in the geometry shader
|
||||
// *NOTE: For terrain normal debug, this seems to also include vertices for water, which is technically not part of the terrain. Should fix that at some point.
|
||||
buf->drawRange(LLRender::TRIANGLES, face.getGeomIndex(), face.getGeomIndex() + face.getGeomCount()-1, face.getIndicesCount(), face.getIndicesStart());
|
||||
}
|
||||
if (prev_shader)
|
||||
{
|
||||
prev_shader->bind();
|
||||
}
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,17 +643,18 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent)
|
|||
}
|
||||
}
|
||||
|
||||
BOOL LLSurface::idleUpdate(F32 max_update_time)
|
||||
template<bool PBR>
|
||||
bool LLSurface::idleUpdate(F32 max_update_time)
|
||||
{
|
||||
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN))
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform idle time update of non-critical stuff.
|
||||
// In this case, texture and normal updates.
|
||||
LLTimer update_timer;
|
||||
BOOL did_update = FALSE;
|
||||
bool did_update = false;
|
||||
|
||||
// If the Z height data has changed, we need to rebuild our
|
||||
// property line vertex arrays.
|
||||
|
|
@ -669,13 +670,13 @@ BOOL LLSurface::idleUpdate(F32 max_update_time)
|
|||
{
|
||||
std::set<LLSurfacePatch *>::iterator curiter = iter++;
|
||||
LLSurfacePatch *patchp = *curiter;
|
||||
patchp->updateNormals();
|
||||
patchp->updateNormals<PBR>();
|
||||
patchp->updateVerticalStats();
|
||||
if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time)
|
||||
{
|
||||
if (patchp->updateTexture())
|
||||
{
|
||||
did_update = TRUE;
|
||||
did_update = true;
|
||||
patchp->clearDirty();
|
||||
mDirtyPatchList.erase(curiter);
|
||||
}
|
||||
|
|
@ -691,6 +692,9 @@ BOOL LLSurface::idleUpdate(F32 max_update_time)
|
|||
return did_update;
|
||||
}
|
||||
|
||||
template bool LLSurface::idleUpdate</*PBR=*/false>(F32 max_update_time);
|
||||
template bool LLSurface::idleUpdate</*PBR=*/true>(F32 max_update_time);
|
||||
|
||||
void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ public:
|
|||
LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const;
|
||||
|
||||
// Update methods (called during idle, normally)
|
||||
BOOL idleUpdate(F32 max_update_time);
|
||||
template<bool PBR>
|
||||
bool idleUpdate(F32 max_update_time);
|
||||
|
||||
BOOL containsPosition(const LLVector3 &position);
|
||||
|
||||
|
|
@ -224,6 +225,9 @@ private:
|
|||
static S32 sTextureSize; // Size of the surface texture
|
||||
};
|
||||
|
||||
extern template bool LLSurface::idleUpdate</*PBR=*/false>(F32 max_update_time);
|
||||
extern template bool LLSurface::idleUpdate</*PBR=*/true>(F32 max_update_time);
|
||||
|
||||
|
||||
|
||||
// . __.
|
||||
|
|
|
|||
|
|
@ -221,7 +221,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);
|
||||
|
|
@ -241,7 +243,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
|
|||
}
|
||||
|
||||
|
||||
void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
|
||||
template<>
|
||||
void LLSurfacePatch::calcNormal</*PBR=*/false>(const U32 x, const U32 y, const U32 stride)
|
||||
{
|
||||
U32 patch_width = mSurfacep->mPVArray.mPatchWidth;
|
||||
U32 surface_stride = mSurfacep->getGridsPerEdge();
|
||||
|
|
@ -354,6 +357,166 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
|
|||
*(mDataNorm + surface_stride * y + x) = normal;
|
||||
}
|
||||
|
||||
template<>
|
||||
void LLSurfacePatch::calcNormal</*PBR=*/true>(const U32 x, const U32 y, const U32 stride)
|
||||
{
|
||||
llassert(mDataNorm);
|
||||
constexpr U32 index = 0;
|
||||
|
||||
const U32 surface_stride = mSurfacep->getGridsPerEdge();
|
||||
LLVector3& normal_out = *(mDataNorm + surface_stride * y + x);
|
||||
calcNormalFlat(normal_out, x, y, index);
|
||||
}
|
||||
|
||||
// Calculate the flat normal of a triangle whose least coordinate is specified by the given x,y values.
|
||||
// If index = 0, calculate the normal of the first triangle, otherwise calculate the normal of the second.
|
||||
void LLSurfacePatch::calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index)
|
||||
{
|
||||
llassert(index == 0 || index == 1);
|
||||
|
||||
U32 patch_width = mSurfacep->mPVArray.mPatchWidth;
|
||||
U32 surface_stride = mSurfacep->getGridsPerEdge();
|
||||
|
||||
// Vertex stride is always 1 because we want the flat surface of the current triangle face
|
||||
constexpr U32 stride = 1;
|
||||
|
||||
const F32 mpg = mSurfacep->getMetersPerGrid() * stride;
|
||||
|
||||
S32 poffsets[2][2][2];
|
||||
poffsets[0][0][0] = x;
|
||||
poffsets[0][0][1] = y;
|
||||
|
||||
poffsets[0][1][0] = x;
|
||||
poffsets[0][1][1] = y + stride;
|
||||
|
||||
poffsets[1][0][0] = x + stride;
|
||||
poffsets[1][0][1] = y;
|
||||
|
||||
poffsets[1][1][0] = x + stride;
|
||||
poffsets[1][1][1] = y + stride;
|
||||
|
||||
const LLSurfacePatch *ppatches[2][2];
|
||||
|
||||
// LLVector3 p1, p2, p3, p4;
|
||||
|
||||
ppatches[0][0] = this;
|
||||
ppatches[0][1] = this;
|
||||
ppatches[1][0] = this;
|
||||
ppatches[1][1] = this;
|
||||
|
||||
U32 i, j;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (poffsets[i][j][0] < 0)
|
||||
{
|
||||
if (!ppatches[i][j]->getNeighborPatch(WEST))
|
||||
{
|
||||
poffsets[i][j][0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
poffsets[i][j][0] += patch_width;
|
||||
ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST);
|
||||
}
|
||||
}
|
||||
if (poffsets[i][j][1] < 0)
|
||||
{
|
||||
if (!ppatches[i][j]->getNeighborPatch(SOUTH))
|
||||
{
|
||||
poffsets[i][j][1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
poffsets[i][j][1] += patch_width;
|
||||
ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH);
|
||||
}
|
||||
}
|
||||
if (poffsets[i][j][0] >= (S32)patch_width)
|
||||
{
|
||||
if (!ppatches[i][j]->getNeighborPatch(EAST))
|
||||
{
|
||||
poffsets[i][j][0] = patch_width - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
poffsets[i][j][0] -= patch_width;
|
||||
ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST);
|
||||
}
|
||||
}
|
||||
if (poffsets[i][j][1] >= (S32)patch_width)
|
||||
{
|
||||
if (!ppatches[i][j]->getNeighborPatch(NORTH))
|
||||
{
|
||||
poffsets[i][j][1] = patch_width - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
poffsets[i][j][1] -= patch_width;
|
||||
ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLVector3 p00(-mpg,-mpg,
|
||||
*(ppatches[0][0]->mDataZ
|
||||
+ poffsets[0][0][0]
|
||||
+ poffsets[0][0][1]*surface_stride));
|
||||
LLVector3 p01(-mpg,+mpg,
|
||||
*(ppatches[0][1]->mDataZ
|
||||
+ poffsets[0][1][0]
|
||||
+ poffsets[0][1][1]*surface_stride));
|
||||
LLVector3 p10(+mpg,-mpg,
|
||||
*(ppatches[1][0]->mDataZ
|
||||
+ poffsets[1][0][0]
|
||||
+ poffsets[1][0][1]*surface_stride));
|
||||
LLVector3 p11(+mpg,+mpg,
|
||||
*(ppatches[1][1]->mDataZ
|
||||
+ poffsets[1][1][0]
|
||||
+ poffsets[1][1][1]*surface_stride));
|
||||
|
||||
// Triangle index / coordinate convention
|
||||
// for a single surface patch
|
||||
//
|
||||
// p01 p11
|
||||
//
|
||||
// ^ ._____.
|
||||
// | |\ |
|
||||
// | | \ 1 |
|
||||
// | | \ |
|
||||
// | 0 \ |
|
||||
// y |____\|
|
||||
//
|
||||
// p00 x ---> p10
|
||||
//
|
||||
// (z up / out of the screen due to right-handed coordinate system)
|
||||
|
||||
LLVector3 normal;
|
||||
if (index == 0)
|
||||
{
|
||||
LLVector3 c1 = p10 - p00;
|
||||
LLVector3 c2 = p01 - p00;
|
||||
|
||||
normal = c1;
|
||||
normal %= c2;
|
||||
normal.normVec();
|
||||
}
|
||||
else // index == 1
|
||||
{
|
||||
LLVector3 c1 = p11 - p01;
|
||||
LLVector3 c2 = p11 - p10;
|
||||
|
||||
normal = c1;
|
||||
normal %= c2;
|
||||
normal.normVec();
|
||||
}
|
||||
|
||||
llassert(&normal_out);
|
||||
normal_out = normal;
|
||||
}
|
||||
|
||||
const LLVector3 &LLSurfacePatch::getNormal(const U32 x, const U32 y) const
|
||||
{
|
||||
U32 surface_stride = mSurfacep->getGridsPerEdge();
|
||||
|
|
@ -451,6 +614,7 @@ void LLSurfacePatch::updateVerticalStats()
|
|||
}
|
||||
|
||||
|
||||
template<bool PBR>
|
||||
void LLSurfacePatch::updateNormals()
|
||||
{
|
||||
if (mSurfacep->mType == 'w')
|
||||
|
|
@ -468,9 +632,9 @@ void LLSurfacePatch::updateNormals()
|
|||
{
|
||||
for (j = 0; j <= grids_per_patch_edge; j++)
|
||||
{
|
||||
calcNormal(grids_per_patch_edge, j, 2);
|
||||
calcNormal(grids_per_patch_edge - 1, j, 2);
|
||||
calcNormal(grids_per_patch_edge - 2, j, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge, j, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge - 1, j, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge - 2, j, 2);
|
||||
}
|
||||
|
||||
dirty_patch = TRUE;
|
||||
|
|
@ -481,9 +645,9 @@ void LLSurfacePatch::updateNormals()
|
|||
{
|
||||
for (i = 0; i <= grids_per_patch_edge; i++)
|
||||
{
|
||||
calcNormal(i, grids_per_patch_edge, 2);
|
||||
calcNormal(i, grids_per_patch_edge - 1, 2);
|
||||
calcNormal(i, grids_per_patch_edge - 2, 2);
|
||||
calcNormal<PBR>(i, grids_per_patch_edge, 2);
|
||||
calcNormal<PBR>(i, grids_per_patch_edge - 1, 2);
|
||||
calcNormal<PBR>(i, grids_per_patch_edge - 2, 2);
|
||||
}
|
||||
|
||||
dirty_patch = TRUE;
|
||||
|
|
@ -494,8 +658,8 @@ void LLSurfacePatch::updateNormals()
|
|||
{
|
||||
for (j = 0; j < grids_per_patch_edge; j++)
|
||||
{
|
||||
calcNormal(0, j, 2);
|
||||
calcNormal(1, j, 2);
|
||||
calcNormal<PBR>(0, j, 2);
|
||||
calcNormal<PBR>(1, j, 2);
|
||||
}
|
||||
dirty_patch = TRUE;
|
||||
}
|
||||
|
|
@ -505,8 +669,8 @@ void LLSurfacePatch::updateNormals()
|
|||
{
|
||||
for (i = 0; i < grids_per_patch_edge; i++)
|
||||
{
|
||||
calcNormal(i, 0, 2);
|
||||
calcNormal(i, 1, 2);
|
||||
calcNormal<PBR>(i, 0, 2);
|
||||
calcNormal<PBR>(i, 1, 2);
|
||||
}
|
||||
dirty_patch = TRUE;
|
||||
}
|
||||
|
|
@ -582,10 +746,10 @@ void LLSurfacePatch::updateNormals()
|
|||
// We've got a northeast patch in the same surface.
|
||||
// The z and normals will be handled by that patch.
|
||||
}
|
||||
calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2);
|
||||
calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2);
|
||||
calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2);
|
||||
calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge, grids_per_patch_edge, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge, grids_per_patch_edge - 1, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge - 1, grids_per_patch_edge, 2);
|
||||
calcNormal<PBR>(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2);
|
||||
dirty_patch = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -596,7 +760,7 @@ void LLSurfacePatch::updateNormals()
|
|||
{
|
||||
for (i=2; i < grids_per_patch_edge - 2; i++)
|
||||
{
|
||||
calcNormal(i, j, 2);
|
||||
calcNormal<PBR>(i, j, 2);
|
||||
}
|
||||
}
|
||||
dirty_patch = TRUE;
|
||||
|
|
@ -613,6 +777,9 @@ void LLSurfacePatch::updateNormals()
|
|||
}
|
||||
}
|
||||
|
||||
template void LLSurfacePatch::updateNormals</*PBR=*/false>();
|
||||
template void LLSurfacePatch::updateNormals</*PBR=*/true>();
|
||||
|
||||
void LLSurfacePatch::updateEastEdge()
|
||||
{
|
||||
U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
|
||||
|
|
@ -739,7 +906,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;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ public:
|
|||
|
||||
void updateVerticalStats();
|
||||
void updateCompositionStats();
|
||||
template<bool PBR>
|
||||
void updateNormals();
|
||||
|
||||
void updateEastEdge();
|
||||
|
|
@ -102,9 +103,18 @@ public:
|
|||
LLVector3 getPointAgent(const U32 x, const U32 y) const; // get the point at the offset.
|
||||
LLVector2 getTexCoords(const U32 x, const U32 y) const;
|
||||
|
||||
// Per-vertex normals
|
||||
// *TODO: PBR=true is a test implementation solely for proof-of-concept.
|
||||
// Final implementation would likely be very different and may not even use
|
||||
// this function. If we decide to keep calcNormalFlat, remove index as it
|
||||
// is a debug parameter for testing.
|
||||
template<bool PBR>
|
||||
void calcNormal(const U32 x, const U32 y, const U32 stride);
|
||||
const LLVector3 &getNormal(const U32 x, const U32 y) const;
|
||||
|
||||
// Per-triangle normals for flat edges
|
||||
void calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index /* 0 or 1 */);
|
||||
|
||||
void eval(const U32 x, const U32 y, const U32 stride,
|
||||
LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1);
|
||||
|
||||
|
|
@ -181,5 +191,8 @@ protected:
|
|||
LLSurface *mSurfacep; // Pointer to "parent" surface
|
||||
};
|
||||
|
||||
extern template void LLSurfacePatch::updateNormals</*PBR=*/false>();
|
||||
extern template void LLSurfacePatch::updateNormals</*PBR=*/true>();
|
||||
|
||||
|
||||
#endif // LL_LLSURFACEPATCH_H
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@
|
|||
|
||||
#include "llradiogroup.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llgltfmaterialpreviewmgr.h"
|
||||
#include "lllocalbitmaps.h"
|
||||
#include "lllocalgltfmaterials.h"
|
||||
#include "llerror.h"
|
||||
|
|
@ -659,6 +660,7 @@ void LLFloaterTexturePicker::draw()
|
|||
if( mOwner )
|
||||
{
|
||||
mTexturep = NULL;
|
||||
LLPointer<LLFetchedGLTFMaterial> old_material = mGLTFMaterial;
|
||||
mGLTFMaterial = NULL;
|
||||
if (mImageAssetID.notNull())
|
||||
{
|
||||
|
|
@ -666,10 +668,27 @@ 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);
|
||||
}
|
||||
}
|
||||
if (mGLTFPreview)
|
||||
{
|
||||
mGLTFPreview->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLPointer<LLViewerFetchedTexture> texture = NULL;
|
||||
mGLTFPreview = nullptr;
|
||||
|
||||
if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
|
||||
{
|
||||
|
|
@ -679,7 +698,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -720,27 +739,25 @@ 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;
|
||||
if (mGLTFMaterial)
|
||||
{
|
||||
texture = mGLTFMaterial->getUITexture();
|
||||
preview = mGLTFPreview.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = mTexturep.get();
|
||||
preview = mTexturep.get();
|
||||
}
|
||||
|
||||
if( texture )
|
||||
if( preview )
|
||||
{
|
||||
if( texture->getComponents() == 4 )
|
||||
preview->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
|
||||
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())
|
||||
{
|
||||
|
|
@ -1639,7 +1656,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
|
|||
mShowLoadingPlaceholder( TRUE ),
|
||||
mOpenTexPreview(false),
|
||||
mBakeTextureEnabled(true),
|
||||
mInventoryPickType(PICK_TEXTURE),
|
||||
mInventoryPickType(p.pick_type),
|
||||
mImageAssetID(p.image_id),
|
||||
mDefaultImageAssetID(p.default_image_id),
|
||||
mDefaultImageName(p.default_image_name),
|
||||
|
|
@ -2157,48 +2174,73 @@ 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);
|
||||
}
|
||||
}
|
||||
if (mGLTFPreview)
|
||||
{
|
||||
mGLTFPreview->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -2211,15 +2253,15 @@ 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);
|
||||
preview->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
|
||||
}
|
||||
else if (!mFallbackImage.isNull())
|
||||
{
|
||||
|
|
@ -2366,6 +2408,16 @@ LLSD LLTextureCtrl::getValue() const
|
|||
return LLSD(getImageAssetID());
|
||||
}
|
||||
|
||||
namespace LLInitParam
|
||||
{
|
||||
void TypeValues<EPickInventoryType>::declareValues()
|
||||
{
|
||||
declare("texture_material", PICK_TEXTURE_MATERIAL);
|
||||
declare("texture", PICK_TEXTURE);
|
||||
declare("material", PICK_MATERIAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,13 +64,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
|
||||
{
|
||||
|
|
@ -79,6 +72,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
|
||||
|
||||
|
|
@ -100,6 +110,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
|
||||
|
|
@ -117,6 +128,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),
|
||||
|
|
@ -250,6 +262,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;
|
||||
|
|
@ -382,6 +396,7 @@ protected:
|
|||
|
||||
LLPointer<LLViewerTexture> mTexturep;
|
||||
LLPointer<LLFetchedGLTFMaterial> mGLTFMaterial;
|
||||
LLPointer<LLViewerTexture> mGLTFPreview;
|
||||
LLView* mOwner;
|
||||
|
||||
LLUUID mImageAssetID; // Currently selected texture
|
||||
|
|
|
|||
|
|
@ -764,6 +764,12 @@ BOOL LLViewerCamera::cameraUnderWater() const
|
|||
{
|
||||
LLViewerRegion* regionp = LLWorld::instance().getRegionFromPosAgent(getOrigin());
|
||||
|
||||
if (gPipeline.mHeroProbeManager.isMirrorPass())
|
||||
{
|
||||
// TODO: figure out how to handle this case
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!regionp)
|
||||
{
|
||||
regionp = gAgent.getRegion();
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include "llvotree.h"
|
||||
#include "llvovolume.h"
|
||||
#include "llworld.h"
|
||||
#include "llvlcomposition.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewerjoystick.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
|
|
@ -117,12 +118,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)
|
||||
{
|
||||
|
|
@ -650,6 +664,16 @@ void handleFPSTuningStrategyChanged(const LLSD& newValue)
|
|||
const auto newval = gSavedSettings.getU32("TuningFPSStrategy");
|
||||
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);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLPointer<LLControlVariable> setting_get_control(LLControlGroup& group, const std::string& setting)
|
||||
|
|
@ -684,7 +708,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);
|
||||
|
|
@ -830,6 +858,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -656,6 +656,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
|
|||
|
||||
if (!gDisconnected)
|
||||
{
|
||||
// Render mirrors and associated hero probes before we render the rest of the scene.
|
||||
// This ensures the scene state in the hero probes are exactly the same as the rest of the scene before we render it.
|
||||
if (gPipeline.RenderMirrors && !gSnapshot)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes");
|
||||
gPipeline.mHeroProbeManager.update();
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 1");
|
||||
LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
|
||||
if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
|
||||
|
|
@ -696,7 +704,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
|
|||
}
|
||||
|
||||
gPipeline.updateGL();
|
||||
|
||||
|
||||
stop_glerror();
|
||||
|
||||
LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
|
||||
|
|
@ -1064,7 +1072,7 @@ void display_cube_face()
|
|||
LLSpatialGroup::sNoDelete = TRUE;
|
||||
|
||||
S32 occlusion = LLPipeline::sUseOcclusion;
|
||||
LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
|
||||
LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
|
||||
//gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data
|
||||
|
||||
static LLCullResult result;
|
||||
|
|
|
|||
|
|
@ -2122,6 +2122,20 @@ class LLAdvancedPurgeShaderCache : public view_listener_t
|
|||
}
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
// REBUILD TERRAIN //
|
||||
/////////////////////
|
||||
|
||||
|
||||
class LLAdvancedRebuildTerrain : public view_listener_t
|
||||
{
|
||||
bool handleEvent(const LLSD& userdata)
|
||||
{
|
||||
gPipeline.rebuildTerrain();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////
|
||||
// EVENT Recorder //
|
||||
///////////////////
|
||||
|
|
@ -9492,6 +9506,10 @@ void initialize_menus()
|
|||
view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile");
|
||||
view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark");
|
||||
view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache");
|
||||
if (gSavedSettings.get<bool>("RenderTerrainPBREnabled"))
|
||||
{
|
||||
view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain");
|
||||
}
|
||||
|
||||
#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
|
||||
view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue