# Conflicts:
#	indra/newview/app_settings/settings.xml
#	indra/newview/llreflectionmapmanager.cpp
#	indra/newview/llspatialpartition.cpp
#	indra/newview/llviewercontrol.cpp
#	indra/newview/llviewerdisplay.cpp
#	indra/newview/llviewermenu.cpp
#	indra/newview/llviewershadermgr.cpp
#	indra/newview/llworldmapview.cpp
#	indra/newview/pipeline.cpp
#	indra/newview/skins/default/xui/en/panel_tools_texture.xml
master
Ansariel 2023-03-06 17:11:43 +01:00
commit f4182ddc7f
99 changed files with 2302 additions and 1664 deletions

View File

@ -3078,7 +3078,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>canonical_repo</key>
<string>https://bitbucket.org/lindenlab/3p-tracy</string>
<key>copyright</key>
<string>Copyright (c) 2017-2021, Bartosz Taudul (wolf@nereid.pl)</string>
<string>Copyright (c) 2017-2022, Bartosz Taudul (wolf@nereid.pl)</string>
<key>description</key>
<string>Tracy Profiler Library</string>
<key>license</key>
@ -3094,9 +3094,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>da7317e4a81609f624f84780f28b07de</string>
<string>9b6e1a1f4b0969d38a1ca8ee00aeb548</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86972/801630/tracy-v0.7.8.563351-darwin64-563351.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110584/960613/tracy-v0.8.1.578241-darwin64-578241.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3106,11 +3106,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>47c696cd2966c5cc3c8ba6115dd1f886</string>
<string>9e6975565d7337442259324e68bcf59c</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86973/801641/tracy-v0.7.8.563351-windows-563351.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110585/960636/tracy-v0.8.1.578241-windows-578241.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3120,11 +3120,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>dff3dd1db6a4cb0b73f60a5db3ee0de2</string>
<string>05b72ae5d733aed7d3bf142287601cc6</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100101/882119/tracy-v0.8.1.571983-windows64-571983.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/110586/960637/tracy-v0.8.1.578241-windows64-578241.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
@ -3135,7 +3135,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key>
<string>git</string>
<key>version</key>
<string>v0.7.8.563351</string>
<string>v0.8.1.578241</string>
</map>
<key>tut</key>
<map>

View File

@ -34,6 +34,7 @@ else (LINUX)
${BOOST_CONTEXT_LIBRARY}
${BOOST_THREAD_LIBRARY}
${BOOST_SYSTEM_LIBRARY}
${TRACY_LIBRARY}
)
endif (LINUX)

View File

@ -17,10 +17,12 @@ if (USE_TRACY)
if (DARWIN)
MESSAGE(STATUS "Including Tracy for Darwin: '${TRACY_INCLUDE_DIR}'")
set(TRACY_LIBRARY "TracyClient")
endif (DARWIN)
if (LINUX)
MESSAGE(STATUS "Including Tracy for Linux: '${TRACY_INCLUDE_DIR}'")
set(TRACY_LIBRARY "TracyClient")
endif (LINUX)
else (USE_TRACY)
# Tracy.cmake should not set LLCOMMON_INCLUDE_DIRS, let LLCommon.cmake do that

View File

@ -44,6 +44,7 @@
#include "lltimer.h"
#include "llthread.h"
#include "llmutex.h"
#include "llmd5.h"
#include "hbxxh.h"
#include "llprofiler.h"
@ -404,11 +405,16 @@ LLUUID LLUUID::operator^(const LLUUID& rhs) const
return id;
}
// WARNING: this algorithm SHALL NOT be changed. It is also used by the server
// and plays a role in some assets validation (e.g. clothing items). Changing
// it would cause invalid assets.
void LLUUID::combine(const LLUUID& other, LLUUID& result) const
{
HBXXH128 hash((const void*)mData, 16, false); // false = do not finalize
hash.update((const void*)other.mData, 16);
hash.digest(result);
LLMD5 md5_uuid;
md5_uuid.update((unsigned char*)mData, 16);
md5_uuid.update((unsigned char*)other.mData, 16);
md5_uuid.finalize();
md5_uuid.raw_digest(result.mData);
}
LLUUID LLUUID::combine(const LLUUID &other) const

View File

@ -101,6 +101,8 @@ if (LL_TESTS)
SET(llprimitive_TEST_SOURCE_FILES
llmediaentry.cpp
llprimitive.cpp
llgltfmaterial.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
endif (LL_TESTS)

View File

@ -31,34 +31,28 @@
// NOTE -- this should be the one and only place tiny_gltf.h is included
#include "tinygltf/tiny_gltf.h"
const char* GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
const char* GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
const char* GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
const char* GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
const char* const LLGLTFMaterial::ASSET_VERSION = "1.1";
const char* const LLGLTFMaterial::ASSET_TYPE = "GLTF 2.0";
const std::array<std::string, 2> LLGLTFMaterial::ACCEPTED_ASSET_VERSIONS = { "1.0", "1.1" };
const char* const GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
const char* const GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
// special UUID that indicates a null UUID in override data
static const LLUUID GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
// https://github.com/KhronosGroup/glTF/tree/main/extensions/3.0/Khronos/KHR_texture_transform
LLMatrix3 LLGLTFMaterial::TextureTransform::asMatrix()
void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8])
{
LLMatrix3 scale;
scale.mMatrix[0][0] = mScale[0];
scale.mMatrix[1][1] = mScale[1];
LLMatrix3 rotation;
const F32 cos_r = cos(mRotation);
const F32 sin_r = sin(mRotation);
rotation.mMatrix[0][0] = cos_r;
rotation.mMatrix[0][1] = sin_r;
rotation.mMatrix[1][0] = -sin_r;
rotation.mMatrix[1][1] = cos_r;
LLMatrix3 offset;
offset.mMatrix[2][0] = mOffset[0];
offset.mMatrix[2][1] = mOffset[1];
return offset * rotation * scale;
packed[0] = mScale.mV[VX];
packed[1] = mScale.mV[VY];
packed[2] = mRotation;
// packed[3] = unused
packed[4] = mOffset.mV[VX];
packed[5] = mOffset.mV[VY];
// packed[6] = unused
// packed[7] = unused
}
bool LLGLTFMaterial::TextureTransform::operator==(const TextureTransform& other) const
@ -73,16 +67,14 @@ LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)
LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
{
LL_PROFILE_ZONE_SCOPED;
//have to do a manual operator= because of LLRefCount
mBaseColorId = rhs.mBaseColorId;
mNormalId = rhs.mNormalId;
mMetallicRoughnessId = rhs.mMetallicRoughnessId;
mEmissiveId = rhs.mEmissiveId;
//have to do a manual operator= because of LLRefCount
mTextureId = rhs.mTextureId;
mTextureTransform = rhs.mTextureTransform;
mBaseColor = rhs.mBaseColor;
mEmissiveColor = rhs.mEmissiveColor;
mMetallicFactor = rhs.mMetallicFactor;
mRoughnessFactor = rhs.mRoughnessFactor;
mAlphaCutoff = rhs.mAlphaCutoff;
@ -90,8 +82,6 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
mDoubleSided = rhs.mDoubleSided;
mAlphaMode = rhs.mAlphaMode;
mTextureTransform = rhs.mTextureTransform;
mOverrideDoubleSided = rhs.mOverrideDoubleSided;
mOverrideAlphaMode = rhs.mOverrideAlphaMode;
@ -100,10 +90,9 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const
{
return mBaseColorId == rhs.mBaseColorId &&
mNormalId == rhs.mNormalId &&
mMetallicRoughnessId == rhs.mMetallicRoughnessId &&
mEmissiveId == rhs.mEmissiveId &&
return mTextureId == rhs.mTextureId &&
mTextureTransform == rhs.mTextureTransform &&
mBaseColor == rhs.mBaseColor &&
mEmissiveColor == rhs.mEmissiveColor &&
@ -115,8 +104,6 @@ bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const
mDoubleSided == rhs.mDoubleSided &&
mAlphaMode == rhs.mAlphaMode &&
mTextureTransform == rhs.mTextureTransform &&
mOverrideDoubleSided == rhs.mOverrideDoubleSided &&
mOverrideAlphaMode == rhs.mOverrideAlphaMode;
}
@ -148,6 +135,8 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const
writeToModel(model_out, 0);
// To ensure consistency in asset upload, this should be the only reference
// to WriteGltfSceneToStream in the viewer.
gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false);
return str.str();
@ -164,13 +153,13 @@ void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
const tinygltf::Material& material_in = model.materials[mat_index];
// Apply base color texture
setFromTexture(model, material_in.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId);
setFromTexture(model, material_in.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR);
// Apply normal map
setFromTexture(model, material_in.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId);
setFromTexture(model, material_in.normalTexture, GLTF_TEXTURE_INFO_NORMAL);
// Apply metallic-roughness texture
setFromTexture(model, material_in.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId);
setFromTexture(model, material_in.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS);
// Apply emissive texture
setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId);
setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE);
setAlphaMode(material_in.alphaMode);
mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f);
@ -264,11 +253,11 @@ std::string gltf_get_texture_image(const tinygltf::Model& model, const T& textur
// *NOTE: Use template here as workaround for the different similar texture info classes
template<typename T>
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out)
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id)
{
LL_PROFILE_ZONE_SCOPED;
const std::string uri = gltf_get_texture_image(model, texture_info);
texture_id_out.set(uri);
mTextureId[texture_info_id].set(uri);
const tinygltf::Value::Object& extensions_object = texture_info.extensions;
const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM);
@ -297,21 +286,24 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
tinygltf::Material& material_out = model.materials[mat_index];
// set base color texture
writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId);
writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR);
// set normal texture
writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId);
writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL);
// set metallic-roughness texture
writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId);
writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS);
// set emissive texture
writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId);
writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE);
// set occlusion texture
// *NOTE: This is required for ORM materials for GLTF compliance.
// See: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_material_occlusiontexture
writeToTexture(model, material_out.occlusionTexture, GLTF_TEXTURE_INFO_OCCLUSION);
material_out.alphaMode = getAlphaMode();
material_out.alphaCutoff = mAlphaCutoff;
mBaseColor.write(material_out.pbrMetallicRoughness.baseColorFactor);
material_out.emissiveFactor.resize(3); // 0 size by default
if (mEmissiveColor != LLGLTFMaterial::getDefaultEmissiveColor())
{
material_out.emissiveFactor.resize(3);
@ -323,7 +315,6 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
material_out.doubleSided = mDoubleSided;
// generate "extras" string
tinygltf::Value::Object extras;
bool write_extras = false;
@ -364,28 +355,43 @@ void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const
}
template<typename T>
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write) const
{
LL_PROFILE_ZONE_SCOPED;
const LLUUID& texture_id = mTextureId[texture_info_id];
const TextureTransform& transform = mTextureTransform[texture_info_id];
if (texture_id.isNull() && transform == sDefault.mTextureTransform[0])
const bool is_blank_transform = transform == sDefault.mTextureTransform[0];
// Check if this material matches all the fallback values, and if so, then
// skip including it to reduce material size
if (!force_write && texture_id.isNull() && is_blank_transform)
{
return;
}
// tinygltf will discard this texture info if there is no valid texture,
// causing potential loss of information for overrides, so ensure one is
// defined. -Cosmic,2023-01-30
gltf_allocate_texture_image(model, texture_info, texture_id.asString());
tinygltf::Value::Object transform_map;
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mOffset.mV[VX]),
tinygltf::Value(transform.mOffset.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mScale.mV[VX]),
tinygltf::Value(transform.mScale.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
if (!is_blank_transform)
{
tinygltf::Value::Object transform_map;
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mOffset.mV[VX]),
tinygltf::Value(transform.mOffset.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mScale.mV[VX]),
tinygltf::Value(transform.mScale.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
}
}
void LLGLTFMaterial::sanitizeAssetMaterial()
{
mTextureTransform = sDefault.mTextureTransform;
}
bool LLGLTFMaterial::setBaseMaterial()
@ -419,40 +425,33 @@ void LLGLTFMaterial::hackOverrideUUID(LLUUID& id)
}
}
void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override)
void LLGLTFMaterial::setTextureId(TextureInfo texture_info, const LLUUID& id, bool for_override)
{
mBaseColorId = id;
mTextureId[texture_info] = id;
if (for_override)
{
hackOverrideUUID(mBaseColorId);
hackOverrideUUID(mTextureId[texture_info]);
}
}
void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override)
{
setTextureId(GLTF_TEXTURE_INFO_BASE_COLOR, id, for_override);
}
void LLGLTFMaterial::setNormalId(const LLUUID& id, bool for_override)
{
mNormalId = id;
if (for_override)
{
hackOverrideUUID(mNormalId);
}
setTextureId(GLTF_TEXTURE_INFO_NORMAL, id, for_override);
}
void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id, bool for_override)
void LLGLTFMaterial::setOcclusionRoughnessMetallicId(const LLUUID& id, bool for_override)
{
mMetallicRoughnessId = id;
if (for_override)
{
hackOverrideUUID(mMetallicRoughnessId);
}
setTextureId(GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, id, for_override);
}
void LLGLTFMaterial::setEmissiveId(const LLUUID& id, bool for_override)
{
mEmissiveId = id;
if (for_override)
{
hackOverrideUUID(mEmissiveId);
}
setTextureId(GLTF_TEXTURE_INFO_EMISSIVE, id, for_override);
}
void LLGLTFMaterial::setBaseColorFactor(const LLColor4& baseColor, bool for_override)
@ -533,10 +532,7 @@ const char* LLGLTFMaterial::getAlphaMode() const
void LLGLTFMaterial::setAlphaMode(S32 mode, bool for_override)
{
mAlphaMode = (AlphaMode) llclamp(mode, (S32) ALPHA_MODE_OPAQUE, (S32) ALPHA_MODE_MASK);
if (for_override)
{
mOverrideAlphaMode = true;
}
mOverrideAlphaMode = for_override && mAlphaMode == getDefaultAlphaMode();
}
void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override)
@ -544,10 +540,7 @@ void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override)
// sure, no clamping will ever be needed for a bool, but include the
// setter for consistency with the clamping API
mDoubleSided = double_sided;
if (for_override)
{
mOverrideDoubleSided = true;
}
mOverrideDoubleSided = for_override && mDoubleSided == getDefaultDoubleSided();
}
void LLGLTFMaterial::setTextureOffset(TextureInfo texture_info, const LLVector2& offset)
@ -640,10 +633,12 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
{
LL_PROFILE_ZONE_SCOPED;
applyOverrideUUID(mBaseColorId, override_mat.mBaseColorId);
applyOverrideUUID(mNormalId, override_mat.mNormalId);
applyOverrideUUID(mMetallicRoughnessId, override_mat.mMetallicRoughnessId);
applyOverrideUUID(mEmissiveId, override_mat.mEmissiveId);
for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i)
{
LLUUID& texture_id = mTextureId[i];
const LLUUID& override_texture_id = override_mat.mTextureId[i];
applyOverrideUUID(texture_id, override_texture_id);
}
if (override_mat.mBaseColor != getDefaultBaseColor())
{

View File

@ -28,7 +28,6 @@
#include "llrefcount.h"
#include "llmemory.h"
#include "m3math.h"
#include "v4color.h"
#include "v3color.h"
#include "v2math.h"
@ -49,13 +48,18 @@ public:
// default material for reference
static const LLGLTFMaterial sDefault;
static const char* const ASSET_VERSION;
static const char* const ASSET_TYPE;
static const std::array<std::string, 2> ACCEPTED_ASSET_VERSIONS;
static bool isAcceptedVersion(const std::string& version) { return std::find(ACCEPTED_ASSET_VERSIONS.cbegin(), ACCEPTED_ASSET_VERSIONS.cend(), version) != ACCEPTED_ASSET_VERSIONS.cend(); }
struct TextureTransform
{
LLVector2 mOffset = { 0.f, 0.f };
LLVector2 mScale = { 1.f, 1.f };
F32 mRotation = 0.f;
LLMatrix3 asMatrix();
void getPacked(F32 (&packed)[8]);
bool operator==(const TextureTransform& other) const;
};
@ -74,12 +78,28 @@ public:
bool operator==(const LLGLTFMaterial& rhs) const;
bool operator!=(const LLGLTFMaterial& rhs) const { return !(*this == rhs); }
LLUUID mBaseColorId;
LLUUID mNormalId;
LLUUID mMetallicRoughnessId;
LLUUID mEmissiveId;
enum TextureInfo : U32
{
GLTF_TEXTURE_INFO_BASE_COLOR,
GLTF_TEXTURE_INFO_NORMAL,
GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
// *NOTE: GLTF_TEXTURE_INFO_OCCLUSION is currently ignored, in favor of
// the values specified with GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS.
// Currently, only ORM materials are supported (materials which define
// occlusion, roughness, and metallic in the same texture).
// -Cosmic,2023-01-26
GLTF_TEXTURE_INFO_OCCLUSION = GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
GLTF_TEXTURE_INFO_EMISSIVE,
// NOTE : initialize values to defaults according to the GLTF spec
GLTF_TEXTURE_INFO_COUNT
};
std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId;
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
// NOTE: initialize values to defaults according to the GLTF spec
// NOTE: these values should be in linear color space
LLColor4 mBaseColor = LLColor4(1, 1, 1, 1);
LLColor3 mEmissiveColor = LLColor3(0, 0, 0);
@ -104,24 +124,14 @@ public:
return hash;
}
enum TextureInfo : U32
{
GLTF_TEXTURE_INFO_BASE_COLOR,
GLTF_TEXTURE_INFO_NORMAL,
GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
GLTF_TEXTURE_INFO_EMISSIVE,
GLTF_TEXTURE_INFO_COUNT
};
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
//setters for various members (will clamp to acceptable ranges)
// for_override - set to true if this value is being set as part of an override (important for handling override to default value)
void setTextureId(TextureInfo texture_info, const LLUUID& id, bool for_override = false);
void setBaseColorId(const LLUUID& id, bool for_override = false);
void setNormalId(const LLUUID& id, bool for_override = false);
void setMetallicRoughnessId(const LLUUID& id, bool for_override = false);
void setOcclusionRoughnessMetallicId(const LLUUID& id, bool for_override = false);
void setEmissiveId(const LLUUID& id, bool for_override = false);
void setBaseColorFactor(const LLColor4& baseColor, bool for_override = false);
@ -180,6 +190,10 @@ public:
void applyOverride(const LLGLTFMaterial& override_mat);
// For base materials only (i.e. assets). Clears transforms to
// default since they're not supported in assets yet.
void sanitizeAssetMaterial();
// For material overrides only. Clears most properties to
// default/fallthrough, but preserves the transforms.
bool setBaseMaterial();
@ -187,12 +201,11 @@ public:
bool isClearedForBaseMaterial();
private:
template<typename T>
void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id);
template<typename T>
void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out);
template<typename T>
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const;
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;
void setBaseMaterial(const LLGLTFMaterial& old_override_mat);
};

View File

@ -0,0 +1,369 @@
/**
* @file llgltfmaterial_test.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 "linden_common.h"
#include "lltut.h"
#include "../llgltfmaterial.h"
#include "lluuid.cpp"
// Import & define single-header gltf import/export lib
#define TINYGLTF_IMPLEMENTATION
#define TINYGLTF_USE_CPP14 // default is C++ 11
// tinygltf by default loads image files using STB
#define STB_IMAGE_IMPLEMENTATION
// to use our own image loading:
// 1. replace this definition with TINYGLTF_NO_STB_IMAGE
// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)
// tinygltf saves image files using STB
#define STB_IMAGE_WRITE_IMPLEMENTATION
// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data)
// Disable reading external images to prevent warnings and speed up the tests.
// We don't need this for the tests, but still need the filesystem
// implementation to be defined in order for llprimitive to link correctly.
#define TINYGLTF_NO_EXTERNAL_IMAGE 1
#include "tinygltf/tiny_gltf.h"
namespace tut
{
struct llgltfmaterial
{
};
typedef test_group<llgltfmaterial> llgltfmaterial_t;
typedef llgltfmaterial_t::object llgltfmaterial_object_t;
tut::llgltfmaterial_t tut_llgltfmaterial("llgltfmaterial");
// A positive 32-bit float with a long string representation
constexpr F32 test_fraction = 1.09045365e-32;
// A larger positive 32-bit float for values that get zeroed if below a threshold
constexpr F32 test_fraction_big = 0.109045;
void apply_test_material_texture_ids(LLGLTFMaterial& material)
{
material.setBaseColorId(LLUUID::generateNewID());
material.setNormalId(LLUUID::generateNewID());
material.setOcclusionRoughnessMetallicId(LLUUID::generateNewID());
material.setEmissiveId(LLUUID::generateNewID());
}
void apply_test_material_texture_transforms(LLGLTFMaterial& material)
{
LLGLTFMaterial::TextureTransform test_transform;
test_transform.mOffset.mV[VX] = test_fraction;
test_transform.mOffset.mV[VY] = test_fraction;
test_transform.mScale.mV[VX] = test_fraction;
test_transform.mScale.mV[VY] = test_fraction;
test_transform.mRotation = test_fraction;
for (LLGLTFMaterial::TextureInfo i = LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; i = LLGLTFMaterial::TextureInfo((U32)i + 1))
{
material.setTextureOffset(i, test_transform.mOffset);
material.setTextureScale(i, test_transform.mScale);
material.setTextureRotation(i, test_transform.mRotation);
}
}
void apply_test_material_factors(LLGLTFMaterial& material)
{
material.setBaseColorFactor(LLColor4(test_fraction_big, test_fraction_big, test_fraction_big, test_fraction_big));
material.setEmissiveColorFactor(LLColor3(test_fraction_big, test_fraction_big, test_fraction_big));
material.setMetallicFactor(test_fraction);
material.setRoughnessFactor(test_fraction);
}
LLGLTFMaterial create_test_material()
{
LLGLTFMaterial material;
apply_test_material_texture_ids(material);
apply_test_material_texture_transforms(material);
apply_test_material_factors(material);
material.setAlphaCutoff(test_fraction);
// Because this is the default value, it should append to the extras field to mark it as an override
material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_OPAQUE);
// Because this is the default value, it should append to the extras field to mark it as an override
material.setDoubleSided(false);
return material;
}
void ensure_gltf_material_serialize(const std::string& ensure_suffix, const LLGLTFMaterial& material_in)
{
const std::string json_in = material_in.asJSON();
LLGLTFMaterial material_out;
std::string warn_msg;
std::string error_msg;
bool serialize_success = material_out.fromJSON(json_in, warn_msg, error_msg);
ensure_equals("LLGLTFMaterial serialization has no warnings: " + ensure_suffix, "", warn_msg);
ensure_equals("LLGLTFMaterial serialization has no errors: " + ensure_suffix, "", error_msg);
ensure("LLGLTFMaterial serializes successfully: " + ensure_suffix, serialize_success);
ensure("LLGLTFMaterial is preserved when deserialized: " + ensure_suffix, material_in == material_out);
const std::string json_out = material_out.asJSON();
ensure_equals("LLGLTFMaterial is preserved when serialized: " + ensure_suffix, json_in, json_out);
}
void ensure_gltf_material_trimmed(const std::string& material_json, const std::string& must_not_contain)
{
ensure("LLGLTFMaterial serialization trims property '" + must_not_contain + "'", material_json.find(must_not_contain) == std::string::npos);
}
// Test that GLTF material fields have not changed since these tests were written
template<> template<>
void llgltfmaterial_object_t::test<1>()
{
#if ADDRESS_SIZE != 32
#if LL_WINDOWS
// If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial)
// This test result will vary between compilers, so only test a single platform
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 216);
#endif
#endif
ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4);
}
// Test that occlusion and metallicRoughness are the same (They are different for asset validation. See lluploadmaterial.cpp)
template<> template<>
void llgltfmaterial_object_t::test<2>()
{
ensure_equals("LLGLTFMaterial occlusion does not differ from metallic roughness", LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, LLGLTFMaterial::GLTF_TEXTURE_INFO_OCCLUSION);
}
// Ensure double sided and alpha mode overrides serialize as expected
template<> template<>
void llgltfmaterial_object_t::test<3>()
{
const bool doubleSideds[] { false, true };
const LLGLTFMaterial::AlphaMode alphaModes[] { LLGLTFMaterial::ALPHA_MODE_OPAQUE, LLGLTFMaterial::ALPHA_MODE_BLEND, LLGLTFMaterial::ALPHA_MODE_MASK };
const bool forOverrides[] { false, true };
for (bool doubleSided : doubleSideds)
{
for (bool forOverride : forOverrides)
{
LLGLTFMaterial material;
material.setDoubleSided(doubleSided, forOverride);
const bool overrideBit = (doubleSided == false) && forOverride;
ensure_equals("LLGLTFMaterial: double sided = " + std::to_string(doubleSided) + " override bit when forOverride = " + std::to_string(forOverride), material.mOverrideDoubleSided, overrideBit);
ensure_gltf_material_serialize("double sided = " + std::to_string(doubleSided), material);
}
}
for (LLGLTFMaterial::AlphaMode alphaMode : alphaModes)
{
for (bool forOverride : forOverrides)
{
LLGLTFMaterial material;
material.setAlphaMode(alphaMode, forOverride);
const bool overrideBit = (alphaMode == LLGLTFMaterial::ALPHA_MODE_OPAQUE) && forOverride;
ensure_equals("LLGLTFMaterial: alpha mode = " + std::to_string(alphaMode) + " override bit when forOverride = " + std::to_string(forOverride), material.mOverrideAlphaMode, overrideBit);
ensure_gltf_material_serialize("alpha mode = " + std::to_string(alphaMode), material);
}
}
}
// Test that a GLTF material's transform components serialize as expected
template<> template<>
void llgltfmaterial_object_t::test<4>()
{
LLGLTFMaterial material;
LLGLTFMaterial::TextureTransform& transform = material.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR];
transform.mOffset[VX] = 1.f;
transform.mOffset[VY] = 2.f;
transform.mScale[VX] = 0.05f;
transform.mScale[VY] = 100.f;
transform.mRotation = 1.571f;
ensure_gltf_material_serialize("material with transform", material);
}
// Test that a GLTF material avoids serializing a material unnecessarily
template<> template<>
void llgltfmaterial_object_t::test<5>()
{
{
const LLGLTFMaterial material;
const std::string material_json = material.asJSON();
ensure_gltf_material_trimmed(material_json, "pbrMetallicRoughness");
ensure_gltf_material_trimmed(material_json, "normalTexture");
ensure_gltf_material_trimmed(material_json, "emissiveTexture");
ensure_gltf_material_trimmed(material_json, "occlusionTexture");
}
{
LLGLTFMaterial metallic_factor_material;
metallic_factor_material.setMetallicFactor(0.5);
const std::string metallic_factor_material_json = metallic_factor_material.asJSON();
ensure_gltf_material_trimmed(metallic_factor_material_json, "baseColorTexture");
ensure_gltf_material_trimmed(metallic_factor_material_json, "metallicRoughnessTexture");
}
}
// Test that a GLTF material preserves values on serialization
template<> template<>
void llgltfmaterial_object_t::test<6>()
{
{
const LLGLTFMaterial full_material = create_test_material();
ensure_gltf_material_serialize("full material", full_material);
}
{
LLGLTFMaterial texture_ids_only_material;
apply_test_material_texture_ids(texture_ids_only_material);
ensure_gltf_material_serialize("material with texture IDs only", texture_ids_only_material);
}
{
LLGLTFMaterial texture_transforms_only_material;
apply_test_material_texture_ids(texture_transforms_only_material);
ensure_gltf_material_serialize("material with texture transforms only", texture_transforms_only_material);
}
{
LLGLTFMaterial factors_only_material;
apply_test_material_factors(factors_only_material);
ensure_gltf_material_serialize("material with scaling/tint factors only", factors_only_material);
}
}
// Test that sDefault is a no-op override
template<> template<>
void llgltfmaterial_object_t::test<7>()
{
const LLGLTFMaterial material_asset = create_test_material();
LLGLTFMaterial render_material = material_asset;
render_material.applyOverride(LLGLTFMaterial::sDefault);
ensure("LLGLTFMaterial: sDefault is a no-op override", material_asset == render_material);
}
// Test application of transform overrides
template<> template<>
void llgltfmaterial_object_t::test<8>()
{
LLGLTFMaterial override_material;
apply_test_material_texture_transforms(override_material);
LLGLTFMaterial render_material;
render_material.applyOverride(override_material);
ensure("LLGLTFMaterial: transform overrides", render_material == override_material);
}
// Test application of flag-based overrides
template<> template<>
void llgltfmaterial_object_t::test<9>()
{
{
LLGLTFMaterial override_material;
override_material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_BLEND, true);
override_material.setDoubleSided(true, true);
LLGLTFMaterial render_material;
render_material.applyOverride(override_material);
ensure("LLGLTFMaterial: extra overrides with non-default values applied over default", render_material == override_material);
}
{
LLGLTFMaterial override_material;
override_material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_OPAQUE, true);
override_material.setDoubleSided(false, true);
LLGLTFMaterial render_material;
override_material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_BLEND, false);
override_material.setDoubleSided(true, false);
render_material.applyOverride(override_material);
// Not interested in these flags for equality comparison
override_material.mOverrideDoubleSided = false;
override_material.mOverrideAlphaMode = false;
ensure("LLGLTFMaterial: extra overrides with default values applied over non-default", render_material == override_material);
}
}
// Test application of texture overrides
template<> template<>
void llgltfmaterial_object_t::test<10>()
{
const U32 texture_count = 2;
const LLUUID override_textures[texture_count] = { LLUUID::null, LLUUID::generateNewID() };
const LLUUID asset_textures[texture_count] = { LLUUID::generateNewID(), LLUUID::null };
for (U32 i = 0; i < texture_count; ++i)
{
LLGLTFMaterial override_material;
const LLUUID& override_texture = override_textures[i];
for (LLGLTFMaterial::TextureInfo j = LLGLTFMaterial::TextureInfo(0); j < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; j = LLGLTFMaterial::TextureInfo(U32(j) + 1))
{
override_material.setTextureId(j, override_texture, true);
}
LLGLTFMaterial render_material;
const LLUUID& asset_texture = asset_textures[i];
for (LLGLTFMaterial::TextureInfo j = LLGLTFMaterial::TextureInfo(0); j < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; j = LLGLTFMaterial::TextureInfo(U32(j) + 1))
{
render_material.setTextureId(j, asset_texture, false);
}
render_material.applyOverride(override_material);
for (LLGLTFMaterial::TextureInfo j = LLGLTFMaterial::TextureInfo(0); j < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; j = LLGLTFMaterial::TextureInfo(U32(j) + 1))
{
const LLUUID& render_texture = render_material.mTextureId[j];
ensure_equals("LLGLTFMaterial: Override texture ID " + override_texture.asString() + " replaces underlying texture ID " + asset_texture.asString(), render_texture, override_texture);
}
}
}
// Test non-persistence of default value flags in overrides
template<> template<>
void llgltfmaterial_object_t::test<11>()
{
const S32 non_default_alpha_modes[] = { LLGLTFMaterial::ALPHA_MODE_BLEND, LLGLTFMaterial::ALPHA_MODE_MASK };
for (S32 non_default_alpha_mode : non_default_alpha_modes)
{
LLGLTFMaterial material;
// Set default alpha mode
material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_OPAQUE, true);
ensure_equals("LLGLTFMaterial: alpha mode override flag set", material.mOverrideAlphaMode, true);
// Set non-default alpha mode
material.setAlphaMode(non_default_alpha_mode, true);
ensure_equals("LLGLTFMaterial: alpha mode override flag unset", material.mOverrideAlphaMode, false);
}
{
// Set default double sided
LLGLTFMaterial material;
material.setDoubleSided(false, true);
ensure_equals("LLGLTFMaterial: double sided override flag set", material.mOverrideDoubleSided, true);
// Set non-default double sided
material.setDoubleSided(true, true);
ensure_equals("LLGLTFMaterial: double sided override flag unset", material.mOverrideDoubleSided, false);
}
}
}

View File

@ -122,7 +122,7 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, BOOL us
bind(0);
U32 format = components == 4 ? GL_RGBA12 : GL_RGB10;
U32 format = components == 4 ? GL_RGBA12 : GL_RGB16F;
U32 mip = 0;

View File

@ -1408,8 +1408,11 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
LL_PROFILE_ZONE_NUM(height);
free_cur_tex_image();
#if 0
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
#if LL_DARWIN
{
LL_PROFILE_ZONE_NAMED("glTexImage2D alloc");
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
}
#else
// break up calls to a manageable size for the GL command buffer
{

View File

@ -117,7 +117,6 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixe
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
{
stop_glerror();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// Counterclockwise quad will face the viewer
@ -155,7 +154,6 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
gGL.vertex2i(left, top);
gGL.end();
}
stop_glerror();
}
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )

View File

@ -177,6 +177,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
if (!shader->attachVertexObject("deferred/textureUtilV.glsl"))
{
return FALSE;
}
///////////////////////////////////////
// Attach Fragment Shader Features Next
@ -685,7 +690,6 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n");
extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n");
extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n");
extra_code_text[extra_code_count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n");
if (major_version > 1 || minor_version >= 40)
{ //GLSL 1.40 replaces texture2DRect et al with texture
@ -1075,11 +1079,13 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_matrix3");
mReservedUniforms.push_back("object_plane_s");
mReservedUniforms.push_back("object_plane_t");
mReservedUniforms.push_back("texture_basecolor_matrix"); // GLTF
mReservedUniforms.push_back("texture_normal_matrix"); // GLTF
mReservedUniforms.push_back("texture_metallic_roughness_matrix"); // GLTF
mReservedUniforms.push_back("texture_emissive_matrix"); // GLTF
llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_MATRIX+1);
mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF)
mReservedUniforms.push_back("texture_normal_transform"); // (GLTF)
mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF)
mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF)
llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM+1);
mReservedUniforms.push_back("viewport");

View File

@ -52,10 +52,12 @@ public:
TEXTURE_MATRIX3, // "texture_matrix3"
OBJECT_PLANE_S, // "object_plane_s"
OBJECT_PLANE_T, // "object_plane_t"
TEXTURE_BASECOLOR_MATRIX, // "texture_basecolor_matrix" (GLTF)
TEXTURE_NORMAL_MATRIX, // "texture_normal_matrix" (GLTF)
TEXTURE_METALLIC_ROUGHNESS_MATRIX, // "texture_metallic_roughness_matrix" (GLTF)
TEXTURE_EMISSIVE_MATRIX, // "texture_emissive_matrix" (GLTF)
TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF)
TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF)
TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF)
TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF)
VIEWPORT, // "viewport"
LIGHT_POSITION, // "light_position"
LIGHT_DIRECTION, // "light_direction"

View File

@ -1390,7 +1390,7 @@ void LLVertexBuffer::setBuffer()
U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
// this Vertex Buffer must provide all necessary attributes for currently bound shader
llassert(((~data_mask & mTypeMask) > 0) || (mTypeMask == data_mask));
llassert((data_mask & mTypeMask) == data_mask);
if (sGLRenderBuffer != mGLBuffer)
{

View File

@ -23,6 +23,7 @@
<string>RenderDeferredSSAO</string>
<string>RenderDepthOfField</string>
<string>RenderDepthOfFieldInEditMode</string>
<string>RenderExposure</string>
<string>RenderFarClip</string>
<string>RenderFlexTimeFactor</string>
<string>RenderFSAASamples</string>
@ -41,6 +42,7 @@
<string>RenderTerrainDetail</string>
<string>RenderTerrainLODFactor</string>
<string>RenderTerrainScale</string>
<string>RenderTonemapper</string>
<string>RenderTreeLODFactor</string>
<string>RenderTransparentWater</string>
<string>RenderUnloadedAvatar</string>

View File

@ -13462,7 +13462,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>256</integer>
<integer>128</integer>
</map>
<key>RenderReflectionProbeAmbianceScale</key>
<map>
@ -13473,9 +13473,31 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>8</integer>
<real>8</real>
</map>
<key>RenderTonemapper</key>
<map>
<key>Comment</key>
<string>Which tone mapping function to use (0 - Linear, 1 - ACES Narkowicz, 2 - ACES Hill)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>1</real>
</map>
<key>RenderExposure</key>
<map>
<key>Comment</key>
<string>Exposure value to send to tonemapper.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1</real>
</map>
<key>RenderReflectionProbeDrawDistance</key>
<map>
<key>Comment</key>
@ -13485,7 +13507,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>64</real>
<integer>64</integer>
</map>
<key>RenderReflectionProbeAmbiance</key>
<map>

View File

@ -52,9 +52,6 @@ VARYING vec2 vary_texcoord2;
VARYING vec2 vary_texcoord3;
VARYING float altitude_blend_factor;
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light);
vec4 cloudNoise(vec2 uv)
{
vec4 a = texture2D(cloud_noise_texture, uv);
@ -119,7 +116,6 @@ void main()
color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
color.rgb= max(vec3(0), color.rgb);
color.rgb *= 2.0;
color.rgb = scaleSoftClip(color.rgb);
/// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, alpha1);

View File

@ -74,7 +74,6 @@ const float ONE_OVER_PI = 0.3183098861;
vec3 srgb_to_linear(vec3 cs);
vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
vec3 scaleSoftClipFragLinear(vec3 light);
float calcLegacyDistanceAttenuation(float distance, float falloff)
{
@ -383,7 +382,8 @@ vec3 pbrIbl(vec3 diffuseColor,
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv, // normal dot view vector
float perceptualRough)
float perceptualRough,
out vec3 specContrib)
{
// retrieve a scale and bias to F0. See [1], Figure 3
vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough);
@ -393,9 +393,24 @@ vec3 pbrIbl(vec3 diffuseColor,
vec3 diffuse = diffuseLight * diffuseColor;
vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
return (diffuse + specular*0.5) * ao; //reduce by half to place in appropriate color space for atmospherics
specContrib = specular * ao;
return (diffuse + specular) * ao;
}
vec3 pbrIbl(vec3 diffuseColor,
vec3 specularColor,
vec3 radiance, // radiance map sample
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv, // normal dot view vector
float perceptualRough)
{
vec3 specContrib;
return pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, nv, perceptualRough, specContrib);
}
// Encapsulate the various inputs used by the various functions in the shading equation
// We store values in this struct to simplify the integration of alternative implementations
// of the shading terms, outlined in the Readme.MD Appendix.
@ -460,7 +475,8 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l) //surface point to light
vec3 l, //surface point to light
out vec3 specContrib) //specular contribution (exposed to alpha shaders to calculate "glare")
{
// make sure specular highlights from punctual lights don't fall off of polished surfaces
perceptualRoughness = max(perceptualRoughness, 8.0/255.0);
@ -506,17 +522,30 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float G = geometricOcclusion(pbrInputs);
float D = microfacetDistribution(pbrInputs);
const vec3 u_LightColor = vec3(1.0);
// Calculation of analytical lighting contribution
vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV);
specContrib = F * G * D / (4.0 * NdotL * NdotV);
// Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);
vec3 color = NdotL * (diffuseContrib + specContrib);
specContrib *= NdotL;
specContrib = max(specContrib, vec3(0));
return color;
}
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l) //surface point to light
{
vec3 specContrib;
return pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n, v, l, specContrib);
}
void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor)
{
vec3 f0 = vec3(0.04);
@ -525,23 +554,30 @@ void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor
specularColor = mix(f0, baseColor, metallic);
}
vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten)
vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten, out vec3 specContrib)
{
vec3 color = vec3(0);
float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0);
color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, 0.2);
vec3 ibl_spec;
color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness, ibl_spec);
color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir)) * sunlit * 2.75 * scol;
color += colorEmissive*0.5;
color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir), specContrib) * sunlit * 2.75 * scol;
specContrib *= sunlit * 2.75 * scol;
specContrib += ibl_spec;
color = atmosFragLightingLinear(color, additive, atten);
color = scaleSoftClipFragLinear(color);
color += colorEmissive;
return color;
}
vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten)
{
vec3 specContrib;
return pbrBaseLight(diffuseColor, specularColor, metallic, v, norm, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten, specContrib);
}
uniform vec4 waterPlane;
uniform float waterSign;

View File

@ -27,14 +27,9 @@
/*[EXTRA_CODE_HERE]*/
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
vec3 fullbrightAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
@ -46,8 +41,6 @@ void main()
vec4 color = diffuseLookup(vary_texcoord0.xy)*vertex_color;
color.rgb = fullbrightAtmosTransport(color.rgb);
color.rgb = fullbrightScaleSoftClip(color.rgb);
frag_color = color;
}

View File

@ -100,8 +100,10 @@ void main()
#endif
#ifndef IS_HUD
color.rgb = fullbrightAtmosTransport(color.rgb);
color.rgb = srgb_to_linear(color.rgb);
#endif
frag_color.rgb = color.rgb;
frag_color.a = color.a;
}

View File

@ -0,0 +1,49 @@
/**
* @file materialF.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]*/
// debug stub
#define DIFFUSE_ALPHA_MODE_BLEND 1
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
out vec4 frag_color;
#else
out vec4 frag_data[3];
#endif
void main()
{
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
frag_color = vec4(0.5, 0, 1, 0.5);
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
frag_data[0] = vec4(0.5, 0, 1, 0); // gbuffer is sRGB for legacy materials
frag_data[1] = vec4(0); // XYZ = Specular color. W = Specular exponent.
frag_data[2] = vec4(0); // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
#endif
}

View File

@ -27,10 +27,10 @@ uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
in vec3 position;
in vec2 texcoord0;
VARYING vec2 vary_texcoord0;
out vec2 vary_texcoord0;
void main()
{

View File

@ -0,0 +1,33 @@
/**
* @file pbralphaF.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$
*/
// debug stub
out vec4 frag_color;
void main()
{
frag_color = vec4(1.0, 0, 0.5, 0.5);
}

View File

@ -44,15 +44,14 @@ uniform mat4 modelview_matrix;
out vec3 vary_position;
uniform mat3 texture_basecolor_matrix;
uniform mat3 texture_normal_matrix;
uniform mat3 texture_metallic_roughness_matrix;
uniform mat3 texture_emissive_matrix;
uniform vec4[2] texture_base_color_transform;
uniform vec4[2] texture_normal_transform;
uniform vec4[2] texture_metallic_roughness_transform;
uniform vec4[2] texture_emissive_transform;
#ifdef HAS_SUN_SHADOW
out vec3 vary_fragcoord;
uniform float near_clip;
#endif
in vec3 position;
in vec4 diffuse_color;
@ -60,7 +59,7 @@ in vec3 normal;
in vec4 tangent;
in vec2 texcoord0;
out vec2 basecolor_texcoord;
out vec2 base_color_texcoord;
out vec2 normal_texcoord;
out vec2 metallic_roughness_texcoord;
out vec2 emissive_texcoord;
@ -71,6 +70,8 @@ out vec3 vary_tangent;
flat out float vary_sign;
out vec3 vary_normal;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
void main()
{
@ -86,14 +87,12 @@ void main()
#endif
gl_Position = vert;
#ifdef HAS_SUN_SHADOW
vary_fragcoord.xyz = vert.xyz + vec3(0,0,near_clip);
#endif
basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
normal_texcoord = (texture_matrix0 * vec4(texture_normal_matrix * vec3(texcoord0,1), 1)).xy;
metallic_roughness_texcoord = (texture_matrix0 * vec4(texture_metallic_roughness_matrix * vec3(texcoord0,1), 1)).xy;
emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0);
metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_transform, texture_matrix0);
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0);
#ifdef HAS_SKIN
vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz;
@ -126,18 +125,21 @@ uniform mat4 modelview_matrix;
out vec3 vary_position;
uniform mat3 texture_basecolor_matrix;
uniform mat3 texture_emissive_matrix;
uniform vec4[2] texture_base_color_transform;
uniform vec4[2] texture_emissive_transform;
in vec3 position;
in vec4 diffuse_color;
in vec2 texcoord0;
out vec2 basecolor_texcoord;
out vec2 base_color_texcoord;
out vec2 emissive_texcoord;
out vec4 vertex_color;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
void main()
{
//transform vertex
@ -145,8 +147,8 @@ void main()
gl_Position = vert;
vary_position = vert.xyz;
basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0);
vertex_color = diffuse_color;
}

View File

@ -37,7 +37,7 @@ out vec4 frag_color;
in vec3 vary_position;
in vec4 vertex_emissive;
in vec2 basecolor_texcoord;
in vec2 base_color_texcoord;
in vec2 emissive_texcoord;
uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
@ -47,7 +47,7 @@ vec3 srgb_to_linear(vec3 c);
void main()
{
vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
vec4 basecolor = texture2D(diffuseMap, base_color_texcoord.xy).rgba;
if (basecolor.a < minimum_alpha)
{

View File

@ -34,19 +34,21 @@ uniform mat4 modelview_projection_matrix;
uniform mat4 texture_matrix0;
uniform mat3 texture_basecolor_matrix;
uniform mat3 texture_emissive_matrix;
uniform vec4[2] texture_base_color_transform;
uniform vec4[2] texture_emissive_transform;
in vec3 position;
in vec4 emissive;
in vec2 texcoord0;
out vec2 basecolor_texcoord;
out vec2 base_color_texcoord;
out vec2 emissive_texcoord;
out vec4 vertex_emissive;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
void main()
{
#ifdef HAS_SKIN
@ -62,8 +64,8 @@ void main()
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
#endif
basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0);
vertex_emissive = emissive;
}

View File

@ -47,7 +47,7 @@ in vec3 vary_normal;
in vec3 vary_tangent;
flat in float vary_sign;
in vec2 basecolor_texcoord;
in vec2 base_color_texcoord;
in vec2 normal_texcoord;
in vec2 metallic_roughness_texcoord;
in vec2 emissive_texcoord;
@ -62,7 +62,7 @@ uniform mat3 normal_matrix;
void main()
{
vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
vec4 basecolor = texture2D(diffuseMap, base_color_texcoord.xy).rgba;
if (basecolor.a < minimum_alpha)
{
discard;
@ -121,7 +121,7 @@ out vec4 frag_color;
in vec3 vary_position;
in vec4 vertex_color;
in vec2 basecolor_texcoord;
in vec2 base_color_texcoord;
in vec2 emissive_texcoord;
uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
@ -131,7 +131,7 @@ vec3 srgb_to_linear(vec3 c);
void main()
{
vec4 basecolor = texture2D(diffuseMap, basecolor_texcoord.xy).rgba;
vec4 basecolor = texture2D(diffuseMap, base_color_texcoord.xy).rgba;
if (basecolor.a < minimum_alpha)
{
discard;

View File

@ -38,10 +38,10 @@ uniform mat4 modelview_projection_matrix;
#endif
uniform mat4 texture_matrix0;
uniform mat3 texture_basecolor_matrix;
uniform mat3 texture_normal_matrix;
uniform mat3 texture_metallic_roughness_matrix;
uniform mat3 texture_emissive_matrix;
uniform vec4[2] texture_base_color_transform;
uniform vec4[2] texture_normal_transform;
uniform vec4[2] texture_metallic_roughness_transform;
uniform vec4[2] texture_emissive_transform;
in vec3 position;
in vec4 diffuse_color;
@ -49,7 +49,7 @@ in vec3 normal;
in vec4 tangent;
in vec2 texcoord0;
out vec2 basecolor_texcoord;
out vec2 base_color_texcoord;
out vec2 normal_texcoord;
out vec2 metallic_roughness_texcoord;
out vec2 emissive_texcoord;
@ -60,6 +60,8 @@ out vec3 vary_tangent;
flat out float vary_sign;
out vec3 vary_normal;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
void main()
{
#ifdef HAS_SKIN
@ -75,11 +77,11 @@ void main()
//transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
#endif
basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
normal_texcoord = (texture_matrix0 * vec4(texture_normal_matrix * vec3(texcoord0,1), 1)).xy;
metallic_roughness_texcoord = (texture_matrix0 * vec4(texture_metallic_roughness_matrix * vec3(texcoord0,1), 1)).xy;
emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0);
metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_transform, texture_matrix0);
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0);
#ifdef HAS_SKIN
vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz;
@ -104,27 +106,29 @@ uniform mat4 modelview_projection_matrix;
uniform mat4 texture_matrix0;
uniform mat3 texture_basecolor_matrix;
uniform mat3 texture_normal_matrix;
uniform mat3 texture_metallic_roughness_matrix;
uniform mat3 texture_emissive_matrix;
uniform vec4[2] texture_base_color_transform;
uniform vec4[2] texture_normal_transform;
uniform vec4[2] texture_metallic_roughness_transform;
uniform vec4[2] texture_emissive_transform;
in vec3 position;
in vec4 diffuse_color;
in vec2 texcoord0;
out vec2 basecolor_texcoord;
out vec2 base_color_texcoord;
out vec2 emissive_texcoord;
out vec4 vertex_color;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
void main()
{
//transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
basecolor_texcoord = (texture_matrix0 * vec4(texture_basecolor_matrix * vec3(texcoord0,1), 1)).xy;
emissive_texcoord = (texture_matrix0 * vec4(texture_emissive_matrix * vec3(texcoord0,1), 1)).xy;
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0);
vertex_color = diffuse_color;
}

View File

@ -41,6 +41,95 @@ uniform float display_gamma;
vec3 linear_to_srgb(vec3 cl);
//===============================================================
// tone mapping taken from Khronos sample implementation
//===============================================================
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
const mat3 ACESInputMat = mat3
(
0.59719, 0.07600, 0.02840,
0.35458, 0.90834, 0.13383,
0.04823, 0.01566, 0.83777
);
// ODT_SAT => XYZ => D60_2_D65 => sRGB
const mat3 ACESOutputMat = mat3
(
1.60475, -0.10208, -0.00327,
-0.53108, 1.10813, -0.07276,
-0.07367, -0.00605, 1.07602
);
// ACES tone map (faster approximation)
// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
vec3 toneMapACES_Narkowicz(vec3 color)
{
const float A = 2.51;
const float B = 0.03;
const float C = 2.43;
const float D = 0.59;
const float E = 0.14;
return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
}
// ACES filmic tone map approximation
// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
vec3 RRTAndODTFit(vec3 color)
{
vec3 a = color * (color + 0.0245786) - 0.000090537;
vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
return a / b;
}
// tone mapping
vec3 toneMapACES_Hill(vec3 color)
{
color = ACESInputMat * color;
// Apply RRT and ODT
color = RRTAndODTFit(color);
color = ACESOutputMat * color;
// Clamp to [0, 1]
color = clamp(color, 0.0, 1.0);
return color;
}
uniform float exposure;
uniform float gamma;
vec3 toneMap(vec3 color)
{
color *= exposure;
#ifdef TONEMAP_ACES_NARKOWICZ
color = toneMapACES_Narkowicz(color);
#endif
#ifdef TONEMAP_ACES_HILL
color = toneMapACES_Hill(color);
#endif
#ifdef TONEMAP_ACES_HILL_EXPOSURE_BOOST
// boost exposure as discussed in https://github.com/mrdoob/three.js/pull/19621
// this factor is based on the exposure correction of Krzysztof Narkowicz in his
// implemetation of ACES tone mapping
color *= 1.0/0.6;
//color /= 0.6;
color = toneMapACES_Hill(color);
#endif
return linear_to_srgb(color);
}
//===============================================================
//=================================
// borrowed noise from:
// <https://www.shadertoy.com/view/4dS3Wd>
@ -79,16 +168,26 @@ float noise(vec2 x) {
//=============================
vec3 legacyGamma(vec3 color)
{
color = 1. - clamp(color, vec3(0.), vec3(1.));
color = 1. - pow(color, vec3(gamma)); // s/b inverted already CPU-side
return color;
}
void main()
{
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
vec4 diff = texture2D(diffuseRect, vary_fragcoord);
diff.rgb = linear_to_srgb(diff.rgb);
vec2 tc = vary_fragcoord.xy*screen_res;
diff.rgb = toneMap(diff.rgb);
diff.rgb = legacyGamma(diff.rgb);
vec2 tc = vary_fragcoord.xy*screen_res*4.0;
vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
diff.rgb += nz*0.008;
diff.rgb += nz*0.003;
//diff.rgb = nz;
frag_color = diff;
}

View File

@ -59,12 +59,12 @@ float pcfShadow(sampler2DShadow shadowMap, vec3 norm, vec4 stc, float bias_mul,
stc.xyz /= stc.w;
stc.z += offset * 2.0;
stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*shadow_res.y))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
float cs = shadow2D(shadowMap, stc.xyz).x;
float cs = texture(shadowMap, stc.xyz);
float shadow = cs * 4.0;
shadow += shadow2D(shadowMap, stc.xyz+vec3( 1.5/shadow_res.x, 0.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3( 0.5/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.5/shadow_res.x, -0.5/shadow_res.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-0.5/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
shadow += texture(shadowMap, stc.xyz+vec3( 1.5/shadow_res.x, 0.5/shadow_res.y, 0.0));
shadow += texture(shadowMap, stc.xyz+vec3( 0.5/shadow_res.x, -1.5/shadow_res.y, 0.0));
shadow += texture(shadowMap, stc.xyz+vec3(-1.5/shadow_res.x, -0.5/shadow_res.y, 0.0));
shadow += texture(shadowMap, stc.xyz+vec3(-0.5/shadow_res.x, 1.5/shadow_res.y, 0.0));
return clamp(shadow * 0.125, 0.0, 1.0);
#else
return 1.0;
@ -78,16 +78,16 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2
stc.z += spot_shadow_bias * bias_scale;
stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
float cs = shadow2D(shadowMap, stc.xyz).x;
float cs = texture(shadowMap, stc.xyz);
float shadow = cs;
vec2 off = 1.0/proj_shadow_res;
off.y *= 1.5;
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
shadow += texture(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0));
shadow += texture(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0));
shadow += texture(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0));
shadow += texture(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0));
return shadow*0.2;
#else
return 1.0;

View File

@ -0,0 +1,78 @@
/**
* @file class1/deferred/textureUtilV.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$
*/
// This shader code is taken from the sample code on the KHR_texture_transform
// spec page page, plus or minus some sign error corrections (I think because the GLSL
// matrix constructor is backwards?):
// https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform
// Previously (6494eed242b1), we passed in a single, precalculated matrix
// uniform per transform into the shaders. However, that was found to produce
// small-but-noticeable discrepancies with the GLTF sample model
// "TextureTransformTest", likely due to numerical precision differences. In
// the interest of parity with other renderers, calculate the transform
// directly in the shader. -Cosmic,2023-02-24
vec2 khr_texture_transform(vec2 texcoord, vec2 scale, float rotation, vec2 offset)
{
mat3 scale_mat = mat3(scale.x,0,0, 0,scale.y,0, 0,0,1);
mat3 offset_mat = mat3(1,0,0, 0,1,0, offset.x, offset.y, 1);
mat3 rotation_mat = mat3(
cos(rotation),-sin(rotation), 0,
sin(rotation), cos(rotation), 0,
0, 0, 1
);
mat3 transform = offset_mat * rotation_mat * scale_mat;
return (transform * vec3(texcoord, 1)).xy;
}
// vertex_texcoord - The UV texture coordinates sampled from the vertex at
// runtime. Per SL convention, this is in a right-handed UV coordinate
// system. Collada models also have right-handed UVs.
// khr_gltf_transform - The texture transform matrix as defined in the
// KHR_texture_transform GLTF extension spec. It assumes a left-handed UV
// coordinate system. GLTF models also have left-handed UVs.
// sl_animation_transform - The texture transform matrix for texture
// animations, available through LSL script functions such as
// LlSetTextureAnim. It assumes a right-handed UV coordinate system.
// texcoord - The final texcoord to use for image sampling
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform)
{
vec2 texcoord = vertex_texcoord;
// 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.
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
texcoord.y = 1.0 - texcoord.y;
// To make things more confusing, all SL image assets are upside-down
// We may need an additional sign flip here when we implement a Vulkan backend
return texcoord;
}

View File

@ -33,6 +33,7 @@ uniform float waterFogKS;
vec3 getPositionEye();
vec3 srgb_to_linear(vec3 col);
vec3 linear_to_srgb(vec3 col);
vec4 applyWaterFogView(vec3 pos, vec4 color)
{
@ -68,48 +69,16 @@ vec4 applyWaterFogView(vec3 pos, vec4 color)
float D = pow(0.98, l*kd);
color.rgb = color.rgb * D + kc.rgb * L;
color.a = kc.a + color.a;
return color;
}
vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color, vec3 sunlit)
{
vec3 view = normalize(pos);
//normalize view vector
float es = -(dot(view, waterPlane.xyz));
//find intersection point with water plane and eye vector
//get eye depth
float e0 = max(-waterPlane.w, 0.0);
vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w / es : vec3(0.0, 0.0, 0.0);
//get object depth
float depth = length(pos - int_v);
//get "thickness" of water
float l = max(depth, 0.1);
float kd = waterFogDensity;
float ks = waterFogKS;
vec4 kc = waterFogColor;
kc.rgb = srgb_to_linear(kc.rgb); // TODO -- pass in waterFogColor linear
kc.rgb *= sunlit;
float F = 0.98;
float t1 = -kd * pow(F, ks * e0);
float t2 = kd + ks * es;
float t3 = pow(F, t2 * l) - 1.0;
float L = min(t1 / t2 * t3, 1.0);
float D = pow(0.98, l * kd);
color.rgb = color.rgb * D + kc.rgb * L;
color.rgb = linear_to_srgb(color.rgb);
color = applyWaterFogView(pos, color);
color.rgb = srgb_to_linear(color.rgb);
return color;
}

View File

@ -0,0 +1,53 @@
/**
* @file gaussianF.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;
uniform sampler2D diffuseRect;
uniform float resScale;
// texture direction, will be <1, 0> or <0, 1>
uniform vec2 direction;
in vec2 vary_texcoord0;
// get linear depth value given a depth buffer sample d and znear and zfar values
float linearDepth(float d, float znear, float zfar);
void main()
{
vec3 col = vec3(0,0,0);
float w[9] = float[9]( 0.0002, 0.0060, 0.0606, 0.2417, 0.3829, 0.2417, 0.0606, 0.0060, 0.0002 );
for (int i = 0; i < 9; ++i)
{
vec2 tc = vary_texcoord0 + (i-4)*direction*resScale;
col += texture(diffuseRect, tc).rgb * w[i];
}
frag_color = vec4(col, 0.0);
}

View File

@ -127,14 +127,11 @@ vec4 prefilterEnvMap(vec3 R)
vec3 V = R;
vec4 color = vec4(0.0);
float totalWeight = 0.0;
float envMapDim = u_width;
int numSamples = 4;
float numMips = max_probe_lod;
float envMapDim = float(textureSize(reflectionProbes, 0).s);
float roughness = mipLevel/max_probe_lod;
int numSamples = max(int(32*roughness), 1);
float roughness = mipLevel/numMips;
numSamples = max(int(numSamples*roughness), 1);
float numMips = max_probe_lod+1;
for(uint i = 0u; i < numSamples; i++) {
vec2 Xi = hammersley2d(i, numSamples);
@ -154,11 +151,9 @@ vec4 prefilterEnvMap(vec3 R)
// Solid angle of 1 pixel across all cube faces
float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
// Biased (+1.0) mip level for better result
float mip = roughness == 0.0 ? 0.0 : clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, numMips);
//float mip = clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, 7.f);
color += textureLod(reflectionProbes, vec4(L,sourceIdx), mip) * dotNL;
float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
color += textureLod(reflectionProbes, vec4(L, sourceIdx), mipLevel) * dotNL;
totalWeight += dotNL;
}
}
return (color / totalWeight);

View File

@ -23,78 +23,14 @@
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
/*[EXTRA_CODE_HERE]*/
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
// NOTE screenMap should always be texture channel 0 and
// depthmap should always be channel 1
uniform sampler2D diffuseRect;
uniform sampler2D depthMap;
uniform float resScale;
uniform float znear;
uniform float zfar;
VARYING vec2 vary_texcoord0;
// get linear depth value given a depth buffer sample d and znear and zfar values
float linearDepth(float d, float znear, float zfar);
in vec2 vary_texcoord0;
void main()
{
#if 0
float w[9];
float c = 1.0/16.0; //corner weight
float e = 1.0/8.0; //edge weight
float m = 1.0/4.0; //middle weight
//float wsum = c*4+e*4+m;
w[0] = c; w[1] = e; w[2] = c;
w[3] = e; w[4] = m; w[5] = e;
w[6] = c; w[7] = e; w[8] = c;
vec2 tc[9];
float ed = 1;
float cd = 1;
tc[0] = vec2(-cd, cd); tc[1] = vec2(0, ed); tc[2] = vec2(cd, cd);
tc[3] = vec2(-ed, 0); tc[4] = vec2(0, 0); tc[5] = vec2(ed, 0);
tc[6] = vec2(-cd, -cd); tc[7] = vec2(0, -ed); tc[8] = vec2(cd, -1);
vec3 color = vec3(0,0,0);
for (int i = 0; i < 9; ++i)
{
color += texture2D(screenMap, vary_texcoord0.xy+tc[i]).rgb * w[i];
//color += texture2D(screenMap, vary_texcoord0.xy+tc[i]*2.0).rgb * w[i]*0.5;
}
//color /= wsum;
frag_color = vec4(color, 1.0);
#else
float depth = texture(depthMap, vary_texcoord0.xy).r;
float dist = linearDepth(depth, znear, zfar);
// convert linear depth to distance
vec3 v;
v.xy = vary_texcoord0.xy / 512.0 * 2.0 - 1.0;
v.z = 1.0;
v = normalize(v);
dist /= v.z;
vec3 col = texture2D(diffuseRect, vary_texcoord0.xy).rgb;
frag_color = vec4(col, dist/256.0);
#endif
vec3 col = texture(diffuseRect, vary_texcoord0.xy).rgb;
frag_color = vec4(col, 0.0);
}

View File

@ -25,17 +25,13 @@
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
ATTRIBUTE vec4 diffuse_color;
in vec3 position;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
out vec2 vary_texcoord0;
void main()
{
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_texcoord0 = texcoord0;
vertex_color = diffuse_color;
vary_texcoord0 = position.xy*0.5+0.5;
}

View File

@ -250,6 +250,9 @@ void main()
calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
vec3 sunlit_linear = srgb_to_linear(sunlit);
vec3 amblit_linear = amblit;
vec3 irradiance;
vec3 glossenv;
vec3 legacyenv;
@ -266,7 +269,7 @@ void main()
color.a = final_alpha;
vec3 sun_contrib = min(final_da, shadow) * sunlit;
vec3 sun_contrib = min(final_da, shadow) * sunlit_linear;
color.rgb = max(amblit, irradiance);
@ -274,8 +277,10 @@ void main()
color.rgb *= diffuse_linear.rgb;
color.rgb = linear_to_srgb(color.rgb);
color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
color.rgb = scaleSoftClipFragLinear(color.rgb);
color.rgb = srgb_to_linear(color.rgb);
vec4 light = vec4(0,0,0,0);
@ -294,8 +299,9 @@ void main()
color.rgb += light.rgb;
#endif // !defined(LOCAL_LIGHT_KILL)
#ifdef WATER_FOG
color = applyWaterFogViewLinear(pos.xyz, color, sunlit);
color = applyWaterFogViewLinear(pos.xyz, color, sunlit_linear);
#endif // WATER_FOG
#endif // #else // FOR_IMPOSTOR
@ -303,6 +309,7 @@ void main()
#ifdef IS_HUD
color.rgb = linear_to_srgb(color.rgb);
#endif
frag_color = color;
}

View File

@ -46,14 +46,15 @@ uniform vec3 moon_dir;
out vec4 frag_color;
in vec3 vary_fragcoord;
#ifdef HAS_SUN_SHADOW
in vec3 vary_fragcoord;
uniform vec2 screen_res;
#endif
in vec3 vary_position;
in vec2 basecolor_texcoord;
in vec2 base_color_texcoord;
in vec2 normal_texcoord;
in vec2 metallic_roughness_texcoord;
in vec2 emissive_texcoord;
@ -81,6 +82,8 @@ vec3 srgb_to_linear(vec3 c);
vec3 linear_to_srgb(vec3 c);
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
vec3 atmosFragLightingLinear(vec3 color, vec3 additive, vec3 atten);
vec3 scaleSoftClipFragLinear(vec3 color);
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
@ -106,16 +109,16 @@ vec3 pbrBaseLight(vec3 diffuseColor,
vec3 colorEmissive,
float ao,
vec3 additive,
vec3 atten);
vec3 atten,
out vec3 specContrib);
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
vec2 BRDF(float NoV, float roughness);
vec3 l, //surface point to light
out vec3 specContrib);
vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
@ -126,7 +129,7 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
vec3 lp, // light position
vec3 ld, // light direction (for spotlights)
vec3 lightColor,
float lightSize, float falloff, float is_pointlight, float ambiance)
float lightSize, float falloff, float is_pointlight, inout float glare, float ambiance)
{
vec3 color = vec3(0,0,0);
@ -148,7 +151,10 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
vec3 intensity = spot_atten * dist_atten * lightColor * 3.0;
color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
vec3 speccol;
color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv, speccol);
speccol *= intensity;
glare += max(max(speccol.r, speccol.g), speccol.b);
}
return color;
@ -157,13 +163,14 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
void main()
{
vec3 color = vec3(0,0,0);
float glare = 0.0;
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
vec3 pos = vary_position;
waterClip(pos);
vec4 basecolor = texture(diffuseMap, basecolor_texcoord.xy).rgba;
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
basecolor.rgb = srgb_to_linear(basecolor.rgb);
#ifdef HAS_ALPHA_MASK
if (basecolor.a < minimum_alpha)
@ -191,8 +198,11 @@ void main()
vec3 atten;
calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
#ifdef HAS_SUN_SHADOW
vec3 sunlit_linear = srgb_to_linear(sunlit);
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
#ifdef HAS_SUN_SHADOW
scol = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
#endif
@ -211,7 +221,7 @@ void main()
float gloss = 1.0 - perceptualRoughness;
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
sampleReflectionProbes(irradiance, radiance, vec2(0), pos.xyz, norm.xyz, gloss);
sampleReflectionProbes(irradiance, radiance, vary_position.xy*0.5+0.5, pos.xyz, norm.xyz, gloss);
// Take maximium of legacy ambient vs irradiance sample as irradiance
// NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here
irradiance = max(amblit,irradiance);
@ -222,15 +232,19 @@ void main()
vec3 v = -normalize(pos.xyz);
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
vec3 spec;
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten, spec);
glare += max(max(spec.r, spec.g), spec.b);
float nv = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0);
vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRoughness);
color.rgb = linear_to_srgb(color.rgb);
color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
color.rgb = scaleSoftClipFragLinear(color.rgb);
color.rgb = srgb_to_linear(color.rgb);
vec3 light = vec3(0);
// Punctual lights
#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w);
LIGHT_LOOP(1)
LIGHT_LOOP(2)
@ -244,11 +258,10 @@ void main()
float a = basecolor.a*vertex_color.a;
vec3 spec = radiance; // *specularColor;
float lum = max(max(spec.r, spec.g), spec.b);
float f = brdf.y;
a += f;
glare = min(glare, 1.0);
a = max(a, glare);
frag_color = vec4(color.rgb,a);
}
@ -263,7 +276,7 @@ out vec4 frag_color;
in vec3 vary_position;
in vec2 basecolor_texcoord;
in vec2 base_color_texcoord;
in vec2 emissive_texcoord;
in vec4 vertex_color;
@ -282,7 +295,7 @@ void main()
vec3 pos = vary_position;
vec4 basecolor = texture(diffuseMap, basecolor_texcoord.xy).rgba;
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
basecolor.rgb = srgb_to_linear(basecolor.rgb);
#ifdef HAS_ALPHA_MASK
if (basecolor.a < minimum_alpha)

View File

@ -34,7 +34,7 @@ uniform mat3 env_mat;
vec3 srgb_to_linear(vec3 c);
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
vec2 tc, vec3 pos, vec3 norm, float glossiness)
{
ambenv = vec3(reflection_probe_ambiance * 0.25);
@ -43,11 +43,10 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
glossenv = srgb_to_linear(textureCube(environmentMap, env_vec).rgb);
}
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness)
void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness)
{
sampleReflectionProbes(ambenv, glossenv,
tc, pos, norm, glossiness, false);
sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness);
}
vec4 sampleReflectionProbesDebug(vec3 pos)

View File

@ -176,7 +176,6 @@ float computeLod(float pdf)
vec4 filterColor(vec3 N)
{
//return textureLod(uCubeMap, N, 3.0).rgb;
vec4 color = vec4(0.f);
for(int i = 0; i < u_sampleCount; ++i)
@ -192,7 +191,7 @@ vec4 filterColor(vec3 N)
// apply the bias to the lod
lod += u_lodBias;
lod = clamp(lod, 0, 7);
lod = clamp(lod, 0, max_probe_lod);
// sample lambertian at a lower resolution to avoid fireflies
vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod);

View File

@ -33,8 +33,8 @@ vec3 linear_to_srgb(vec3 col);
vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
{
light *= atten.r;
light += additive;
return light * 2.0;
light += additive * 2.0;
return light;
}
vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten)

View File

@ -137,12 +137,15 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb);
// brightness of surface both sunlight and ambient
sunlit = sunlight.rgb;
amblit = tmpAmbient.rgb;
// fudge sunlit and amblit to get consistent lighting compared to legacy
// midday before PBR was a thing
sunlit = sunlight.rgb * 0.7;
amblit = tmpAmbient.rgb * 0.25;
additive *= vec3(1.0 - combined_haze);
}
vec3 srgb_to_linear(vec3 col);
// provide a touch of lighting in the opposite direction of the sun light
@ -150,21 +153,24 @@ vec3 srgb_to_linear(vec3 col);
float ambientLighting(vec3 norm, vec3 light_dir)
{
float ambient = min(abs(dot(norm.xyz, light_dir.xyz)), 1.0);
ambient *= 0.56;
ambient *= 0.5;
ambient *= ambient;
ambient = (1.0 - ambient);
return ambient;
}
// return colors in linear space
// return lit amblit in linear space, leave sunlit and additive in sRGB space
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive,
out vec3 atten)
{
calcAtmosphericVars(inPositionEye, light_dir, 1.0, sunlit, amblit, additive, atten, false);
sunlit = srgb_to_linear(sunlit);
additive = srgb_to_linear(additive);
amblit = ambient_linear;
// multiply by 2 to get same colors as when the "scaleSoftClip" implementation was doubling color values
// (allows for mixing of light sources other than sunlight e.g. reflection probes)
sunlit *= 2.0;
amblit *= 2.0;
amblit *= ambientLighting(norm, light_dir);
amblit = srgb_to_linear(amblit);
}

View File

@ -22,43 +22,34 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform float gamma;
vec3 getAtmosAttenuation();
vec3 getAdditiveColor();
// DEPRECATED
vec3 srgb_to_linear(vec3 col);
vec3 linear_to_srgb(vec3 col);
vec3 scaleSoftClipFragLinear(vec3 light)
{ // identical to non-linear version and that's probably close enough
//soft clip effect:
light = 1. - clamp(light, vec3(0.), vec3(1.));
light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side
return light;
}
//soft clip effect has been moved to postDeferredGammaCorrect legacyGamma, this file is effectively dead
// but these functions need to be removed from all existing shaders before removing this file
vec3 scaleSoftClipFrag(vec3 light)
{
//soft clip effect:
light = 1. - clamp(light, vec3(0.), vec3(1.));
light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side
return light;
}
vec3 scaleSoftClipFragLinear(vec3 light)
{ // identical to non-linear version and that's probably close enough
return light;
}
vec3 scaleSoftClip(vec3 light)
{
return scaleSoftClipFrag(light);
return light;
}
vec3 fullbrightScaleSoftClipFrag(vec3 light, vec3 add, vec3 atten)
{
//return mix(scaleSoftClipFrag(light.rgb), add, atten);
return scaleSoftClipFrag(light.rgb);
return light;
}
vec3 fullbrightScaleSoftClip(vec3 light)
{
return fullbrightScaleSoftClipFrag(light, getAdditiveColor(), getAtmosAttenuation());
return light;
}

View File

@ -48,23 +48,27 @@ vec3 atmosTransport(vec3 light)
vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten)
{
// same as non-linear version, probably fine
float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;
return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
//float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;
//return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
return atmosTransportFrag(light, additive, atten);
}
vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
{
float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;
return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
//float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;
//return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
return atmosTransportFrag(light, additive, atten);
}
vec3 fullbrightAtmosTransport(vec3 light)
{
return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
//return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
return atmosTransport(light);
}
vec3 fullbrightShinyAtmosTransport(vec3 light)
{
float brightness = dot(light.rgb, vec3(0.33333));
return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
//float brightness = dot(light.rgb, vec3(0.33333));
//return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
return atmosTransport(light);
}

View File

@ -92,7 +92,7 @@ uniform vec3 light_diffuse[8];
float getAmbientClamp();
void waterClip(vec3 pos);
vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
{
// SL-14895 inverted attenuation work-around
// This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
@ -170,6 +170,11 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe
vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
speccol = clamp(speccol, vec3(0), vec3(1));
col += speccol;
float cur_glare = max(speccol.r, speccol.g);
cur_glare = max(cur_glare, speccol.b);
glare = max(glare, speccol.r);
glare += max(cur_glare, 0.0);
}
}
}
@ -218,83 +223,105 @@ VARYING vec2 vary_texcoord0;
vec2 encode_normal(vec3 n);
void main()
// get the transformed normal and apply glossiness component from normal map
vec3 getNormal(inout float glossiness)
{
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
waterClip(vary_position.xyz);
#endif
vec2 pos_screen = vary_texcoord0.xy;
vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
diffcol.rgb *= vertex_color.rgb;
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
// Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
float bias = 0.001953125; // 1/512, or half an 8-bit quantization
if (diffcol.a < minimum_alpha-bias)
{
discard;
}
#ifdef HAS_NORMAL_MAP
vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
glossiness *= norm.a;
norm.xyz = norm.xyz * 2 - 1;
return normalize(vec3(dot(norm.xyz,vary_mat0),
dot(norm.xyz,vary_mat1),
dot(norm.xyz,vary_mat2)));
#else
return normalize(vary_normal);
#endif
}
vec4 getSpecular()
{
#ifdef HAS_SPECULAR_MAP
vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
spec.rgb *= specular_color.rgb;
#else
vec4 spec = vec4(specular_color.rgb, 1.0);
#endif
return spec;
}
#ifdef HAS_NORMAL_MAP
vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
norm.xyz = norm.xyz * 2 - 1;
vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
dot(norm.xyz,vary_mat1),
dot(norm.xyz,vary_mat2));
#else
vec4 norm = vec4(0,0,0,1.0);
vec3 tnorm = vary_normal;
void alphaMask(float alpha)
{
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
// Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
float bias = 0.001953125; // 1/512, or half an 8-bit quantization
if (alpha < minimum_alpha-bias)
{
discard;
}
#endif
}
norm.xyz = normalize(tnorm.xyz);
void waterClip()
{
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
waterClip(vary_position.xyz);
#endif
}
float getEmissive(vec4 diffcol)
{
#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
return emissive_brightness;
#else
return max(diffcol.a, emissive_brightness);
#endif
}
float getShadow(vec3 pos, vec3 norm)
{
#ifdef HAS_SUN_SHADOW
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
return sampleDirectionalShadow(pos, norm, vary_texcoord0.xy);
#else
return 1;
#endif
#else
return 1;
#endif
}
void main()
{
waterClip();
// diffcol == diffuse map combined with vertex color
vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
diffcol.rgb *= vertex_color.rgb;
alphaMask(diffcol.a);
// spec == specular map combined with specular color
vec4 spec = getSpecular();
float env = env_intensity * spec.a;
float glossiness = specular_color.a;
vec3 norm = getNormal(glossiness);
vec2 abnormal = encode_normal(norm.xyz);
vec4 final_color = diffcol;
#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
final_color.a = emissive_brightness;
#else
final_color.a = max(final_color.a, emissive_brightness);
#endif
vec4 final_specular = spec;
#ifdef HAS_SPECULAR_MAP
vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, GBUFFER_FLAG_HAS_ATMOS);
final_specular.a = specular_color.a * norm.a;
#else
vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, GBUFFER_FLAG_HAS_ATMOS);
final_specular.a = specular_color.a;
#endif
float emissive = getEmissive(diffcol);
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
//forward rendering, output lit linear color
diffcol.rgb = srgb_to_linear(diffcol.rgb);
final_specular.rgb = srgb_to_linear(final_specular.rgb);
spec.rgb = srgb_to_linear(spec.rgb);
vec3 pos = vary_position;
float shadow = 1.0f;
float shadow = getShadow(pos, norm);
#ifdef HAS_SUN_SHADOW
shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
#endif
vec4 diffuse = final_color;
vec4 diffuse = diffcol;
vec3 color = vec3(0,0,0);
@ -307,54 +334,63 @@ void main()
vec3 atten;
calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
vec3 sunlit_linear = srgb_to_linear(sunlit);
vec3 amblit_linear = amblit;
vec3 ambenv;
vec3 glossenv;
vec3 legacyenv;
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos_screen, pos.xyz, norm.xyz, final_specular.a, env_intensity);
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xy*0.5+0.5, pos.xyz, norm.xyz, glossiness, env);
// use sky settings ambient or irradiance map sample, whichever is brighter
color = max(amblit, ambenv);
color = max(amblit_linear, ambenv);
float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
vec3 sun_contrib = min(da, shadow) * sunlit;
vec3 sun_contrib = min(da, shadow) * sunlit_linear;
color.rgb += sun_contrib;
color *= diffcol.rgb;
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
if (final_specular.a > 0.0) // specular reflection
float glare = 0.0;
if (glossiness > 0.0) // specular reflection
{
float sa = dot(normalize(refnormpersp), light_dir.xyz);
vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, final_specular.a)).r);
vec3 dumbshiny = sunlit_linear * shadow * (texture2D(lightFunc, vec2(sa, glossiness)).r);
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * final_specular.rgb;
vec3 spec_contrib = dumbshiny * spec.rgb;
bloom = dot(spec_contrib, spec_contrib) / 6;
glare = max(spec_contrib.r, spec_contrib.g);
glare = max(glare, spec_contrib.b);
color += spec_contrib;
applyGlossEnv(color, glossenv, final_specular, pos.xyz, norm.xyz);
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
}
color = mix(color.rgb, diffcol.rgb, diffuse.a);
color = mix(color.rgb, diffcol.rgb, emissive);
if (env_intensity > 0.0)
if (env > 0.0)
{ // add environmentmap
applyLegacyEnv(color, legacyenv, final_specular, pos.xyz, norm.xyz, env_intensity);
applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, env);
float cur_glare = max(max(legacyenv.r, legacyenv.g), legacyenv.b);
cur_glare *= env*4.0;
glare += cur_glare;
}
color.rgb = mix(atmosFragLightingLinear(color.rgb, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), diffuse.a);
color.rgb = linear_to_srgb(color.rgb);
color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
color.rgb = scaleSoftClipFragLinear(color.rgb);
#ifdef WATER_FOG
vec4 temp = applyWaterFogView(pos, vec4(color, 0.0));
color = temp.rgb;
#endif
color.rgb = srgb_to_linear(color.rgb);
vec3 npos = normalize(-pos.xyz);
vec3 light = vec3(0, 0, 0);
#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w );
#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, spec, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
LIGHT_LOOP(1)
LIGHT_LOOP(2)
@ -364,17 +400,25 @@ void main()
LIGHT_LOOP(6)
LIGHT_LOOP(7)
light *= 1.0-emissive;
color += light;
float al = diffcol.a*vertex_color.a;
glare *= 1.0-emissive;
glare = min(glare, 1.0);
float al = max(diffcol.a, glare) * vertex_color.a;
#ifdef WATER_FOG
vec4 temp = applyWaterFogView(pos, vec4(color, 0.0));
color = temp.rgb;
#endif
frag_color = vec4(color, al);
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
frag_data[0] = final_color; // gbuffer is sRGB for legacy materials
frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
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)
#endif
}

View File

@ -37,7 +37,6 @@ uniform sampler2D diffuseRect;
uniform sampler2D specularRect;
uniform sampler2D normalMap;
uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform sampler2D depthMap;
@ -126,8 +125,7 @@ void main()
diffuse = srgb_to_linear(diffuse);
spec.rgb = srgb_to_linear(spec.rgb);
float noise = texture2D(noiseMap, tc).b;
float lit = nl * dist_atten * noise;
float lit = nl * dist_atten;
final_color = color.rgb*lit*diffuse;

View File

@ -80,7 +80,7 @@ bool isAbove(vec3 pos, vec4 plane)
return (dot(plane.xyz, pos) + plane.w) > 0;
}
int max_priority = 0;
bool sample_automatic = true;
// return true if probe at index i influences position pos
bool shouldSampleProbe(int i, vec3 pos)
@ -95,24 +95,24 @@ bool shouldSampleProbe(int i, vec3 pos)
return false;
}
max_priority = max(max_priority, -refIndex[i].w);
sample_automatic = false;
}
else
{
if (refSphere[i].w > 0.0) // zero is special indicator to always sample this probe
if (refIndex[i].w == 0 && !sample_automatic)
{
vec3 delta = pos.xyz - refSphere[i].xyz;
float d = dot(delta, delta);
float r2 = refSphere[i].w;
r2 *= r2;
if (d > r2)
{ //outside bounding sphere
return false;
}
return false;
}
max_priority = max(max_priority, refIndex[i].w);
vec3 delta = pos.xyz - refSphere[i].xyz;
float d = dot(delta, delta);
float r2 = refSphere[i].w;
r2 *= r2;
if (d > r2)
{ // outside bounding sphere
return false;
}
}
return true;
@ -120,7 +120,6 @@ bool shouldSampleProbe(int i, vec3 pos)
// call before sampleRef
// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT
// overall algorithm --
void preProbeSample(vec3 pos)
{
// TODO: make some sort of structure that reduces the number of distance checks
@ -210,7 +209,7 @@ void preProbeSample(vec3 pos)
}
}
if (max_priority <= 1)
if (sample_automatic)
{ // probe at index 0 is a special probe for smoothing out automatic probes
probeIndex[probeInfluences++] = 0;
}
@ -342,7 +341,7 @@ return texCUBE(envMap, ReflDirectionWS);
// d - distance to nearest wall in clip space
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d)
{
// Intersection with OBB convertto unit box space
// Intersection with OBB convert to unit box space
// Transform in local unit parallax cube space (scaled and rotated)
mat4 clipToLocal = refBox[i];
@ -431,18 +430,24 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
// origin - center of sphere probe
// r - radius of probe influence volume
// min_da - minimum angular attenuation coefficient
float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da)
// i - index of probe in refSphere
// dw - distance weight
float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da, int i, out float dw)
{
float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz - origin;
float d2 = max(length(delta), 0.001);
float r2 = r1; //r1 * r1;
//float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001);
float atten = 1.0 - max(d2 - r2, 0.0) / max((r - r2), 0.001);
float w = 1.0 / d2;
dw = w * atten * max(r, 1.0)*4;
atten *= max(dot(normalize(-delta), dir), min_da);
float w = 1.0 / d2;
w *= atten;
return w;
@ -451,48 +456,43 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da)
// Tap a reflection probe
// pos - position of pixel
// dir - pixel normal
// vi - return value of intersection point with influence volume
// wi - return value of approximate world space position of sampled pixel
// lod - which mip to bias towards (lower is higher res, sharper reflections)
// w - weight of sample (distance and angular attenuation)
// dw - weight of sample (distance only)
// lod - which mip to sample (lower is higher res, sharper reflections)
// c - center of probe
// r2 - radius of probe squared
// i - index of probe
vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float lod, vec3 c, int i)
vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, int i)
{
//lod = max(lod, 1);
// parallax adjustment
vec3 v;
if (refIndex[i].w < 0)
{
{ // box probe
float d = 0;
v = boxIntersect(pos, dir, i, d);
w = max(d, 0.001);
}
else
{
float r = refSphere[i].w; // radius of sphere volume
float rr = r * r; // radius squared
{ // sphere probe
float r = refSphere[i].w;
float rr = r * r;
v = sphereIntersect(pos, dir, c,
refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr);
w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25);
w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25, i, dw);
}
vi = v;
v -= c;
vec3 d = normalize(v);
v = env_mat * v;
vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod);
wi = d * ret.a * 256.0+c;
vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y;
return ret.rgb;
}
@ -500,10 +500,10 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float
// Tap an irradiance map
// pos - position of pixel
// dir - pixel normal
// c - center of probe
// r2 - radius of probe squared
// w - weight of sample (distance and angular attenuation)
// dw - weight of sample (distance only)
// i - index of probe
vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int i)
{
// parallax adjustment
vec3 v;
@ -516,14 +516,15 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
else
{
float r = refSphere[i].w; // radius of sphere volume
float p = float(abs(refIndex[i].w)); // priority
float rr = r * r; // radius squred
// pad sphere for manual probe extending into automatic probe space
float rr = r * r;
v = sphereIntersect(pos, dir, c,
refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr);
w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001);
w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001, i, dw);
}
v -= c;
@ -533,106 +534,129 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
}
}
vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
{
float wsum = 0.0;
vec3 col = vec3(0,0,0);
float vd2 = dot(pos,pos); // view distance squared
float wsum[2];
wsum[0] = 0;
wsum[1] = 0;
float dwsum[2];
dwsum[0] = 0;
dwsum[1] = 0;
vec3 col[2];
col[0] = vec3(0);
col[1] = vec3(0);
for (int idx = 0; idx < probeInfluences; ++idx)
{
int i = probeIndex[idx];
if (abs(refIndex[i].w) < max_priority)
int p = clamp(abs(refIndex[i].w), 0, 1);
if (p == 0 && !sample_automatic)
{
continue;
}
float w;
vec3 vi, wi;
float w = 0;
float dw = 0;
vec3 refcol;
{
if (errorCorrect && refIndex[i].w >= 0)
{ // error correction is on and this probe is a sphere
//take a sample to get depth value, then error correct
refcol = tapRefMap(pos, dir, w, vi, wi, abs(lod + 2), refSphere[i].xyz, i);
refcol = tapRefMap(pos, dir, w, dw, lod, refSphere[i].xyz, i);
//adjust lookup by distance result
float d = length(vi - wi);
vi += dir * d;
vi -= refSphere[i].xyz;
vi = env_mat * vi;
refcol = textureLod(reflectionProbes, vec4(vi, refIndex[i].x), lod).rgb;
// weight by vector correctness
vec3 pi = normalize(wi - pos);
w *= max(dot(pi, dir), 0.1);
//w = pow(w, 32.0);
}
else
{
refcol = tapRefMap(pos, dir, w, vi, wi, lod, refSphere[i].xyz, i);
}
col += refcol.rgb*w;
wsum += w;
col[p] += refcol.rgb*w;
wsum[p] += w;
dwsum[p] += dw;
}
}
if (wsum > 0.0)
// mix automatic and manual probes
if (sample_automatic && wsum[0] > 0.0)
{ // some automatic probes were sampled
col[0] *= 1.0/wsum[0];
if (wsum[1] > 0.0)
{ //some manual probes were sampled, mix between the two
col[1] *= 1.0/wsum[1];
col[1] = mix(col[0], col[1], min(dwsum[1], 1.0));
col[0] = vec3(0);
}
}
else if (wsum[1] > 0.0)
{
col *= 1.0/wsum;
// manual probes were sampled but no automatic probes were
col[1] *= 1.0/wsum[1];
col[0] = vec3(0);
}
return col;
return col[1]+col[0];
}
vec3 sampleProbeAmbient(vec3 pos, vec3 dir)
{
// modified copy/paste of sampleProbes follows, will likely diverge from sampleProbes further
// as irradiance map mixing is tuned independently of radiance map mixing
float wsum = 0.0;
vec3 col = vec3(0,0,0);
float vd2 = dot(pos,pos); // view distance squared
float wsum[2];
wsum[0] = 0;
wsum[1] = 0;
float minweight = 1.0;
float dwsum[2];
dwsum[0] = 0;
dwsum[1] = 0;
vec3 col[2];
col[0] = vec3(0);
col[1] = vec3(0);
for (int idx = 0; idx < probeInfluences; ++idx)
{
int i = probeIndex[idx];
if (abs(refIndex[i].w) < max_priority)
int p = clamp(abs(refIndex[i].w), 0, 1);
if (p == 0 && !sample_automatic)
{
continue;
}
{
float w;
vec3 refcol = tapIrradianceMap(pos, dir, w, refSphere[i].xyz, i);
float w = 0;
float dw = 0;
col += refcol*w;
wsum += w;
vec3 refcol = tapIrradianceMap(pos, dir, w, dw, refSphere[i].xyz, i);
col[p] += refcol*w;
wsum[p] += w;
dwsum[p] += dw;
}
}
if (wsum > 0.0)
{
col *= 1.0/wsum;
// mix automatic and manual probes
if (sample_automatic && wsum[0] > 0.0)
{ // some automatic probes were sampled
col[0] *= 1.0/wsum[0];
if (wsum[1] > 0.0)
{ //some manual probes were sampled, mix between the two
col[1] *= 1.0/wsum[1];
col[1] = mix(col[0], col[1], min(dwsum[1], 1.0));
col[0] = vec3(0);
}
}
return col;
else if (wsum[1] > 0.0)
{
// manual probes were sampled but no automatic probes were
col[1] *= 1.0/wsum[1];
col[0] = vec3(0);
}
return col[1]+col[0];
}
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
vec2 tc, vec3 pos, vec3 norm, float glossiness)
{
// TODO - don't hard code lods
float reflection_lods = max_probe_lod;
float reflection_lods = max_probe_lod-1;
preProbeSample(pos);
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
@ -640,13 +664,12 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
ambenv = sampleProbeAmbient(pos, norm);
float lod = (1.0-glossiness)*reflection_lods;
glossenv = sampleProbes(pos, normalize(refnormpersp), lod, errorCorrect);
glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
#if defined(SSR)
if (cube_snapshot != 1 && glossiness >= 0.9)
{
vec4 ssr = vec4(0);
//float w = tapScreenSpaceReflection(errorCorrect ? 1 : 4, tc, pos, norm, ssr, sceneMap);
float w = tapScreenSpaceReflection(1, tc, pos, norm, ssr, sceneMap);
glossenv = mix(glossenv, ssr.rgb, w);
@ -654,11 +677,20 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
#endif
}
void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness)
{
sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness);
// fudge factor to get PBR water at a similar luminance ot legacy water
glossenv *= 0.25;
}
void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
{
vec3 origin = vec3(0,0,0);
bool manual_probe = abs(refIndex[i].w) > 2;
bool manual_probe = abs(refIndex[i].w) > 0;
if (manual_probe)
{
@ -694,18 +726,9 @@ vec4 sampleReflectionProbesDebug(vec3 pos)
return col;
}
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness)
{
sampleReflectionProbes(ambenv, glossenv,
tc, pos, norm, glossiness, false);
}
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity)
{
// TODO - don't hard code lods
float reflection_lods = max_probe_lod;
preProbeSample(pos);
@ -716,12 +739,12 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
if (glossiness > 0.0)
{
float lod = (1.0-glossiness)*reflection_lods;
glossenv = sampleProbes(pos, normalize(refnormpersp), lod, false);
glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
}
if (envIntensity > 0.0)
{
legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, false);
legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0);
}
#if defined(SSR)

View File

@ -85,6 +85,8 @@ float getDepth(vec2 pos_screen);
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
uniform vec4 waterPlane;
#ifdef WATER_FOG
vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
#endif
@ -153,6 +155,24 @@ void main()
calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
vec3 sunlit_linear = srgb_to_linear(sunlit);
vec3 amblit_linear = amblit;
bool do_atmospherics = false;
#ifndef WATER_FOG
// when above water, mask off atmospherics below water
if (dot(pos.xyz, waterPlane.xyz) + waterPlane.w > 0.0)
{
do_atmospherics = true;
}
#else
do_atmospherics = true;
#endif
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 orm = texture2D(specularRect, tc).rgb;
@ -161,23 +181,32 @@ void main()
float ao = orm.r * ambocc;
vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
// PBR IBL
float gloss = 1.0 - perceptualRoughness;
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss);
// Take maximium of legacy ambient vs irradiance sample as irradiance
// NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here
irradiance = max(amblit,irradiance);
irradiance = max(amblit_linear,irradiance);
vec3 diffuseColor;
vec3 specularColor;
calcDiffuseSpecular(baseColor.rgb, metallic, diffuseColor, specularColor);
vec3 v = -normalize(pos.xyz);
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
color = vec3(1,0,1);
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
if (do_atmospherics)
{
color = linear_to_srgb(color);
color = atmosFragLightingLinear(color, additive, atten);
color = srgb_to_linear(color);
}
}
else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
{
@ -199,12 +228,12 @@ void main()
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity);
// use sky settings ambient or irradiance map sample, whichever is brighter
irradiance = max(amblit, irradiance);
irradiance = max(amblit_linear, irradiance);
// apply lambertian IBL only (see pbrIbl)
color.rgb = irradiance * ambocc;
vec3 sun_contrib = min(da, scol) * sunlit;
vec3 sun_contrib = min(da, scol) * sunlit_linear;
color.rgb += sun_contrib;
color.rgb *= baseColor.rgb;
@ -230,9 +259,16 @@ void main()
applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
}
color = mix(atmosFragLightingLinear(color, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), baseColor.a);
color = scaleSoftClipFragLinear(color);
}
if (do_atmospherics)
{
color = linear_to_srgb(color);
color = atmosFragLightingLinear(color, additive, atten);
color = srgb_to_linear(color);
}
}
#ifdef WATER_FOG
vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom));

View File

@ -114,6 +114,7 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
}
vec3 srgb_to_linear(vec3 col);
vec3 linear_to_srgb(vec3 col);
vec3 vN, vT, vB;
@ -122,11 +123,8 @@ vec3 transform_normal(vec3 vNt)
return normalize(vNt.x * vT + vNt.y * vB + vNt.z * vN);
}
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness);
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect);
void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness);
vec3 getPositionWithNDC(vec3 ndc);
@ -203,6 +201,8 @@ void main()
calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
vec3 sunlit_linear = srgb_to_linear(sunlit);
#ifdef TRANSPARENT_WATER
vec4 fb = texture2D(screenTex, distort2);
float depth = texture2D(screenDepth, distort2).r;
@ -219,21 +219,24 @@ void main()
fb = applyWaterFogViewLinear(refPos, fb, sunlit);
#else
vec4 fb = applyWaterFogViewLinear(viewVec*1024.0, vec4(0.5), sunlit);
vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0), sunlit_linear);
#endif
// fudge sample on other side of water to be a tad darker
fb.rgb *= 0.75;
float metallic = 0.0;
float perceptualRoughness = 0.1;
float perceptualRoughness = 0.05;
float gloss = 1.0 - perceptualRoughness;
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss);
sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss);
irradiance = vec3(0);
vec3 diffuseColor;
vec3 specularColor;
vec3 diffuseColor = vec3(0);
vec3 specularColor = vec3(0);
calcDiffuseSpecular(vec3(1), metallic, diffuseColor, specularColor);
vec3 v = -normalize(pos.xyz);
@ -250,10 +253,7 @@ void main()
vec3 punctual = pbrPunctual(vec3(0), specularColor, 0.1, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir));
vec3 color = punctual * sunlit * 2.75 * scol;
color = atmosFragLightingLinear(color, additive, atten);
color = scaleSoftClipFragLinear(color);
vec3 color = punctual * sunlit_linear * 2.75 * scol;
vec3 ibl = pbrIbl(vec3(0), vec3(1), radiance, vec3(0), ao, NdotV, 0.0);
@ -265,10 +265,24 @@ void main()
f *= 0.9;
f *= f;
// incoming scale is [0, 1] with 0.5 being default
// shift to 0.5 to 1.5
f *= (fresnelScale - 0.5)+1.0;
// incoming offset is [0, 1] with 0.5 being default
// shift from -1 to 1
f += (fresnelOffset - 0.5) * 2.0;
f = clamp(f, 0, 1);
//fb.rgb *= 1.;
color = mix(color, fb.rgb, f);
color.rgb = linear_to_srgb(color.rgb);
color = atmosFragLightingLinear(color, additive, atten);
color = scaleSoftClipFragLinear(color);
color.rgb = srgb_to_linear(color.rgb);
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05);
frag_color = vec4(color, spec); //*sunAngle2);

View File

@ -1,4 +1,4 @@
version 48
version 50
// 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
@ -71,7 +71,7 @@ RenderFSAASamples 1 16
RenderMaxTextureIndex 1 16
RenderGLContextCoreProfile 1 1
RenderGLMultiThreaded 1 0
RenderReflectionProbeResolution 1 256
RenderReflectionProbeResolution 1 128
RenderScreenSpaceReflections 1 1
@ -117,7 +117,7 @@ RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
RenderLocalLights 1 1
RenderTransparentWater 1 0
RenderReflectionsEnabled 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
@ -279,12 +279,6 @@ RenderUseAdvancedAtmospherics 1 0
list VRAMGT512
RenderCompressTextures 1 0
//
// VRAM < 2GB
//
list VRAMLT2GB
RenderReflectionProbeResolution 1 128
//
// "Default" setups for safe, low, medium, high
//

View File

@ -1,4 +1,4 @@
version 37
version 38
// 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
@ -71,7 +71,7 @@ RenderFSAASamples 1 16
RenderMaxTextureIndex 1 16
RenderGLContextCoreProfile 1 1
RenderGLMultiThreaded 1 0
RenderReflectionProbeResolution 1 256
RenderReflectionProbeResolution 1 128
RenderScreenSpaceReflections 1 1
@ -117,7 +117,7 @@ RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
RenderLocalLights 1 1
RenderTransparentWater 1 0
RenderReflectionsEnabled 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
@ -279,12 +279,6 @@ RenderUseAdvancedAtmospherics 1 0
list VRAMGT512
RenderCompressTextures 1 0
//
// VRAM < 2GB
//
list VRAMLT2GB
RenderReflectionProbeResolution 1 128
//
// "Default" setups for safe, low, medium, high
//

View File

@ -1,4 +1,4 @@
version 44
version 45
// 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
@ -71,6 +71,7 @@ RenderGLMultiThreaded 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 2
RenderScreenSpaceReflections 1 1
RenderReflectionProbeCount 1 8
//
// Low Graphics Settings
@ -123,7 +124,7 @@ RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 48
RenderFSAASamples 1 0
RenderReflectionsEnabled 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderScreenSpaceReflections 1 0

View File

@ -4727,8 +4727,6 @@ bool LLAgent::teleportCore(bool is_local)
LL_INFOS("Teleport") << "Non-local, setting teleport state to TELEPORT_START" << LL_ENDL;
gAgent.setTeleportState( LLAgent::TELEPORT_START );
//release geometry from old location
gPipeline.resetVertexBuffers();
LLSpatialPartition::sTeleportRequested = TRUE;
// <FS:Ansariel> Draw Distance stepping; originally based on SpeedRez by Henri Beauchamp, licensed under LGPL
@ -5122,7 +5120,6 @@ void LLAgent::teleportCancel()
}
clearTeleportRequest();
gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
gPipeline.resetVertexBuffers();
}
void LLAgent::restoreCanceledTeleportRequest()

View File

@ -117,6 +117,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
break;
case POOL_GLTF_PBR:
poolp = new LLDrawPoolGLTFPBR();
break;
case POOL_GLTF_PBR_ALPHA_MASK:
poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK);
break;
default:
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
@ -717,11 +720,6 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textur
}
}
//if (params.mGroup) // TOO LATE!
//{
// params.mGroup->rebuildMesh();
//}
params.mVertexBuffer->setBuffer();
params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);

View File

@ -58,8 +58,9 @@ public:
POOL_BUMP,
POOL_TERRAIN,
POOL_MATERIALS,
POOL_GRASS,
POOL_GLTF_PBR,
POOL_GRASS,
POOL_GLTF_PBR_ALPHA_MASK,
POOL_TREE,
POOL_ALPHA_MASK,
POOL_FULLBRIGHT_ALPHA_MASK,
@ -109,7 +110,7 @@ public:
virtual void render(S32 pass = 0) {};
virtual void prerender() {};
virtual U32 getVertexDataMask() = 0;
virtual U32 getVertexDataMask() { return 0; } // DEPRECATED -- draw pool doesn't actually determine vertex data mask any more
virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct!
virtual S32 getShaderLevel() const { return mShaderLevel; }

View File

@ -31,11 +31,17 @@
#include "llviewershadermgr.h"
#include "pipeline.h"
static const U32 gltf_render_types[] = { LLPipeline::RENDER_TYPE_PASS_GLTF_PBR, LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK };
LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR() :
LLRenderPass(POOL_GLTF_PBR)
LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR(U32 type) :
LLRenderPass(type)
{
if (type == LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK)
{
mRenderType = LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK;
}
else
{
mRenderType = LLPipeline::RENDER_TYPE_PASS_GLTF_PBR;
}
}
S32 LLDrawPoolGLTFPBR::getNumDeferredPasses()
@ -47,14 +53,11 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass)
{
llassert(!LLPipeline::sRenderingHUDs);
for (U32 type : gltf_render_types)
{
gDeferredPBROpaqueProgram.bind();
pushGLTFBatches(type);
gDeferredPBROpaqueProgram.bind();
pushGLTFBatches(mRenderType);
gDeferredPBROpaqueProgram.bind(true);
pushRiggedGLTFBatches(type + 1);
}
gDeferredPBROpaqueProgram.bind(true);
pushRiggedGLTFBatches(mRenderType + 1);
}
S32 LLDrawPoolGLTFPBR::getNumPostDeferredPasses()
@ -67,12 +70,9 @@ void LLDrawPoolGLTFPBR::renderPostDeferred(S32 pass)
if (LLPipeline::sRenderingHUDs)
{
gHUDPBROpaqueProgram.bind();
for (U32 type : gltf_render_types)
{
pushGLTFBatches(type);
}
pushGLTFBatches(mRenderType);
}
else
else if (mRenderType == LLPipeline::RENDER_TYPE_PASS_GLTF_PBR) // HACK -- don't render glow except for the non-alpha masked implementation
{
gGL.setColorMask(false, true);
gPBRGlowProgram.bind();
@ -85,4 +85,3 @@ void LLDrawPoolGLTFPBR::renderPostDeferred(S32 pass)
}
}

View File

@ -32,21 +32,9 @@
class LLDrawPoolGLTFPBR final : public LLRenderPass
{
public:
enum
{
// See: DEFERRED_VB_MASK
VERTEX_DATA_MASK = 0
| LLVertexBuffer::MAP_VERTEX
| LLVertexBuffer::MAP_NORMAL
| LLVertexBuffer::MAP_TEXCOORD0 // Diffuse
| LLVertexBuffer::MAP_TEXCOORD1 // Normal
| LLVertexBuffer::MAP_TEXCOORD2 // Spec <-- ORM Occlusion Roughness Metal
| LLVertexBuffer::MAP_TANGENT
| LLVertexBuffer::MAP_COLOR
};
U32 getVertexDataMask() override { return VERTEX_DATA_MASK; }
LLDrawPoolGLTFPBR(U32 type = LLDrawPool::POOL_GLTF_PBR);
LLDrawPoolGLTFPBR();
U32 mRenderType = 0;
S32 getNumDeferredPasses() override;
void renderDeferred(S32 pass) override;

View File

@ -45,6 +45,8 @@
#include "llvowlsky.h"
#include "llsettingsvo.h"
extern BOOL gCubeSnapshot;
static LLStaticHashedString sCamPosLocal("camPosLocal");
static LLStaticHashedString sCustomAlpha("custom_alpha");
@ -416,11 +418,14 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
void LLDrawPoolWLSky::renderDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY);
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY) || gSky.mVOSkyp.isNull())
{
return;
}
// TODO: remove gSky.mVOSkyp and fold sun/moon into LLVOWLSky
gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
const F32 camHeightLocal = LLEnvironment::instance().getCamHeight();
gGL.setColorMask(true, false);
@ -431,7 +436,10 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass)
{
renderSkyHazeDeferred(origin, camHeightLocal);
renderHeavenlyBodies();
renderStarsDeferred(origin);
if (!gCubeSnapshot)
{
renderStarsDeferred(origin);
}
renderSkyCloudsDeferred(origin, camHeightLocal, cloud_shader);
}
gGL.setColorMask(true, true);

View File

@ -1603,7 +1603,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|| mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2);
}
bool do_tex_mat = tex_mode && mTextureMatrix;
// For GLTF materials: Transforms will be applied later
bool do_tex_mat = tex_mode && mTextureMatrix && !gltf_mat;
if (!do_bump)
{ //not bump mapped, might be able to do a cheap update
@ -1700,7 +1701,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
*tex_coords0++ = tc;
}
}
else
else if (do_xform)
{
for (S32 i = 0; i < num_vertices; i++)
{
@ -1713,6 +1714,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
*tex_coords0++ = tc;
}
}
else
{
for (S32 i = 0; i < num_vertices; i++)
{
LLVector2 tc(vf.mTexCoords[i]);
LLVector4a& norm = vf.mNormals[i];
LLVector4a& center = *(vf.mCenter);
LLVector4a vec = vf.mPositions[i];
vec.mul(scalea);
planarProjection(tc, norm, center, vec);
*tex_coords0++ = tc;
}
}
@ -1780,44 +1795,44 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
for (S32 i = 0; i < num_vertices; i++)
{
LLVector2 tc(vf.mTexCoords[i]);
LLVector4a& norm = vf.mNormals[i];
LLVector4a& center = *(vf.mCenter);
if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
{
LLVector4a vec = vf.mPositions[i];
vec.mul(scalea);
for (S32 i = 0; i < num_vertices; i++)
{
LLVector2 tc(vf.mTexCoords[i]);
LLVector4a& norm = vf.mNormals[i];
LLVector4a& center = *(vf.mCenter);
if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
{
LLVector4a vec = vf.mPositions[i];
vec.mul(scalea);
if (texgen == LLTextureEntry::TEX_GEN_PLANAR)
{
planarProjection(tc, norm, center, vec);
}
}
if (texgen == LLTextureEntry::TEX_GEN_PLANAR)
{
planarProjection(tc, norm, center, vec);
}
}
if (tex_mode && mTextureMatrix)
{
LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
tmp = tmp * *mTextureMatrix;
tc.mV[0] = tmp.mV[0];
tc.mV[1] = tmp.mV[1];
}
else
{
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
}
if (tex_mode && mTextureMatrix)
{
LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
tmp = tmp * *mTextureMatrix;
tc.mV[0] = tmp.mV[0];
tc.mV[1] = tmp.mV[1];
}
else if (do_xform)
{
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
}
*dst++ = tc;
if (do_bump)
{
bump_tc.push_back(tc);
}
}
*dst++ = tc;
if (do_bump)
{
bump_tc.push_back(tc);
}
}
}
if ((!mat && !gltf_mat) && do_bump)

View File

@ -435,18 +435,14 @@ bool LLFeatureManager::loadGPUClass()
}
if (gbps < 0.f)
{ //couldn't bench, use GLVersion
{ //couldn't bench, default to Low
#if LL_DARWIN
//GLVersion is misleading on OSX, just default to class 3 if we can't bench
LL_WARNS("RenderInit") << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL;
mGPUClass = GPU_CLASS_3;
#else
mGPUClass = GPU_CLASS_2;
#endif
}
else if (gbps <= 5.f)
{
mGPUClass = GPU_CLASS_0;
#endif
}
else if (gbps <= 8.f)
{

View File

@ -110,14 +110,21 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex)
shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor);
shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV);
const LLMatrix3 base_color_matrix = mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].asMatrix();
shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_BASECOLOR_MATRIX, 1, false, (F32*)base_color_matrix.mMatrix);
const LLMatrix3 normal_matrix = mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].asMatrix();
shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_NORMAL_MATRIX, 1, false, (F32*)normal_matrix.mMatrix);
const LLMatrix3 metallic_roughness_matrix = mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].asMatrix();
shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_MATRIX, 1, false, (F32*)metallic_roughness_matrix.mMatrix);
const LLMatrix3 emissive_matrix = mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].asMatrix();
shader->uniformMatrix3fv(LLShaderMgr::TEXTURE_EMISSIVE_MATRIX, 1, false, (F32*)emissive_matrix.mMatrix);
F32 base_color_packed[8];
mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed);
F32 normal_packed[8];
mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed);
F32 metallic_roughness_packed[8];
mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed);
F32 emissive_packed[8];
mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, (F32*)emissive_packed);
}
}

View File

@ -693,6 +693,7 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
allowedv->push_back("anim");
break;
case FFLOAD_GLTF:
case FFLOAD_MATERIAL:
allowedv->push_back("gltf");
allowedv->push_back("glb");
break;

View File

@ -564,9 +564,9 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp
if (LLSDSerialize::deserialize(asset, str, buffer.size()))
{
if (asset.has("version") && asset["version"] == "1.0")
if (asset.has("version") && LLGLTFMaterial::isAcceptedVersion(asset["version"].asString()))
{
if (asset.has("type") && asset["type"].asString() == "GLTF 2.0")
if (asset.has("type") && asset["type"].asString() == LLGLTFMaterial::ASSET_TYPE)
{
if (asset.has("data") && asset["data"].isString())
{

View File

@ -277,10 +277,10 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index)
llassert(mat.notNull()); // by this point shouldn't be null
if (mat.notNull())
{
tex_color_id = mat->mBaseColorId;
tex_metal_id = mat->mMetallicRoughnessId;
tex_emissive_id = mat->mEmissiveId;
tex_normal_id = mat->mNormalId;
tex_color_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR];
tex_metal_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS];
tex_emissive_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE];
tex_normal_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL];
}
if (mFirst)
{
@ -420,6 +420,13 @@ BOOL LLMaterialEditor::postBuild()
mEmissiveTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_EMISIVE_TEX_DIRTY));
mNormalTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_NORMAL_TEX_DIRTY));
}
else
{
mBaseColorTextureCtrl->setCanApplyImmediately(false);
mMetallicTextureCtrl->setCanApplyImmediately(false);
mEmissiveTextureCtrl->setCanApplyImmediately(false);
mNormalTextureCtrl->setCanApplyImmediately(false);
}
if (!mIsOverride)
{
@ -461,6 +468,10 @@ BOOL LLMaterialEditor::postBuild()
mBaseColorCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_BASE_COLOR_DIRTY));
mBaseColorCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_BASE_COLOR_DIRTY));
}
else
{
mBaseColorCtrl->setCanApplyImmediately(false);
}
// transparency is a part of base color
childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
childSetCommitCallback("alpha mode", changes_callback, (void*)&MATERIAL_ALPHA_MODE_DIRTY);
@ -477,6 +488,10 @@ BOOL LLMaterialEditor::postBuild()
mEmissiveColorCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_EMISIVE_COLOR_DIRTY));
mEmissiveColorCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_EMISIVE_COLOR_DIRTY));
}
else
{
mEmissiveColorCtrl->setCanApplyImmediately(false);
}
if (!mIsOverride)
{
@ -949,7 +964,7 @@ void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_
}
case MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY:
{
nodep->mSavedGLTFOverrideMaterials[te]->setMetallicRoughnessId(mCtrl->getValue().asUUID(), true);
nodep->mSavedGLTFOverrideMaterials[te]->setOcclusionRoughnessMetallicId(mCtrl->getValue().asUUID(), true);
break;
}
case MATERIAL_EMISIVE_TEX_DIRTY:
@ -991,30 +1006,6 @@ void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_
LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func);
}
static void write_color(const LLColor4& color, std::vector<double>& c)
{
for (int i = 0; i < c.size(); ++i) // NOTE -- use c.size because some gltf colors are 3-component
{
c[i] = color.mV[i];
}
}
static U32 write_texture(const LLUUID& id, tinygltf::Model& model)
{
tinygltf::Image image;
image.uri = id.asString();
model.images.push_back(image);
U32 image_idx = model.images.size() - 1;
tinygltf::Texture texture;
texture.source = image_idx;
model.textures.push_back(texture);
U32 texture_idx = model.textures.size() - 1;
return texture_idx;
}
void LLMaterialEditor::onClickSave()
{
if (!capabilitiesAvailable())
@ -1034,109 +1025,14 @@ void LLMaterialEditor::onClickSave()
saveIfNeeded();
}
std::string LLMaterialEditor::getGLTFJson(bool prettyprint)
{
tinygltf::Model model;
getGLTFModel(model);
std::ostringstream str;
tinygltf::TinyGLTF gltf;
gltf.WriteGltfSceneToStream(&model, str, prettyprint, false);
std::string dump = str.str();
return dump;
}
void LLMaterialEditor::getGLBData(std::vector<U8>& data)
{
tinygltf::Model model;
getGLTFModel(model);
std::ostringstream str;
tinygltf::TinyGLTF gltf;
gltf.WriteGltfSceneToStream(&model, str, false, true);
std::string dump = str.str();
data.resize(dump.length());
memcpy(&data[0], dump.c_str(), dump.length());
}
void LLMaterialEditor::getGLTFModel(tinygltf::Model& model)
{
model.materials.resize(1);
tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness;
// write base color
LLColor4 base_color = getBaseColor();
base_color.mV[3] = getTransparency();
write_color(base_color, pbrMaterial.baseColorFactor);
model.materials[0].alphaCutoff = getAlphaCutoff();
model.materials[0].alphaMode = getAlphaMode();
LLUUID base_color_id = getBaseColorId();
if (base_color_id.notNull())
{
U32 texture_idx = write_texture(base_color_id, model);
pbrMaterial.baseColorTexture.index = texture_idx;
}
// write metallic/roughness
F32 metalness = getMetalnessFactor();
F32 roughness = getRoughnessFactor();
pbrMaterial.metallicFactor = metalness;
pbrMaterial.roughnessFactor = roughness;
LLUUID mr_id = getMetallicRoughnessId();
if (mr_id.notNull())
{
U32 texture_idx = write_texture(mr_id, model);
pbrMaterial.metallicRoughnessTexture.index = texture_idx;
}
//write emissive
LLColor4 emissive_color = getEmissiveColor();
model.materials[0].emissiveFactor.resize(3);
write_color(emissive_color, model.materials[0].emissiveFactor);
LLUUID emissive_id = getEmissiveId();
if (emissive_id.notNull())
{
U32 idx = write_texture(emissive_id, model);
model.materials[0].emissiveTexture.index = idx;
}
//write normal
LLUUID normal_id = getNormalId();
if (normal_id.notNull())
{
U32 idx = write_texture(normal_id, model);
model.materials[0].normalTexture.index = idx;
}
//write doublesided
model.materials[0].doubleSided = getDoubleSided();
model.asset.version = "2.0";
}
std::string LLMaterialEditor::getEncodedAsset()
{
LLSD asset;
asset["version"] = "1.0";
asset["type"] = "GLTF 2.0";
asset["data"] = getGLTFJson(false);
asset["version"] = LLGLTFMaterial::ASSET_VERSION;
asset["type"] = LLGLTFMaterial::ASSET_TYPE;
LLGLTFMaterial mat;
getGLTFMaterial(&mat);
asset["data"] = mat.asJSON();
std::ostringstream str;
LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY);
@ -1151,9 +1047,9 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)
std::istrstream str(&buffer[0], buffer.size());
if (LLSDSerialize::deserialize(asset, str, buffer.size()))
{
if (asset.has("version") && asset["version"] == "1.0")
if (asset.has("version") && LLGLTFMaterial::isAcceptedVersion(asset["version"].asString()))
{
if (asset.has("type") && asset["type"] == "GLTF 2.0")
if (asset.has("type") && asset["type"] == LLGLTFMaterial::ASSET_TYPE)
{
if (asset.has("data") && asset["data"].isString())
{
@ -1169,6 +1065,12 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)
if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), ""))
{
// assets are only supposed to have one item
// *NOTE: This duplicates some functionality from
// LLGLTFMaterial::fromJSON, but currently does the job
// better for the material editor use case.
// However, LLGLTFMaterial::asJSON should always be
// used when uploading materials, to ensure the
// asset is valid.
return setFromGltfModel(model_in, 0, true);
}
else
@ -1975,7 +1877,9 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con
{
// don't use override material here, it has 'hacked ids'
// and values, use end result, apply it on top of local.
me->setBaseColor(render_material->mBaseColor);
const LLColor4& base_color = render_material->mBaseColor;
me->setBaseColor(LLColor3(base_color));
me->setTransparency(base_color[VW]);
me->setMetalnessFactor(render_material->mMetallicFactor);
me->setRoughnessFactor(render_material->mRoughnessFactor);
me->setEmissiveColor(render_material->mEmissiveColor);
@ -1986,24 +1890,24 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con
// most things like colors we can apply without verifying
// but texture ids are going to be different from both, base and override
// so only apply override id if there is actually a difference
if (local_material->mBaseColorId != render_material->mBaseColorId)
if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR])
{
me->setBaseColorId(render_material->mBaseColorId);
me->setBaseColorId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
me->childSetValue("base_color_upload_fee", me->getString("no_upload_fee_string"));
}
if (local_material->mNormalId != render_material->mNormalId)
if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL])
{
me->setNormalId(render_material->mNormalId);
me->setNormalId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);
me->childSetValue("normal_upload_fee", me->getString("no_upload_fee_string"));
}
if (local_material->mMetallicRoughnessId != render_material->mMetallicRoughnessId)
if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS])
{
me->setMetallicRoughnessId(render_material->mMetallicRoughnessId);
me->setMetallicRoughnessId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);
me->childSetValue("metallic_upload_fee", me->getString("no_upload_fee_string"));
}
if (local_material->mEmissiveId != render_material->mEmissiveId)
if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE])
{
me->setEmissiveId(render_material->mEmissiveId);
me->setEmissiveId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
me->childSetValue("emissive_upload_fee", me->getString("no_upload_fee_string"));
}
@ -2017,7 +1921,11 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con
LLSD payload;
if (render_material)
{
payload["data"] = render_material->asJSON();
// Make a copy of the render material with unsupported transforms removed
LLGLTFMaterial asset_material = *render_material;
asset_material.sanitizeAssetMaterial();
// Serialize the sanitized render material
payload["data"] = asset_material.asJSON();
}
else
{
@ -2040,8 +1948,9 @@ void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notificati
if (0 == option)
{
LLSD asset;
asset["version"] = "1.0";
asset["type"] = "GLTF 2.0";
asset["version"] = LLGLTFMaterial::ASSET_VERSION;
asset["type"] = LLGLTFMaterial::ASSET_TYPE;
// This is the string serialized from LLGLTFMaterial::asJSON
asset["data"] = notification["payload"]["data"];
std::ostringstream str;
@ -2584,7 +2493,7 @@ public:
}
else if ((reverted_flags & MATERIAL_BASE_COLOR_TEX_DIRTY) && revert_mat.notNull())
{
material->setBaseColorId(revert_mat->mBaseColorId, false);
material->setBaseColorId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR], false);
}
if (changed_flags & MATERIAL_NORMAL_TEX_DIRTY)
@ -2593,16 +2502,16 @@ public:
}
else if ((reverted_flags & MATERIAL_NORMAL_TEX_DIRTY) && revert_mat.notNull())
{
material->setNormalId(revert_mat->mNormalId, false);
material->setNormalId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL], false);
}
if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY)
{
material->setMetallicRoughnessId(mEditor->getMetallicRoughnessId(), true);
material->setOcclusionRoughnessMetallicId(mEditor->getMetallicRoughnessId(), true);
}
else if ((reverted_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) && revert_mat.notNull())
{
material->setMetallicRoughnessId(revert_mat->mMetallicRoughnessId, false);
material->setOcclusionRoughnessMetallicId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS], false);
}
if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY)
@ -2638,7 +2547,7 @@ public:
}
else if ((reverted_flags & MATERIAL_EMISIVE_TEX_DIRTY) && revert_mat.notNull())
{
material->setEmissiveId(revert_mat->mEmissiveId, false);
material->setEmissiveId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE], false);
}
if (changed_flags & MATERIAL_DOUBLE_SIDED_DIRTY)
@ -2751,20 +2660,23 @@ void LLMaterialEditor::applyToSelection()
}
}
// Get a dump of the json representation of the current state of the editor UI
// in GLTF format, excluding transforms as they are not supported in material
// assets. (See also LLGLTFMaterial::sanitizeAssetMaterial())
void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)
{
mat->mBaseColor = getBaseColor();
mat->mBaseColor.mV[3] = getTransparency();
mat->mBaseColorId = getBaseColorId();
mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = getBaseColorId();
mat->mNormalId = getNormalId();
mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = getNormalId();
mat->mMetallicRoughnessId = getMetallicRoughnessId();
mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = getMetallicRoughnessId();
mat->mMetallicFactor = getMetalnessFactor();
mat->mRoughnessFactor = getRoughnessFactor();
mat->mEmissiveColor = getEmissiveColor();
mat->mEmissiveId = getEmissiveId();
mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = getEmissiveId();
mat->mDoubleSided = getDoubleSided();
mat->setAlphaMode(getAlphaMode());
@ -2774,15 +2686,15 @@ void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)
void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)
{
setBaseColor(mat->mBaseColor);
setBaseColorId(mat->mBaseColorId);
setNormalId(mat->mNormalId);
setBaseColorId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
setNormalId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);
setMetallicRoughnessId(mat->mMetallicRoughnessId);
setMetallicRoughnessId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);
setMetalnessFactor(mat->mMetallicFactor);
setRoughnessFactor(mat->mRoughnessFactor);
setEmissiveColor(mat->mEmissiveColor);
setEmissiveId(mat->mEmissiveId);
setEmissiveId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
setDoubleSided(mat->mDoubleSided);
setAlphaMode(mat->getAlphaMode());

View File

@ -84,8 +84,7 @@ protected:
};
class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
{
public:
{ public:
LLMaterialEditor(const LLSD& key);
bool setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures = false);
@ -98,6 +97,7 @@ public:
// for live preview, apply current material to currently selected object
void applyToSelection();
// get a dump of the json representation of the current state of the editor UI as a material object
void getGLTFMaterial(LLGLTFMaterial* mat);
void loadAsset() override;
@ -131,11 +131,6 @@ public:
void onClickSave();
// get a dump of the json representation of the current state of the editor UI in GLTF format
std::string getGLTFJson(bool prettyprint = true);
void getGLBData(std::vector<U8>& data);
void getGLTFModel(tinygltf::Model& model);
std::string getEncodedAsset();

View File

@ -1975,6 +1975,7 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material,
const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
const bool show_texture_info = texture_info != LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
const bool new_state = show_texture_info && has_pbr_capabilities && has_pbr_material;
LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
@ -1982,13 +1983,15 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material,
LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
gltfCtrlTextureScaleU->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
gltfCtrlTextureScaleV->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
gltfCtrlTextureRotation->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
gltfCtrlTextureOffsetU->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
gltfCtrlTextureOffsetV->setEnabled(show_texture_info && has_pbr_capabilities && has_pbr_material);
gltfCtrlTextureScaleU->setEnabled(new_state);
gltfCtrlTextureScaleV->setEnabled(new_state);
gltfCtrlTextureRotation->setEnabled(new_state);
gltfCtrlTextureOffsetU->setEnabled(new_state);
gltfCtrlTextureOffsetV->setEnabled(new_state);
// Control values are set in setMaterialOverridesFromSelection
// Control values will be set once per frame in
// setMaterialOverridesFromSelection
sMaterialOverrideSelection.setDirty();
}
}
@ -2979,7 +2982,6 @@ void LLPanelFace::onCommitPbrType(LLUICtrl* ctrl, void* userdata)
// and generally reflecting old state when switching tabs or objects
//
self->updateUI();
self->setMaterialOverridesFromSelection();
}
// static
@ -3981,34 +3983,12 @@ private:
struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor
{
LLPanelFaceUpdateFunctor(bool update_media, bool update_pbr)
LLPanelFaceUpdateFunctor(bool update_media)
: mUpdateMedia(update_media)
, mUpdatePbr(update_pbr)
{}
virtual bool apply(LLViewerObject* object)
{
if (mUpdatePbr)
{
// setRenderMaterialId is supposed to create it
LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
if (param_block)
{
if (param_block->isEmpty())
{
object->setHasRenderMaterialParams(false);
}
else if (object->hasRenderMaterialParams())
{
object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
}
else
{
object->setHasRenderMaterialParams(true);
}
}
}
object->sendTEUpdate();
if (mUpdateMedia)
@ -4023,7 +4003,6 @@ struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor
}
private:
bool mUpdateMedia;
bool mUpdatePbr;
};
struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor
@ -4159,7 +4138,7 @@ void LLPanelFace::onPasteColor()
LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR);
selected_objects->applyToTEs(&paste_func);
LLPanelFaceUpdateFunctor sendfunc(false, false);
LLPanelFaceUpdateFunctor sendfunc(false);
selected_objects->applyToObjects(&sendfunc);
}
@ -4520,7 +4499,7 @@ void LLPanelFace::onPasteTexture()
LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE);
selected_objects->applyToTEs(&paste_func);
LLPanelFaceUpdateFunctor sendfunc(true, true);
LLPanelFaceUpdateFunctor sendfunc(true);
selected_objects->applyToObjects(&sendfunc);
LLGLTFMaterialList::flushUpdates();
@ -4837,7 +4816,7 @@ void LLPanelFace::onPasteFaces()
LLPanelFacePasteTexFunctor paste_color_func(this, PASTE_COLOR);
selected_objects->applyToTEs(&paste_color_func);
LLPanelFaceUpdateFunctor sendfunc(true, true);
LLPanelFaceUpdateFunctor sendfunc(true);
selected_objects->applyToObjects(&sendfunc);
LLPanelFaceNavigateHomeFunctor navigate_home_func;
@ -4950,17 +4929,7 @@ void LLPanelFace::Selection::connect()
bool LLPanelFace::Selection::update()
{
const bool selection_changed = compareSelection();
if (selection_changed)
{
clearObjectUpdatePending();
}
else if (isObjectUpdatePending())
{
return false;
}
const bool changed = mChanged;
const bool changed = mChanged || compareSelection();
mChanged = false;
return changed;
}
@ -4976,16 +4945,9 @@ void LLPanelFace::Selection::onSelectedObjectUpdated(const LLUUID& object_id, S3
if (object_id == mSelectedObjectID && side == mSelectedSide)
{
mChanged = true;
clearObjectUpdatePending();
}
}
void LLPanelFace::Selection::clearObjectUpdatePending()
{
mPendingObjectID = LLUUID::null;
mPendingSide = -1;
}
bool LLPanelFace::Selection::compareSelection()
{
if (!mNeedsSelectionCheck)

View File

@ -547,15 +547,13 @@ private:
// updated. Necessary to prevent controls updating when the mouse is
// held down.
void setObjectUpdatePending(const LLUUID &object_id, S32 side);
void setDirty() { mChanged = true; };
// Callbacks
void onSelectionChanged() { mNeedsSelectionCheck = true; }
void onSelectedObjectUpdated(const LLUUID &object_id, S32 side);
protected:
void clearObjectUpdatePending();
bool isObjectUpdatePending() { return mPendingSide != -1; }
bool compareSelection();
bool mChanged = false;

View File

@ -767,27 +767,49 @@ void LLPanelVolume::sendIsReflectionProbe()
BOOL value = getChild<LLUICtrl>("Reflection Probe")->getValue();
BOOL old_value = volobjp->isReflectionProbe();
volobjp->setIsReflectionProbe(value);
LL_INFOS() << "update reflection probe sent" << LL_ENDL;
if (value && value != old_value)
{ // defer to notification util as to whether or not we *really* make this object a reflection probe
LLNotificationsUtil::add("ReflectionProbeApplied", LLSD(), LLSD(), boost::bind(&LLPanelVolume::doSendIsReflectionProbe, this, _1, _2));
}
else
{
volobjp->setIsReflectionProbe(value);
}
}
if (value && !old_value)
{ // has become a reflection probe, slam to a 10m sphere and pop up a message
// warning people about the pitfalls of reflection probes
auto* select_mgr = LLSelectMgr::getInstance();
void LLPanelVolume::doSendIsReflectionProbe(const LLSD & notification, const LLSD & response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0) // YES
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
mObject->setScale(LLVector3(10.f, 10.f, 10.f));
select_mgr->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION | UPD_SCALE);
volobjp->setIsReflectionProbe(true);
select_mgr->selectionUpdatePhantom(true);
select_mgr->selectionSetGLTFMaterial(LLUUID::null);
select_mgr->selectionSetAlphaOnly(0.f);
LLVolumeParams params;
params.getPathParams().setCurveType(LL_PCODE_PATH_CIRCLE);
params.getProfileParams().setCurveType(LL_PCODE_PROFILE_CIRCLE_HALF);
mObject->updateVolume(params);
{ // has become a reflection probe, slam to a 10m sphere and pop up a message
// warning people about the pitfalls of reflection probes
LLNotificationsUtil::add("ReflectionProbeApplied");
auto* select_mgr = LLSelectMgr::getInstance();
select_mgr->selectionUpdatePhantom(true);
select_mgr->selectionSetGLTFMaterial(LLUUID::null);
select_mgr->selectionSetAlphaOnly(0.f);
LLVolumeParams params;
params.getPathParams().setCurveType(LL_PCODE_PATH_CIRCLE);
params.getProfileParams().setCurveType(LL_PCODE_PROFILE_CIRCLE_HALF);
mObject->updateVolume(params);
}
}
else
{
// cancelled, touch up UI state
getChild<LLUICtrl>("Reflection Probe")->setValue(false);
}
}
@ -1375,6 +1397,12 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
if (volobjp->setReflectionProbeIsBox(is_box))
{
// make the volume match the probe
auto* select_mgr = LLSelectMgr::getInstance();
select_mgr->selectionUpdatePhantom(true);
select_mgr->selectionSetGLTFMaterial(LLUUID::null);
select_mgr->selectionSetAlphaOnly(0.f);
U8 profile, path;
if (!is_box)

View File

@ -57,7 +57,14 @@ 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();
// callback for handling response of the ok/cancel/ignore dialog for making an object a reflection probe
void doSendIsReflectionProbe(const LLSD& notification, const LLSD& response);
void sendIsFlexible();
static bool precommitValidate(const LLSD& data);

View File

@ -31,13 +31,24 @@
#include "llviewerwindow.h"
#include "llviewerregion.h"
#include "llworld.h"
#include "llshadermgr.h"
extern F32SecondsImplicit gFrameTimeSeconds;
extern U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center);
LLReflectionMap::LLReflectionMap()
{
}
LLReflectionMap::~LLReflectionMap()
{
if (mOcclusionQuery)
{
glDeleteQueries(1, &mOcclusionQuery);
}
}
void LLReflectionMap::update(U32 resolution, U32 face)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
@ -66,7 +77,7 @@ void LLReflectionMap::autoAdjustOrigin()
if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
{
mPriority = 1;
mPriority = 0;
// cast a ray towards 8 corners of bounding box
// nudge origin towards center of empty space
@ -150,7 +161,7 @@ void LLReflectionMap::autoAdjustOrigin()
}
else if (mViewerObject)
{
mPriority = 64;
mPriority = 1;
mOrigin.load3(mViewerObject->getPositionAgent().mV);
mRadius = mViewerObject->getScale().mV[0]*0.5f;
}
@ -245,3 +256,71 @@ bool LLReflectionMap::getBox(LLMatrix4& box)
return false;
}
bool LLReflectionMap::isActive()
{
return mCubeIndex != -1;
}
void LLReflectionMap::doOcclusion(const LLVector4a& eye)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
#if 1
// super sloppy, but we're doing an occlusion cull against a bounding cube of
// a bounding sphere, pad radius so we assume if the eye is within
// the bounding sphere of the bounding cube, the node is not culled
F32 dist = mRadius * F_SQRT3 + 1.f;
LLVector4a o;
o.setSub(mOrigin, eye);
bool do_query = false;
if (o.getLength3().getF32() < dist)
{ // eye is inside radius, don't attempt to occlude
mOccluded = false;
return;
}
if (mOcclusionQuery == 0)
{ // no query was previously issued, allocate one and issue
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - glGenQueries");
glGenQueries(1, &mOcclusionQuery);
do_query = true;
}
else
{ // query was previously issued, check it and only issue a new query
// if previous query is available
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - glGetQueryObject");
GLuint result = 0;
glGetQueryObjectuiv(mOcclusionQuery, GL_QUERY_RESULT_AVAILABLE, &result);
if (result > 0)
{
do_query = true;
glGetQueryObjectuiv(mOcclusionQuery, GL_QUERY_RESULT, &result);
mOccluded = result == 0;
mOcclusionPendingFrames = 0;
}
else
{
mOcclusionPendingFrames++;
}
}
if (do_query)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - push query");
glBeginQuery(GL_ANY_SAMPLES_PASSED, mOcclusionQuery);
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mOrigin.getF32ptr());
shader->uniform3f(LLShaderMgr::BOX_SIZE, mRadius, mRadius, mRadius);
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(LLViewerCamera::getInstance(), mOrigin));
glEndQuery(GL_ANY_SAMPLES_PASSED);
}
#endif
}

View File

@ -39,6 +39,8 @@ public:
// allocate an environment map of the given resolution
LLReflectionMap();
~LLReflectionMap();
// update this environment map
// resolution - size of cube map to generate
void update(U32 resolution, U32 face);
@ -64,6 +66,12 @@ public:
// return false if no bounding box (treat as sphere influence volume)
bool getBox(LLMatrix4& box);
// return true if this probe is active for rendering
bool isActive();
// perform occlusion query/readback
void doOcclusion(const LLVector4a& eye);
// point at which environment map was last generated from (in agent space)
LLVector4a mOrigin;
@ -97,6 +105,14 @@ public:
LLViewerObject* mViewerObject = nullptr;
// what priority should this probe have (higher is higher priority)
U32 mPriority = 1;
// currently only 0 or 1
// 0 - automatic probe
// 1 - manual probe
U32 mPriority = 0;
// occlusion culling state
GLuint mOcclusionQuery = 0;
bool mOccluded = false;
U32 mOcclusionPendingFrames = 0;
};

View File

@ -94,8 +94,8 @@ void LLReflectionMapManager::update()
if (!mRenderTarget.isComplete())
{
U32 color_fmt = GL_RGB16F;
U32 targetRes = mProbeResolution * 2; // super sample
U32 color_fmt = GL_RGB16;
U32 targetRes = mProbeResolution * 4; // super sample
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
}
@ -107,7 +107,7 @@ void LLReflectionMapManager::update()
mMipChain.resize(count);
for (int i = 0; i < count; ++i)
{
mMipChain[i].allocate(res, res, GL_RGBA16F);
mMipChain[i].allocate(res, res, GL_RGB16);
res /= 2;
}
}
@ -157,6 +157,7 @@ void LLReflectionMapManager::update()
LLReflectionMap* closestDynamic = nullptr;
LLReflectionMap* oldestProbe = nullptr;
LLReflectionMap* oldestOccluded = nullptr;
if (mUpdatingProbe != nullptr)
{
@ -179,12 +180,27 @@ void LLReflectionMapManager::update()
probe->mProbeIndex = i;
LLVector4a d;
if (!did_update &&
i < mReflectionProbeCount &&
(oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
if (probe->mOccluded)
{
oldestProbe = probe;
if (oldestOccluded == nullptr)
{
oldestOccluded = probe;
}
else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime)
{
oldestOccluded = probe;
}
}
else
{
if (!did_update &&
i < mReflectionProbeCount &&
(oldestProbe == nullptr ||
probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
{
oldestProbe = probe;
}
}
if (realtime &&
@ -240,6 +256,13 @@ void LLReflectionMapManager::update()
doProbeUpdate();
}
if (oldestOccluded)
{
// as far as this occluded probe is concerned, an origin/radius update is as good as a full update
oldestOccluded->autoAdjustOrigin();
oldestOccluded->mLastUpdateTime = gFrameTimeSeconds;
}
// update distance to camera for all probes
std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
}
@ -277,8 +300,11 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma
mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested
if (mProbes[i]->mCubeIndex != -1)
{
mProbes[i]->mProbeIndex = count;
maps[count++] = mProbes[i];
if (!mProbes[i]->mOccluded)
{
mProbes[i]->mProbeIndex = count;
maps[count++] = mProbes[i];
}
}
else
{
@ -449,7 +475,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
//only render sky, water, terrain, and clouds
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY,
LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES);
LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES);
probe->update(mRenderTarget.getWidth(), face);
@ -476,8 +502,6 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
// downsample to placeholder map
{
gReflectionMipProgram.bind();
gGL.matrixMode(gGL.MM_MODELVIEW);
gGL.pushMatrix();
gGL.loadIdentity();
@ -489,13 +513,41 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.flush();
U32 res = mProbeResolution * 2;
S32 mips = log2((F32)mProbeResolution) + 0.5f;
S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE);
static LLStaticHashedString resScale("resScale");
static LLStaticHashedString direction("direction");
static LLStaticHashedString znear("znear");
static LLStaticHashedString zfar("zfar");
LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen;
LLRenderTarget* depth_rt = &gPipeline.mAuxillaryRT.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();
}
S32 mips = log2((F32)mProbeResolution) + 0.5f;
gReflectionMipProgram.bind();
S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
for (int i = 0; i < mMipChain.size(); ++i)
{
@ -503,7 +555,6 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
mMipChain[i].bindTarget();
if (i == 0)
{
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
}
else
@ -511,50 +562,12 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
}
gGL.getTexUnit(depthChannel)->bind(depth_rt, true);
static LLStaticHashedString resScale("resScale");
static LLStaticHashedString znear("znear");
static LLStaticHashedString zfar("zfar");
gReflectionMipProgram.uniform1f(resScale, (F32) (1 << i));
gReflectionMipProgram.uniform1f(znear, probe->getNearClip());
gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP);
// <FS:Ansariel> Remove QUADS rendering mode
//gGL.begin(gGL.QUADS);
//gGL.texCoord2f(0, 0);
//gGL.vertex2f(-1, -1);
//gGL.texCoord2f(1.f, 0);
//gGL.vertex2f(1, -1);
//gGL.texCoord2f(1.f, 1.f);
//gGL.vertex2f(1, 1);
//gGL.texCoord2f(0, 1.f);
//gGL.vertex2f(-1, 1);
//gGL.end();
gGL.begin(gGL.TRIANGLES);
gGL.texCoord2f(0, 0);
gGL.vertex2f(-1, -1);
gGL.texCoord2f(1.f, 0);
gGL.vertex2f(1, -1);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex2f(1, 1);
gGL.texCoord2f(0, 0);
gGL.vertex2f(-1, -1);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex2f(1, 1);
gGL.texCoord2f(0, 1.f);
gGL.vertex2f(-1, 1);
gGL.end();
// </FS:Ansariel>
gGL.flush();
gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
res /= 2;
S32 mip = i - (mMipChain.size() - mips);
@ -579,7 +592,6 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.popMatrix();
gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(depthChannel)->unbind(LLTexUnit::TT_TEXTURE);
gReflectionMipProgram.unbind();
}
@ -802,7 +814,7 @@ void LLReflectionMapManager::updateUniforms()
F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale);
F32 ambscale = gCubeSnapshot && !isRadiancePass() ? 0.f : 1.f;
F32 radscale = gCubeSnapshot && !isRadiancePass() ? 0.5f : 1.f;
for (auto* refmap : mReflectionMaps)
{
@ -817,8 +829,12 @@ void LLReflectionMapManager::updateUniforms()
llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged
{
//LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refSphere");
if (refmap->mViewerObject)
{ // have active manual probes live-track the object they're associated with
refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV);
refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f;
}
modelview.affineTransform(refmap->mOrigin, oa);
rpd.refSphere[count].set(oa.getF32ptr());
rpd.refSphere[count].mV[3] = refmap->mRadius;
@ -836,7 +852,7 @@ void LLReflectionMapManager::updateUniforms()
rpd.refIndex[count][3] = -rpd.refIndex[count][3];
}
rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, 0.f, 0.f, 0.f);
rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, radscale, 0.f, 0.f);
S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
{
@ -850,7 +866,7 @@ void LLReflectionMapManager::updateUniforms()
}
GLint idx = neighbor->mProbeIndex;
if (idx == -1)
if (idx == -1 || neighbor->mOccluded)
{
continue;
}
@ -999,7 +1015,7 @@ void LLReflectionMapManager::initReflectionMaps()
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, 4, mReflectionProbeCount + 2);
mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2);
mIrradianceMaps = new LLCubeMapArray();
mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 4, mReflectionProbeCount, FALSE);
@ -1052,3 +1068,17 @@ void LLReflectionMapManager::cleanup()
// note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state
initCubeFree();
}
void LLReflectionMapManager::doOcclusion()
{
LLVector4a eye;
eye.load3(LLViewerCamera::instance().getOrigin().mV);
for (auto& probe : mProbes)
{
if (probe != nullptr && probe != mDefaultProbe)
{
probe->doOcclusion(eye);
}
}
}

View File

@ -96,6 +96,9 @@ public:
// True if currently updating a radiance map, false if currently updating an irradiance map
bool isRadiancePass() { return mRadiancePass; }
// perform occlusion culling on all active reflection probes
void doOcclusion();
private:
friend class LLPipeline;

View File

@ -2027,12 +2027,6 @@ void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
asset_id = mItem->getAssetUUID();
}
if (asset_id.notNull() && !objectp->hasRenderMaterialParams())
{
// make sure param section exists
objectp->setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, TRUE, false /*prevent an update*/);
}
// Blank out most override data on the object and send to server
objectp->setRenderMaterialID(te, asset_id);
@ -2061,25 +2055,6 @@ void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
return false;
}
LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
if (param_block)
{
// To not cause multiple competing request that modify
// same param field send update only once per object
if (param_block->isEmpty())
{
object->setHasRenderMaterialParams(false);
}
else if (object->hasRenderMaterialParams())
{
object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
}
else
{
object->setHasRenderMaterialParams(true);
}
}
if (!mItem)
{
// 1 particle effect per object
@ -2295,14 +2270,13 @@ void LLSelectMgr::selectionRevertGLTFMaterials()
{
// Restore base material
LLUUID asset_id = nodep->mSavedGLTFMaterialIds[te];
objectp->setRenderMaterialID(te, asset_id, false /*wait for bulk update*/);
// Update material locally
objectp->setRenderMaterialID(te, asset_id, false /*wait for LLGLTFMaterialList update*/);
objectp->setTEGLTFMaterialOverride(te, nodep->mSavedGLTFOverrideMaterials[te]);
// todo: make sure this does not cause race condition with setRenderMaterialID
// when we are reverting from null id to non null plus override
if (te < (S32)nodep->mSavedGLTFOverrideMaterials.size()
&& nodep->mSavedGLTFOverrideMaterials[te].notNull()
&& asset_id.notNull())
// Enqueue update to server
if (asset_id.notNull())
{
// Restore overrides
LLGLTFMaterialList::queueModify(objectp, te, nodep->mSavedGLTFOverrideMaterials[te]);
@ -2318,38 +2292,6 @@ void LLSelectMgr::selectionRevertGLTFMaterials()
}
} setfunc(mSelectedObjects);
getSelection()->applyToTEs(&setfunc);
struct g : public LLSelectedObjectFunctor
{
virtual bool apply(LLViewerObject* object)
{
if (object && !object->permModify())
{
return false;
}
LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
if (param_block)
{
if (param_block->isEmpty())
{
object->setHasRenderMaterialParams(false);
}
else if (object->hasRenderMaterialParams())
{
object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
}
else
{
object->setHasRenderMaterialParams(true);
}
}
object->sendTEUpdate();
return true;
}
} sendfunc;
getSelection()->applyToObjects(&sendfunc);
}
void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id)

View File

@ -716,15 +716,15 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
LLColor3 ambient(getTotalAmbient());
shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV));
if (radiance_pass)
{ // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue)
shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, LLVector3::zero.mV);
shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3::zero.mV);
}
else
{
shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor() / 3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT
shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV));
}
shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY

View File

@ -1722,8 +1722,6 @@ void renderOctree(LLSpatialGroup* group)
}
face->getVertexBuffer()->setBuffer();
//drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
// (face->mExtents[1]-face->mExtents[0])*0.5f);
face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
}
}
@ -1748,145 +1746,20 @@ void renderOctree(LLSpatialGroup* group)
LLVector4a fudge;
fudge.splat(0.001f);
//LLVector4a size = group->mObjectBounds[1];
//size.mul(1.01f);
//size.add(fudge);
//{
// LLGLDepthTest depth(GL_TRUE, GL_FALSE);
// drawBox(group->mObjectBounds[0], fudge);
//}
gGL.setSceneBlendType(LLRender::BT_ALPHA);
//if (group->mBuilt <= 0.f)
{
//draw opaque outline
//gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
//drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
gGL.diffuseColor4f(0,1,1,1);
const LLVector4a* bounds = group->getBounds();
drawBoxOutline(bounds[0], bounds[1]);
//draw bounding box for draw info
/*if (group->getSpatialPartition()->mRenderByGroup)
{
gGL.diffuseColor4f(1.0f, 0.75f, 0.25f, 0.6f);
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
{
for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
LLDrawInfo* draw_info = *j;
LLVector4a center;
center.setAdd(draw_info->mExtents[1], draw_info->mExtents[0]);
center.mul(0.5f);
LLVector4a size;
size.setSub(draw_info->mExtents[1], draw_info->mExtents[0]);
size.mul(0.5f);
drawBoxOutline(center, size);
}
}
}*/
}
// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
// gGL.diffuseColor4f(0,1,0,1);
// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
}
std::set<LLSpatialGroup*> visible_selected_groups;
void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
{
/*LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
LLGLEnable cull(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);*/
/*BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
!group->isEmpty();
if (render_objects)
{
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
LLGLDisable blend(GL_BLEND);
gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
gGL.setLineWidth(4.f); // <FS> Line width OGL core profile fix by Rye Mutt
gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false);
gGL.setLineWidth(1.f); // <FS> Line width OGL core profile fix by Rye Mutt
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
bool selected = false;
for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter)
{
LLDrawable* drawable = *iter;
if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected())
{
selected = true;
break;
}
}
if (selected)
{ //store for rendering occlusion volume as overlay
visible_selected_groups.insert(group);
}
}*/
/*if (render_objects)
{
LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
gGL.diffuseColor4f(0, 0.5f, 0, 0.5f);
gGL.diffuseColor4f(0, 0.5f, 0, 0.5f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
}
{
LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL);
if (render_objects)
{
gGL.diffuseColor4f(0.f, 0.5f, 0.f,1.f);
gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (render_objects)
{
gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f);
gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
bool selected = false;
for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter)
{
LLDrawable* drawable = *iter;
if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected())
{
selected = true;
break;
}
}
if (selected)
{ //store for rendering occlusion volume as overlay
visible_selected_groups.insert(group);
}
}
}*/
}
void renderXRay(LLSpatialGroup* group, LLCamera* camera)
{
@ -3309,23 +3182,6 @@ public:
renderOctree(group);
stop_glerror();
}
//render visibility wireframe
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
group->rebuildGeom();
group->rebuildMesh();
gGL.flush();
gGL.pushMatrix();
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
renderVisibility(group, mCamera);
stop_glerror();
gGLLastMatrix = NULL;
gGL.popMatrix();
gGL.diffuseColor4f(1,1,1,1);
}
}
}
@ -3434,6 +3290,7 @@ public:
renderAgentTarget(avatar);
}
#if 0
if (gDebugGL)
{
for (U32 i = 0; i < drawable->getNumFaces(); ++i)
@ -3459,6 +3316,7 @@ public:
}
}
}
#endif
}
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)

View File

@ -697,6 +697,7 @@ private:
static LLFace** sNormFaces[2];
static LLFace** sSpecFaces[2];
static LLFace** sNormSpecFaces[2];
static LLFace** sPbrFaces[2];
static LLFace** sAlphaFaces[2];
};

View File

@ -289,7 +289,9 @@ void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
{
mCanApplyImmediately = b;
getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately);
LLUICtrl *apply_checkbox = getChild<LLUICtrl>("apply_immediate_check");
apply_checkbox->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
apply_checkbox->setEnabled(mCanApplyImmediately);
}
void LLFloaterTexturePicker::stopUsingPipette()
@ -585,7 +587,7 @@ BOOL LLFloaterTexturePicker::postBuild()
mNoCopyTextureSelected = FALSE;
getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview"));
getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately);
@ -973,7 +975,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem
if(!mPreviewSettingChanged)
{
mCanPreview = gSavedSettings.getBOOL("TextureLivePreview");
mCanPreview = mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
}
else
{
@ -1288,7 +1290,7 @@ void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data
if (!self->mPreviewSettingChanged)
{
self->mCanPreview = gSavedSettings.getBOOL("TextureLivePreview");
self->mCanPreview = self->mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
}
else
{
@ -1309,7 +1311,7 @@ void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply)
getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview);
mCanApply = can_apply;
mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false;
mCanPreview = can_preview ? (mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")) : false;
mPreviewSettingChanged = true;
}

View File

@ -309,48 +309,48 @@ bool LLTinyGLTFHelper::getMaterialFromFile(
if (base_color_tex)
{
base_color_tex->addTextureStats(64.f * 64.f, TRUE);
material->mBaseColorId = base_color_tex->getID();
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = base_color_tex->getID();
material->mBaseColorTexture = base_color_tex;
}
else
{
material->mBaseColorId = LLUUID::null;
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = LLUUID::null;
material->mBaseColorTexture = nullptr;
}
if (normal_tex)
{
normal_tex->addTextureStats(64.f * 64.f, TRUE);
material->mNormalId = normal_tex->getID();
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = normal_tex->getID();
material->mNormalTexture = normal_tex;
}
else
{
material->mNormalId = LLUUID::null;
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = LLUUID::null;
material->mNormalTexture = nullptr;
}
if (mr_tex)
{
mr_tex->addTextureStats(64.f * 64.f, TRUE);
material->mMetallicRoughnessId = mr_tex->getID();
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = mr_tex->getID();
material->mMetallicRoughnessTexture = mr_tex;
}
else
{
material->mMetallicRoughnessId = LLUUID::null;
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = LLUUID::null;
material->mMetallicRoughnessTexture = nullptr;
}
if (emissive_tex)
{
emissive_tex->addTextureStats(64.f * 64.f, TRUE);
material->mEmissiveId = emissive_tex->getID();
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = emissive_tex->getID();
material->mEmissiveTexture = emissive_tex;
}
else
{
material->mEmissiveId = LLUUID::null;
material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = LLUUID::null;
material->mEmissiveTexture = nullptr;
}

View File

@ -2129,11 +2129,6 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
{
return ACCEPT_NO_LOCKED;
}
//If texture !copyable don't texture or you'll never get it back.
if(!item->getPermissions().allowCopyBy(gAgent.getID()))
{
return ACCEPT_NO;
}
if (cargo_type == DAD_TEXTURE)
{

View File

@ -233,14 +233,7 @@ bool handleSetShaderChanged(const LLSD& newvalue)
if (gPipeline.isInit())
{
// ALM depends onto atmospheric shaders, state might have changed
bool old_state = LLPipeline::sRenderDeferred;
LLPipeline::refreshCachedSettings();
if (old_state != LLPipeline::sRenderDeferred)
{
gPipeline.releaseGLBuffers();
gPipeline.createGLBuffers();
gPipeline.resetVertexBuffers();
}
}
// else, leave terrain detail as is
@ -290,7 +283,6 @@ bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
gPipeline.updateRenderTransparentWater();
gPipeline.releaseGLBuffers();
gPipeline.createGLBuffers();
gPipeline.resetVertexBuffers();
LLViewerShaderMgr::instance()->setShaders();
}
LLWorld::getInstance()->updateWaterObjects();
@ -489,15 +481,6 @@ static bool handleWLSkyDetailChanged(const LLSD&)
return true;
}
static bool handleResetVertexBuffersChanged(const LLSD&)
{
if (gPipeline.isInit())
{
gPipeline.resetVertexBuffers();
}
return true;
}
static bool handleRepartition(const LLSD&)
{
if (gPipeline.isInit())
@ -528,7 +511,6 @@ static bool handleReflectionProbeDetailChanged(const LLSD& newvalue)
LLPipeline::refreshCachedSettings();
gPipeline.releaseGLBuffers();
gPipeline.createGLBuffers();
gPipeline.resetVertexBuffers();
LLViewerShaderMgr::instance()->setShaders();
}
return true;
@ -1146,7 +1128,6 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged);
// DEPRECATED -- setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged);
setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged);
@ -1159,23 +1140,18 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "RenderMaxPartCount", handleMaxPartCountChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDynamicLOD", handleRenderDynamicLODChanged);
setting_setup_signal_listener(gSavedSettings, "RenderLocalLights", handleRenderLocalLightsChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDebugTextureBind", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaDeferred", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaNonDeferred", handleResetVertexBuffersChanged);
// DEPRECATED - setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged);
setting_setup_signal_listener(gSavedSettings, "RenderMaxVBOSize", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged);
setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged);
// [SL:KB] - Patch: Settings-RenderResolutionMultiplier | Checked: Catznip-5.4
setting_setup_signal_listener(gSavedSettings, "RenderResolutionMultiplier", handleRenderResolutionDivisorChanged);
// [/SL:KB]
// DEPRECATED - setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged);
setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged);
setting_setup_signal_listener(gSavedSettings, "RenderReflectionsEnabled", handleReflectionProbeDetailChanged);
setting_setup_signal_listener(gSavedSettings, "RenderScreenSpaceReflections", handleReflectionProbeDetailChanged);
setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderTonemapper", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged);
setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged);
setting_setup_signal_listener(gSavedSettings, "ChatConsoleFontSize", handleChatFontSizeChanged);
@ -1199,11 +1175,6 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "MuteVoice", handleAudioVolumeChanged);
setting_setup_signal_listener(gSavedSettings, "MuteAmbient", handleAudioVolumeChanged);
setting_setup_signal_listener(gSavedSettings, "MuteUI", handleAudioVolumeChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVBOEnable", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderUseVAO", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderVBOMappingDisable", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderUseStreamVBO", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "RenderPreferStreamDraw", handleResetVertexBuffersChanged);
setting_setup_signal_listener(gSavedSettings, "WLSkyDetail", handleWLSkyDetailChanged);
setting_setup_signal_listener(gSavedSettings, "JoystickAxis0", handleJoystickChanged);
setting_setup_signal_listener(gSavedSettings, "JoystickAxis1", handleJoystickChanged);

View File

@ -103,9 +103,6 @@ F32 gSavedDrawDistance = 0.0f;
F32 gLastDrawDistanceStep = 0.0f;
// <FS:Ansariel> FIRE-12004: Attachments getting lost on TP
LLFrameTimer gPostTeleportFinishKillObjectDelayTimer;
// <FS:Ansariel> FIRE-15917 / FIRE-31906: Mesh attachments sometimes vanish after teleports
bool postTeleportResetVB = false;
LLFrameTimer postTeleportResetVBTimer;
BOOL gForceRenderLandFence = FALSE;
BOOL gDisplaySwapBuffers = FALSE;
@ -313,26 +310,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLGLState::checkStates();
stop_glerror();
gPipeline.disableLights();
// <FS:Ansariel> FIRE-15917 / FIRE-31906: Mesh attachments sometimes vanish after teleports
static LLCachedControl<F32> teleportArrivalDelay(gSavedSettings, "TeleportArrivalDelay");
if (postTeleportResetVB && postTeleportResetVBTimer.getElapsedTimeF32() > teleportArrivalDelay())
{
LL_INFOS("Teleport") << "Resetting Vertex Buffers after TP finished" << LL_ENDL;
postTeleportResetVB = false;
postTeleportResetVBTimer.stop();
gPipeline.resetVertexBuffers();
}
// </FS:Ansariel>
//reset vertex buffers if needed
gPipeline.doResetVertexBuffers();
stop_glerror();
// Don't draw if the window is hidden or minimized.
// In fact, must explicitly check the minimized state before drawing.
// Attempting to draw into a minimized window causes a GL error. JC
@ -549,11 +528,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
// <FS:Ansariel> FIRE-12004: Attachments getting lost on TP
gPostTeleportFinishKillObjectDelayTimer.reset();
// <FS:Ansariel> FIRE-15917 / FIRE-31906: Mesh attachments sometimes vanish after teleports
postTeleportResetVB = true;
postTeleportResetVBTimer.start();
// </FS:Ansariel>
break;
case LLAgent::TELEPORT_ARRIVING:

View File

@ -10951,7 +10951,6 @@ BOOL get_visibility(void* user_data)
return viewp->getVisible();
}
// TomY TODO: Get rid of these?
class LLViewShowHoverTips : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -10970,7 +10969,6 @@ class LLViewCheckShowHoverTips : public view_listener_t
}
};
// TomY TODO: Get rid of these?
class LLViewHighlightTransparent : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -10979,7 +10977,6 @@ class LLViewHighlightTransparent : public view_listener_t
// [RLVa:KB] - @edit and @viewtransparent
LLDrawPoolAlpha::sShowDebugAlpha = (!LLDrawPoolAlpha::sShowDebugAlpha) && (RlvActions::canHighlightTransparent());
// [/RLVa:KB]
gPipeline.resetVertexBuffers();
return true;
}
};
@ -10998,7 +10995,6 @@ class LLViewHighlightTransparentRigged : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
LLDrawPoolAlpha::sShowDebugAlphaRigged = !LLDrawPoolAlpha::sShowDebugAlphaRigged;
gPipeline.resetVertexBuffers();
return true;
}
};

View File

@ -558,19 +558,19 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3
// Todo: make it account for possibility of same texture in different
// materials and even in scope of same material
S32 texture_count = 0;
if (material->mBaseColorId.notNull())
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull())
{
texture_count++;
}
if (material->mMetallicRoughnessId.notNull())
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull())
{
texture_count++;
}
if (material->mNormalId.notNull())
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull())
{
texture_count++;
}
if (material->mEmissiveId.notNull())
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull())
{
texture_count++;
}

View File

@ -3705,8 +3705,6 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
// Teleport is finished; it can't be cancelled now.
gViewerWindow->setProgressCancelButtonVisible(FALSE);
gPipeline.doResetVertexBuffers(true);
// Do teleport effect for where you're leaving
// VEFFECT: TeleportStart
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);

View File

@ -5165,10 +5165,10 @@ void LLViewerObject::updateTEMaterialTextures(U8 te)
if (mat != nullptr)
{
mat->mBaseColorTexture = fetch_texture(mat->mBaseColorId);
mat->mNormalTexture = fetch_texture(mat->mNormalId);
mat->mMetallicRoughnessTexture = fetch_texture(mat->mMetallicRoughnessId);
mat->mEmissiveTexture= fetch_texture(mat->mEmissiveId);
mat->mBaseColorTexture = fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);
mat->mNormalTexture = fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);
mat->mMetallicRoughnessTexture = fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);
mat->mEmissiveTexture= fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
}
}
@ -6470,6 +6470,11 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL
{
if (local_origin)
{
// *NOTE: Do not send the render material ID in this way as it will get
// out-of-sync with other sent client data.
// See LLViewerObject::setRenderMaterialID and LLGLTFMaterialList
llassert(param_type != LLNetworkData::PARAMS_RENDER_MATERIAL);
LLViewerRegion* regionp = getRegion();
if(!regionp) return;
@ -7432,6 +7437,15 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat
});
}
// predictively update LLRenderMaterialParams (don't wait for server)
if (param_block)
{ // update existing parameter block
for (S32 te = start_idx; te < end_idx; ++te)
{
param_block->setMaterial(te, id);
}
}
if (update_server)
{
// update via ModifyMaterialParams cap (server will echo back changes)
@ -7443,27 +7457,6 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat
LLGLTFMaterialList::queueApply(this, te, id);
}
}
// predictively update LLRenderMaterialParams (don't wait for server)
if (param_block)
{ // update existing parameter block
for (S32 te = start_idx; te < end_idx; ++te)
{
param_block->setMaterial(te, id);
}
if (update_server)
{
// If 'in use' changes, it will send an update itself.
bool in_use_changed = setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, !param_block->isEmpty(), true);
if (!in_use_changed)
{
// In use didn't change, but the parameter did, send an update
parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, param_block, !param_block->isEmpty(), true);
}
}
}
}
void LLViewerObject::setRenderMaterialIDs(const LLUUID& id)

View File

@ -870,6 +870,7 @@ LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctre
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
{
mOcclusionQuery[i] = 0;
mOcclusionCheckCount[i] = 0;
mOcclusionIssued[i] = 0;
mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
mVisible[i] = 0;
@ -1127,10 +1128,12 @@ void LLOcclusionCullingGroup::checkOcclusion()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query available");
glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE, &available);
mOcclusionCheckCount[LLViewerCamera::sCurCameraID]++;
}
if (available)
if (available || mOcclusionCheckCount[LLViewerCamera::sCurCameraID] > 4)
{
mOcclusionCheckCount[LLViewerCamera::sCurCameraID] = 0;
GLuint query_result; // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query result");
@ -1140,20 +1143,6 @@ void LLOcclusionCullingGroup::checkOcclusion()
sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
#endif
#if 0 // (12/2021) occasional false-negative occlusion tests produce water reflection errors, SL-16461
// If/when water occlusion queries become 100% reliable, re-enable this optimization
if (LLPipeline::RENDER_TYPE_WATER == mSpatialPartition->mDrawableType)
{
// Note any unoccluded water, for deciding on reflection/distortion passes
// (If occlusion is disabled, these are set within LLDrawPoolWater::render)
if (query_result > 0)
{
LLDrawPoolWater::sNeedsReflectionUpdate = TRUE;
LLDrawPoolWater::sNeedsDistortionUpdate = TRUE;
}
}
#endif
if (query_result > 0)
{
clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);

View File

@ -336,6 +336,7 @@ protected:
LLViewerOctreePartition* mSpatialPartition;
U32 mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
U32 mOcclusionCheckCount[LLViewerCamera::NUM_CAMERAS];
public:
static std::set<U32> sPendingQueries;

View File

@ -73,6 +73,7 @@ LLGLSLShader gSkinnedOcclusionProgram;
LLGLSLShader gOcclusionCubeProgram;
LLGLSLShader gGlowCombineProgram;
LLGLSLShader gReflectionMipProgram;
LLGLSLShader gGaussianProgram;
LLGLSLShader gRadianceGenProgram;
LLGLSLShader gIrradianceGenProgram;
LLGLSLShader gGlowCombineFXAAProgram;
@ -235,7 +236,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderLevel(SHADER_COUNT, 0),
mMaxAvatarShaderLevel(0)
{
/// Make sure WL Sky is the first program
//ONLY shaders that need WL Param management should be added here
mShaderList.push_back(&gAvatarProgram);
mShaderList.push_back(&gWaterProgram);
@ -291,6 +291,8 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredPBRAlphaProgram);
mShaderList.push_back(&gHUDPBRAlphaProgram);
mShaderList.push_back(&gDeferredSkinnedPBRAlphaProgram);
mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma
}
LLViewerShaderMgr::~LLViewerShaderMgr()
@ -377,9 +379,6 @@ void LLViewerShaderMgr::setShaders()
LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow");
//hack to reset buffers that change behavior with shaders
gPipeline.resetVertexBuffers();
if (gViewerWindow)
{
gViewerWindow->setCursor(UI_CURSOR_WAIT);
@ -655,6 +654,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()
shaders.push_back( make_pair( "environment/srgbF.glsl", 1 ) );
shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) );
shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) );
shaders.push_back( make_pair( "deferred/textureUtilV.glsl", 1 ) );
if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)
{
shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) );
@ -1334,6 +1334,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueV.glsl", GL_VERTEX_SHADER));
gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueF.glsl", GL_FRAGMENT_SHADER));
gDeferredPBROpaqueProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredPBROpaqueProgram.clearPermutations();
success = make_rigged_variant(gDeferredPBROpaqueProgram, gDeferredSkinnedPBROpaqueProgram);
if (success)
@ -1648,8 +1649,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSunProgram.mFeatures.hasShadows = true;
gDeferredSunProgram.mFeatures.hasAmbientOcclusion = use_ao;
gDeferredSunProgram.mName = "Deferred Sun Shader";
gDeferredSunProgram.mShaderFiles.clear();
gDeferredSunProgram.mShaderFiles.clear();
gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER));
gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER));
gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
@ -2532,6 +2532,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true;
gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true;
gDeferredPostGammaCorrectProgram.mShaderFiles.clear();
gDeferredPostGammaCorrectProgram.clearPermutations();
U32 tonemapper = gSavedSettings.getU32("RenderTonemapper");
if (tonemapper == 1)
{
gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_ACES_NARKOWICZ", "1");
}
else if (tonemapper == 2)
{
gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_ACES_HILL_EXPOSURE_BOOST", "1");
}
else
{
gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_LINEAR", "1");
}
gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
@ -3202,12 +3216,20 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/reflectionmipF.glsl", GL_FRAGMENT_SHADER));
gReflectionMipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gReflectionMipProgram.createShader(NULL, NULL);
if (success)
{
gReflectionMipProgram.bind();
gReflectionMipProgram.uniform1i(sScreenMap, 0);
gReflectionMipProgram.unbind();
}
}
if (success)
{
gGaussianProgram.mName = "Reflection Mip Shader";
gGaussianProgram.mFeatures.isDeferred = true;
gGaussianProgram.mFeatures.hasGamma = true;
gGaussianProgram.mFeatures.hasAtmospherics = true;
gGaussianProgram.mFeatures.calculatesAtmospherics = true;
gGaussianProgram.mShaderFiles.clear();
gGaussianProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER));
gGaussianProgram.mShaderFiles.push_back(make_pair("interface/gaussianF.glsl", GL_FRAGMENT_SHADER));
gGaussianProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gGaussianProgram.createShader(NULL, NULL);
}
if (success && gGLManager.mHasCubeMapArray)

View File

@ -151,6 +151,7 @@ extern LLGLSLShader gOcclusionProgram;
extern LLGLSLShader gOcclusionCubeProgram;
extern LLGLSLShader gGlowCombineProgram;
extern LLGLSLShader gReflectionMipProgram;
extern LLGLSLShader gGaussianProgram;
extern LLGLSLShader gRadianceGenProgram;
extern LLGLSLShader gIrradianceGenProgram;
extern LLGLSLShader gGlowCombineFXAAProgram;

View File

@ -1993,18 +1993,12 @@ bool LLViewerFetchedTexture::updateFetch()
{
mIsFetching = FALSE;
mLastFetchState = -1;
setDebugText("");
mLastPacketTimer.reset();
}
else
{
mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
/*if (mFetchState != mLastFetchState)
{
setDebugText(LLTextureFetch::getStateString(mFetchState));
mLastFetchState = mFetchState;
}*/
}
// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)

View File

@ -755,18 +755,8 @@ void LLVOVolume::animateTextures()
continue;
}
if (!(result & LLViewerTextureAnim::ROTATE))
{
te->getRotation(&rot);
}
if (!(result & LLViewerTextureAnim::TRANSLATE))
{
te->getOffset(&off_s,&off_t);
}
if (!(result & LLViewerTextureAnim::SCALE))
{
te->getScale(&scale_s, &scale_t);
}
LLGLTFMaterial *gltf_mat = te->getGLTFRenderMaterial();
const bool is_pbr = gltf_mat != nullptr;
if (!facep->mTextureMatrix)
{
@ -775,22 +765,65 @@ void LLVOVolume::animateTextures()
LLMatrix4& tex_mat = *facep->mTextureMatrix;
tex_mat.setIdentity();
LLVector3 trans ;
trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
if (!is_pbr)
{
if (!(result & LLViewerTextureAnim::ROTATE))
{
te->getRotation(&rot);
}
if (!(result & LLViewerTextureAnim::TRANSLATE))
{
te->getOffset(&off_s,&off_t);
}
if (!(result & LLViewerTextureAnim::SCALE))
{
te->getScale(&scale_s, &scale_t);
}
LLVector3 scale(scale_s, scale_t, 1.f);
LLQuaternion quat;
quat.setQuat(rot, 0, 0, -1.f);
tex_mat.rotate(quat);
LLVector3 trans ;
LLMatrix4 mat;
mat.initAll(scale, LLQuaternion(), LLVector3());
tex_mat *= mat;
tex_mat.translate(trans);
trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
LLVector3 scale(scale_s, scale_t, 1.f);
LLQuaternion quat;
quat.setQuat(rot, 0, 0, -1.f);
tex_mat.rotate(quat);
LLMatrix4 mat;
mat.initAll(scale, LLQuaternion(), LLVector3());
tex_mat *= mat;
tex_mat.translate(trans);
}
else
{
// For PBR materials, use Blinn-Phong rotation as hint for
// translation direction. In a Blinn-Phong material, the
// translation direction would be a byproduct the texture
// transform.
F32 rot_frame;
te->getRotation(&rot_frame);
tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
LLQuaternion quat;
quat.setQuat(rot, 0, 0, -1.f);
tex_mat.rotate(quat);
LLMatrix4 mat;
LLVector3 scale(scale_s, scale_t, 1.f);
mat.initAll(scale, LLQuaternion(), LLVector3());
tex_mat *= mat;
LLVector3 off(off_s, off_t, 0.f);
off.rotVec(rot_frame, 0, 0, 1.f);
tex_mat.translate(off);
tex_mat.translate(LLVector3(0.5f, 0.5f, 0.f));
}
}
}
else
@ -5374,6 +5407,7 @@ LLFace** LLVolumeGeometryManager::sSimpleFaces[2] = { NULL };
LLFace** LLVolumeGeometryManager::sNormFaces[2] = { NULL };
LLFace** LLVolumeGeometryManager::sSpecFaces[2] = { NULL };
LLFace** LLVolumeGeometryManager::sNormSpecFaces[2] = { NULL };
LLFace** LLVolumeGeometryManager::sPbrFaces[2] = { NULL };
LLFace** LLVolumeGeometryManager::sAlphaFaces[2] = { NULL };
LLVolumeGeometryManager::LLVolumeGeometryManager()
@ -5410,6 +5444,7 @@ void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount)
sNormFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
sSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
sNormSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
sPbrFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
sAlphaFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
}
}
@ -5424,6 +5459,7 @@ void LLVolumeGeometryManager::freeFaces()
ll_aligned_free<64>(sNormFaces[i]);
ll_aligned_free<64>(sSpecFaces[i]);
ll_aligned_free<64>(sNormSpecFaces[i]);
ll_aligned_free<64>(sPbrFaces[i]);
ll_aligned_free<64>(sAlphaFaces[i]);
sFullbrightFaces[i] = NULL;
@ -5432,6 +5468,7 @@ void LLVolumeGeometryManager::freeFaces()
sNormFaces[i] = NULL;
sSpecFaces[i] = NULL;
sNormSpecFaces[i] = NULL;
sPbrFaces[i] = NULL;
sAlphaFaces[i] = NULL;
}
}
@ -5883,6 +5920,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
U32 norm_count[2] = { 0 };
U32 spec_count[2] = { 0 };
U32 normspec_count[2] = { 0 };
U32 pbr_count[2] = { 0 };
static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
static LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536);
@ -6215,8 +6253,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
if (gltf_mat != nullptr)
{
// all gltf materials have all vertex attributes for now
add_face(sNormSpecFaces, normspec_count, facep);
add_face(sPbrFaces, pbr_count, facep);
}
else
{
@ -6315,6 +6352,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2;
U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2;
U32 pbr_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TANGENT;
if (emissive)
{ //emissive faces are present, include emissive byte to preserve batching
simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE;
@ -6324,6 +6363,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE;
normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE;
spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE;
pbr_mask = pbr_mask | LLVertexBuffer::MAP_EMISSIVE;
}
BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
@ -6354,6 +6394,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[i], norm_count[i], FALSE, FALSE, rigged);
geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[i], spec_count[i], FALSE, FALSE, rigged);
geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[i], normspec_count[i], FALSE, FALSE, rigged);
geometryBytes += genDrawInfo(group, pbr_mask | extra_mask, sPbrFaces[i], pbr_count[i], FALSE, FALSE, rigged);
// for rigged set, add weights and disable alpha sorting (rigged items use depth buffer)
extra_mask |= LLVertexBuffer::MAP_WEIGHT4;
@ -7051,7 +7092,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("facep->alpha -> invisible");
registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE);
}
else if (facep->canRenderAsMask())
else if (facep->canRenderAsMask() && !hud_group)
{
if (te->getFullbright() || LLPipeline::sNoAlpha)
{

View File

@ -424,22 +424,14 @@ void LLWorldMapView::draw()
S32 level = LLWorldMipmap::scaleToLevel(mMapScale);
LLLocalClipRect clip(getLocalRect());
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.matrixMode(LLRender::MM_MODELVIEW);
// Clear the background alpha to 0
gGL.flush();
gGL.setColorMask(false, true);
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_REPLACE);
gGL.color4f(0.0f, 0.0f, 0.0f, 0.0f);
gl_rect_2d(0, height, width, 0);
}
gGL.flush();
gGL.setColorMask(true, true);
// Draw background rectangle
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4fv(mBackgroundColor.mV);
gl_rect_2d(0, height, width, 0);
// Draw the image tiles
// <FS:CR> Aurora Sim
@ -452,10 +444,6 @@ void LLWorldMapView::draw()
#endif //OPENSIM
// </FS:CR> Aurora Sim
gGL.flush();
gGL.setColorMask(true, true);
// Draw per sim overlayed information (names, mature, offline...)
// <FS:Ansariel> Performance tweak
//for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin();
@ -508,7 +496,6 @@ void LLWorldMapView::draw()
if (info->isDown())
{
// Draw a transparent red square over down sims
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA);
gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@ -532,31 +519,13 @@ void LLWorldMapView::draw()
gGL.end();
// </FS:Ansariel>
}
// As part of the AO project, we no longer want to draw access indicators;
// it's too complicated to get all the rules straight and will only
// cause confusion.
/**********************
else if (!info->isPG() && gAgent.isTeen())
{
// If this is a mature region, and you are not, draw a line across it
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color3f(1.f, 0.f, 0.f);
gGL.begin(LLRender::LINES);
gGL.vertex2f(left, top);
gGL.vertex2f(right, bottom);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, top);
gGL.end();
}
**********************/
// <FS:CR> Aurora Sim
#ifdef OPENSIM
else if ((mapShowLandForSale && (level <= DRAW_LANDFORSALE_THRESHOLD)) || LLGridManager::getInstance()->isInAuroraSim())
#else
else if (mapShowLandForSale && (level <= DRAW_LANDFORSALE_THRESHOLD))
#endif //OPENSIM
{
// Draw the overlay image "Land for Sale / Land for Auction"
LLViewerFetchedTexture* overlayimage = info->getLandForSaleImage();
@ -576,7 +545,6 @@ void LLWorldMapView::draw()
// Draw something whenever we have enough info
if (overlayimage->hasGLTexture())
{
gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
gGL.getTexUnit(0)->bind(overlayimage);
gGL.color4f(1.f, 1.f, 1.f, 1.f);
// <FS:Ansariel> Remove QUADS rendering mode
@ -686,21 +654,6 @@ void LLWorldMapView::draw()
}
}
// Draw background rectangle
LLGLSUIDefault gls_ui;
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.flush();
gGL.blendFunc(LLRender::BF_ONE_MINUS_DEST_ALPHA, LLRender::BF_DEST_ALPHA);
gGL.color4fv( mBackgroundColor.mV );
gl_rect_2d(0, height, width, 0);
}
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_ALPHA);
// Draw item infos if we're not zoomed out too much and there's something to draw
if ((level <= DRAW_SIMINFO_THRESHOLD) && (mapShowInfohubs ||
mapShowTelehubs ||
@ -905,7 +858,6 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load
gGL.getTexUnit(0)->bind(simimage.get());
simimage->setAddressMode(LLTexUnit::TAM_CLAMP);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.color4f(1.f, 1.0f, 1.0f, 1.0f);
// <FS:Ansariel> Remove QUADS rendering mode
@ -963,8 +915,6 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load
// Used for debug only
void LLWorldMapView::drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right)
{
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
if (level == 1)
gGL.color3f(1.f, 0.f, 0.f); // red

View File

@ -376,7 +376,7 @@ bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
bool valid = true
&& target.addColorAttachment(GL_RGBA) // frag-data[1] specular OR PBR ORM
&& target.addColorAttachment(GL_RGBA16F) // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight
&& target.addColorAttachment(GL_RGBA); // frag_data[3] PBR emissive
&& target.addColorAttachment(GL_RGB16); // frag_data[3] PBR emissive
return valid;
}
@ -463,6 +463,7 @@ void LLPipeline::init()
getPool(LLDrawPool::POOL_MATERIALS);
getPool(LLDrawPool::POOL_GLOW);
getPool(LLDrawPool::POOL_GLTF_PBR);
getPool(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK);
resetFrameStats();
@ -731,8 +732,6 @@ void LLPipeline::destroyGL()
resetDrawOrders();
resetVertexBuffers();
releaseGLBuffers();
if (mMeshDirtyQueryObject)
@ -870,7 +869,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
gCubeSnapshot = TRUE;
mReflectionMapManager.initReflectionMaps();
mRT = &mAuxillaryRT;
U32 res = mReflectionMapManager.mProbeResolution * 2; //multiply by 2 because probes will be super sampled
U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled
allocateScreenBuffer(res, res, samples);
mRT = &mMainRT;
gCubeSnapshot = FALSE;
@ -1653,6 +1652,9 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
case LLDrawPool::POOL_GLTF_PBR:
poolp = mPBROpaquePool;
break;
case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK:
poolp = mPBRAlphaMaskPool;
break;
default:
llassert(0);
@ -2389,7 +2391,6 @@ bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
}
LLViewerCamera::sCurCameraID = saved_camera_id;
return res;
}
@ -2400,7 +2401,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, bool hud_att
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL);
LL_PROFILE_GPU_ZONE("updateCull"); // should always be zero GPU time, but drop a timer to flush stuff out
bool water_clip = !sRenderTransparentWater;
bool water_clip = !sRenderTransparentWater && !sRenderingHUDs;
if (water_clip)
{
@ -2550,19 +2551,33 @@ void LLPipeline::doOcclusion(LLCamera& camera)
LL_PROFILE_GPU_ZONE("doOcclusion");
llassert(!gCubeSnapshot);
if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot)
{
gGL.setColorMask(false, false);
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
LLGLDisable cull(GL_CULL_FACE);
gOcclusionCubeProgram.bind();
if (mCubeVB.isNull())
{ //cube VB will be used for issuing occlusion queries
mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX);
}
mCubeVB->setBuffer();
mReflectionMapManager.doOcclusion();
gOcclusionCubeProgram.unbind();
gGL.setColorMask(true, true);
}
if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested &&
(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck))
{
LLVertexBuffer::unbind();
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
gGL.setColorMask(true, false, false, false);
}
else
{
gGL.setColorMask(false, false);
}
gGL.setColorMask(false, false);
LLGLDisable blend(GL_BLEND);
LLGLDisable test(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@ -4118,7 +4133,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)
bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion;
setupHWLights(nullptr);
setupHWLights();
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools");
@ -4245,7 +4260,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE : 0);
calcNearbyLights(camera);
setupHWLights(NULL);
setupHWLights();
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.setColorMask(true, false);
@ -4850,7 +4865,7 @@ void LLPipeline::renderDebug()
mReflectionMapManager.renderDebug();
}
if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes"))
if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes") && !hud_only)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("probe debug display");
@ -4903,7 +4918,7 @@ void LLPipeline::renderDebug()
}
}
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !hud_only)
{
LLVertexBuffer::unbind();
@ -5355,6 +5370,19 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK:
if (mPBRAlphaMaskPool)
{
llassert(0);
LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Alpha Mask Pool" << LL_ENDL;
}
else
{
mPBRAlphaMaskPool = new_poolp;
}
break;
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL;
@ -5471,6 +5499,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mPBROpaquePool = NULL;
break;
case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK:
llassert(poolp == mPBRAlphaMaskPool);
mPBRAlphaMaskPool = NULL;
break;
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL;
@ -5614,7 +5647,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
if (LLPipeline::sReflectionRender || gCubeSnapshot)
if (LLPipeline::sReflectionRender || gCubeSnapshot || LLPipeline::sRenderingHUDs)
{
return;
}
@ -5795,11 +5828,16 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
}
}
void LLPipeline::setupHWLights(LLDrawPool* pool)
void LLPipeline::setupHWLights()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
if (LLPipeline::sRenderingHUDs)
{
return;
}
LLEnvironment& environment = LLEnvironment::instance();
LLSettingsSky::ptr_t psky = environment.getCurrentSky();
@ -6869,94 +6907,6 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
}
}
void LLPipeline::resetVertexBuffers()
{
mResetVertexBuffers = true;
}
void LLPipeline::doResetVertexBuffers(bool forced)
{
if (!mResetVertexBuffers)
{
return;
}
if(!forced && LLSpatialPartition::sTeleportRequested)
{
if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
{
return; //wait for teleporting to finish
}
else
{
//teleporting aborted
LLSpatialPartition::sTeleportRequested = FALSE;
mResetVertexBuffers = false;
return;
}
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
mResetVertexBuffers = false;
mCubeVB = NULL;
mDeferredVB = NULL;
exoPostProcess::instance().destroyVB(); // Will be re-created via updateRenderDeferred()
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
LLViewerRegion* region = *iter;
for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
{
LLSpatialPartition* part = region->getSpatialPartition(i);
if (part)
{
part->resetVertexBuffers();
}
}
}
if(LLSpatialPartition::sTeleportRequested)
{
LLSpatialPartition::sTeleportRequested = FALSE;
LLWorld::getInstance()->clearAllVisibleObjects();
clearRebuildDrawables();
}
resetDrawOrders();
gSky.resetVertexBuffers();
LLVOPartGroup::destroyGL();
if ( LLPathingLib::getInstance() )
{
LLPathingLib::getInstance()->cleanupVBOManager();
}
LLVOPartGroup::destroyGL();
gGL.resetVertexBuffer();
LLVertexBuffer::unbind();
updateRenderBump();
sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
gGL.initVertexBuffer();
// <FS:Ansariel> Reset VB during TP
//mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK);
//mDeferredVB->allocateBuffer(8, 0);
initDeferredVB();
// </FS:Ansariel>
LLVOPartGroup::restoreGL();
exoPostProcess::instance().ExodusRenderPostUpdate(); // <FS:CR> Import Vignette from Exodus
}
void LLPipeline::renderObjects(U32 type, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
@ -7711,9 +7661,13 @@ void LLPipeline::renderFinalize()
gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screenTarget()->getWidth(), screenTarget()->getHeight());
F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f);
gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
F32 e = llclamp(exposure(), 0.5f, 4.f);
static LLStaticHashedString s_exposure("exposure");
gDeferredPostGammaCorrectProgram.uniform1f(s_exposure, e);
mScreenTriangleVB->setBuffer();
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@ -7957,18 +7911,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
stop_glerror();
}
channel = shader.enableTexture(LLShaderMgr::SCENE_MAP);
if (channel > -1)
{
gGL.getTexUnit(channel)->bind(&mSceneMap);
}
channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH);
if (channel > -1)
{
gGL.getTexUnit(channel)->bind(&mSceneMap, true);
}
if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1)
{
shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
@ -8211,7 +8153,7 @@ void LLPipeline::renderDeferredLighting()
glh::matrix4f mat = copy_matrix(gGLModelView);
setupHWLights(NULL); // to set mSun/MoonDir;
setupHWLights(); // to set mSun/MoonDir;
glh::vec4f tc(mSunDir.mV);
mat.mult_matrix_vec(tc);
@ -8347,6 +8289,8 @@ void LLPipeline::renderDeferredLighting()
soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
soften_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
soften_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV);
{
LLGLDepthTest depth(GL_FALSE);
LLGLDisable blend(GL_BLEND);
@ -8750,10 +8694,13 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
//if (!gCubeSnapshot)
// make sure we're not already targeting the same spot light with both shadow maps
llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull());
if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
//determine if this is a good light for casting shadows
//determine if this light is higher priority than one of the existing spot shadows
F32 m_pri = volume->getSpotLightPriority();
for (U32 i = 0; i < 2; i++)
@ -8762,7 +8709,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
if (mTargetShadowSpotLight[i].notNull())
{
pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
}
if (m_pri > pri)
@ -8775,6 +8722,9 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
}
}
// make sure we didn't end up targeting the same spot light with both shadow maps
llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull());
LLViewerTexture* img = volume->getLightTexture();
if (img == NULL)
@ -8895,6 +8845,21 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)
setEnvMat(shader);
}
// reflection probe shaders generally sample the scene map as well for SSR
channel = shader.enableTexture(LLShaderMgr::SCENE_MAP);
if (channel > -1)
{
gGL.getTexUnit(channel)->bind(&mSceneMap);
}
channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH);
if (channel > -1)
{
gGL.getTexUnit(channel)->bind(&mSceneMap, true);
}
}
void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader)
@ -9418,6 +9383,24 @@ LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i)
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render");
// helper class for disabling occlusion culling for the current stack frame
class LLDisableOcclusionCulling
{
public:
S32 mUseOcclusion;
LLDisableOcclusionCulling()
{
mUseOcclusion = LLPipeline::sUseOcclusion;
LLPipeline::sUseOcclusion = 0;
}
~LLDisableOcclusionCulling()
{
LLPipeline::sUseOcclusion = mUseOcclusion;
}
};
void LLPipeline::generateSunShadow(LLCamera& camera)
{
if (!sRenderDeferred || RenderShadowDetail <= 0)
@ -9428,6 +9411,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW);
LL_PROFILE_GPU_ZONE("generateSunShadow");
LLDisableOcclusionCulling no_occlusion;
bool skip_avatar_update = false;
if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
{
@ -9593,7 +9578,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (fp.empty())
{
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowCamera[0] = main_camera;
mShadowExtents[0][0] = min;
@ -9661,7 +9646,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
if (mSunDiffuse == LLColor4::black)
{ //sun diffuse is totally shadows don't matter
{ //sun diffuse is totally black shadows don't matter
LLGLDepthTest depth(GL_TRUE);
for (S32 j = 0; j < 4; j++)
@ -9673,23 +9658,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
else
{
/*if (gCubeSnapshot)
{
// do one shadow split for cube snapshots, clear the rest
mSunClipPlanes.set(64.f, 64.f, 64.f);
dist[1] = dist[2] = dist[3] = dist[4] = 64.f;
for (S32 j = 1; j < 4; j++)
{
mRT->shadow[j].bindTarget();
mRT->shadow[j].clear();
mRT->shadow[j].flush();
}
}*/
//for (S32 j = 0; j < (gCubeSnapshot ? 1 : 4); j++)
for (S32 j = 0; j < 4; j++)
{
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowFrustPoints[j].clear();
}
@ -9731,7 +9702,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
shadow_cam.calcAgentFrustumPlanes(frust);
shadow_cam.mFrustumCornerDist = 0.f;
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowCamera[j] = shadow_cam;
}
@ -9741,7 +9712,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
{
//no possible shadow receivers
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowExtents[j][0] = LLVector3();
mShadowExtents[j][1] = LLVector3();
@ -9761,7 +9732,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
continue;
}
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowExtents[j][0] = min;
mShadowExtents[j][1] = max;
@ -9988,7 +9959,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
eye = LLVector3(origin_agent.v);
if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowFrustOrigin[j] = eye;
}
@ -10051,14 +10022,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mRT->shadow[j].flush();
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot)
{
mShadowCamera[j+4] = shadow_cam;
}
}
}
//hack to disable projector shadows
bool gen_shadow = RenderShadowDetail > 1;
@ -10070,6 +10040,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
F32 fade_amt = gFrameIntervalSeconds.value()
* llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
// should never happen
llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull());
//update shadow targets
for (U32 i = 0; i < 2; i++)
{ //for each current shadow
@ -10100,6 +10073,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
}
// this should never happen
llassert(mShadowSpotLight[0] != mShadowSpotLight[1] || mShadowSpotLight[0].isNull());
for (S32 i = 0; i < 2; i++)
{
set_current_modelview(saved_view);
@ -10185,8 +10161,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
stop_glerror();
//
mSpotShadow[i].bindTarget();

View File

@ -97,9 +97,7 @@ public:
void destroyGL();
void restoreGL();
void resetVertexBuffers();
void doResetVertexBuffers(bool forced = false);
void requestResizeScreenTexture(); // set flag only, no work, safer for callbacks...
void requestResizeScreenTexture(); // set flag only, no work, safer for callbacks...
void requestResizeShadowTexture(); // set flag only, no work, safer for callbacks...
void resizeScreenTexture();
@ -327,7 +325,7 @@ public:
S32 getLightCount() const { return mLights.size(); }
void calcNearbyLights(LLCamera& camera);
void setupHWLights(LLDrawPool* pool);
void setupHWLights();
void setupAvatarLights(bool for_edit = false);
void enableLights(U32 mask);
void enableLightsStatic();
@ -913,6 +911,8 @@ protected:
LLDrawPool* mMaterialsPool = nullptr;
LLDrawPool* mWLSkyPool = nullptr;
LLDrawPool* mPBROpaquePool = nullptr;
LLDrawPool* mPBRAlphaMaskPool = nullptr;
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
public:

View File

@ -712,6 +712,61 @@
value="2"/>
</combo_box>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="420"
name="RenderTonemapperText"
text_readonly_color="LabelDisabledColor"
top_delta="24"
width="128">
Tonemapper:
</text>
<combo_box
control_name="RenderTonemapper"
height="18"
layout="topleft"
left_delta="130"
top_delta="0"
name="ToneMapper"
width="150">
<combo_box.item
label="Linear"
name="0"
value="0"/>
<combo_box.item
label="ACES Narkowicz"
name="1"
value="1"/>
<combo_box.item
label="ACES Hill"
name="2"
value="2"/>
</combo_box>
<slider
control_name="RenderExposure"
decimal_digits="1"
follows="left|top"
height="16"
increment="0.1"
initial_value="160"
label="Exposure:"
label_width="145"
layout="topleft"
left="420"
min_val="0.5"
max_val="4.0"
name="RenderExposure"
show_text="true"
top_delta="20"
width="260">
</slider>
<!-- End of Advanced Settings block -->
<view_border
bevel_style="in"

View File

@ -13979,10 +13979,12 @@ Material successfully created. Asset ID: [ASSET_ID]
name="ReflectionProbeApplied"
persist="true"
type="alertmodal">
Your object has been set to the default Reflection Probe state, which is an invisible, phantom, 5m sphere. To learn more about Reflection Probes and how to use them, see the Knowledge Base.
<usetemplate ignoretext="Reflection Probe tips"
name="okignore"
yestext="OK"/>
WARNING: You have made your object a Reflection Probe. This will implicitly change the object to mimic its influence volume and will make irreversible changes to the object. Do you want to continue?
<usetemplate
ignoretext="Reflection Probe tips"
name="okcancelignore"
notext="Cancel"
yestext="OK"/>
</notification>
<notification

View File

@ -376,6 +376,40 @@
name="2"
value="2"/>
</combo_box>
<text
type="string"
length="1"
follows="left|top"
height="12"
layout="topleft"
left_delta="-5"
name="RenderTonemapperText"
text_readonly_color="LabelDisabledColor"
top_pad="4"
width="170">
Tonemapper:
</text>
<combo_box
control_name="RenderTonemapper"
height="23"
layout="topleft"
left_delta="5"
top_pad="3"
name="ToneMapper"
width="150">
<combo_box.item
label="Linear"
name="0"
value="0"/>
<combo_box.item
label="ACES Narkowicz"
name="1"
value="1"/>
<combo_box.item
label="ACES Hill"
name="2"
value="2"/>
</combo_box>
<!-- FS:TM Avatar Physics was moved down to LOD section-->
<!-- FS:TM Point Lighting added instead of above-->
<text
@ -576,6 +610,24 @@
top_pad="5"
width="297"/>
<slider
control_name="RenderExposure"
decimal_digits="1"
follows="left|top"
height="16"
increment="0.1"
initial_value="1"
label="Exposure"
label_width="185"
layout="topleft"
left="200"
min_val="0.5"
max_val="4.0"
name="RenderExposure"
show_text="true"
top_pad="2"
width="297"/>
<text
type="string"
length="1"

View File

@ -144,11 +144,11 @@
top="65"
width="90">
<combo_box.item
label="Materials"
label="Blinn-Phong"
name="Materials"
value="Materials" />
<combo_box.item
label="PBR"
label="PBR Metallic Roughness"
name="PBR"
value="PBR" />
<combo_box.item
@ -249,7 +249,7 @@
allow_no_texture="true"
follows="left|top"
height="80"
label="PBR"
label="Material"
layout="topleft"
left="10"
name="pbr_control"