Merge branch 'release/2024.12-ForeverFPS' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/llinventorymodel.h # indra/newview/llviewertexturelist.cpp # indra/newview/llvoiceclient.cpp # indra/newview/pipeline.cppmaster
commit
7e7e19ee35
|
|
@ -1402,6 +1402,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("screenTex");
|
||||
mReservedUniforms.push_back("screenDepth");
|
||||
mReservedUniforms.push_back("refTex");
|
||||
mReservedUniforms.push_back("exclusionTex");
|
||||
mReservedUniforms.push_back("eyeVec");
|
||||
mReservedUniforms.push_back("time");
|
||||
mReservedUniforms.push_back("waveDir1");
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ public:
|
|||
LLShaderMgr();
|
||||
virtual ~LLShaderMgr();
|
||||
|
||||
// Note: although you can use statically hashed strings to just bind a random uniform, it's generally preferably that you use this.
|
||||
// Always document what the actual shader uniform is next to the shader uniform in this struct.
|
||||
// clang-format off
|
||||
typedef enum
|
||||
{ // Shader uniform name, set in LLShaderMgr::initAttribsAndUniforms()
|
||||
|
|
@ -238,6 +240,7 @@ public:
|
|||
WATER_SCREENTEX, // "screenTex"
|
||||
WATER_SCREENDEPTH, // "screenDepth"
|
||||
WATER_REFTEX, // "refTex"
|
||||
WATER_EXCLUSIONTEX, // "exclusionTex"
|
||||
WATER_EYEVEC, // "eyeVec"
|
||||
WATER_TIME, // "time"
|
||||
WATER_WAVE_DIR1, // "waveDir1"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "llfolderview.h"
|
||||
#include "llfolderviewmodel.h"
|
||||
#include "llcallbacklist.h"
|
||||
#include "llclipboard.h" // *TODO: remove this once hack below gone.
|
||||
#include "llkeyboard.h"
|
||||
#include "lllineeditor.h"
|
||||
|
|
@ -278,7 +279,11 @@ LLFolderView::~LLFolderView( void )
|
|||
mRenamer = NULL;
|
||||
mStatusTextBox = NULL;
|
||||
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
if (mPopupMenuHandle.get())
|
||||
{
|
||||
mPopupMenuHandle.get()->die();
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
mPopupMenuHandle.markDead();
|
||||
|
||||
mAutoOpenItems.removeAllNodes();
|
||||
|
|
@ -1132,7 +1137,10 @@ bool LLFolderView::handleKeyHere( KEY key, MASK mask )
|
|||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->isOpen())
|
||||
{
|
||||
LLMenuGL::sMenuContainer->hideMenus();
|
||||
if (LLMenuGL::sMenuContainer->hideMenus())
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
switch( key )
|
||||
|
|
@ -1417,7 +1425,10 @@ bool LLFolderView::handleUnicodeCharHere(llwchar uni_char)
|
|||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->isOpen())
|
||||
{
|
||||
LLMenuGL::sMenuContainer->hideMenus();
|
||||
if (LLMenuGL::sMenuContainer->hideMenus())
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
//do text search
|
||||
|
|
@ -1706,7 +1717,11 @@ void LLFolderView::deleteAllChildren()
|
|||
{
|
||||
LLUI::getInstance()->removePopup(mRenamer);
|
||||
}
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
if (mPopupMenuHandle.get())
|
||||
{
|
||||
mPopupMenuHandle.get()->die();
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
mPopupMenuHandle.markDead();
|
||||
mScrollContainer = NULL;
|
||||
mRenameItem = NULL;
|
||||
|
|
@ -2073,9 +2088,24 @@ void LLFolderView::updateMenu()
|
|||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->getVisible())
|
||||
{
|
||||
updateMenuOptions(menu);
|
||||
// When fetching folders in bulk or in parts, each callback
|
||||
// cause updateMenu individually, so make sure it gets called
|
||||
// only once per frame, after callbacks are done.
|
||||
// gIdleCallbacks has built in dupplicate protection.
|
||||
gIdleCallbacks.addFunction(onIdleUpdateMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFolderView::onIdleUpdateMenu(void* user_data)
|
||||
{
|
||||
LLFolderView* self = (LLFolderView*)user_data;
|
||||
LLMenuGL* menu = (LLMenuGL*)self->mPopupMenuHandle.get();
|
||||
if (menu)
|
||||
{
|
||||
self->updateMenuOptions(menu);
|
||||
menu->needsArrange(); // update menu height if needed
|
||||
}
|
||||
gIdleCallbacks.deleteFunction(onIdleUpdateMenu, NULL);
|
||||
}
|
||||
|
||||
bool LLFolderView::isFolderSelected()
|
||||
|
|
|
|||
|
|
@ -271,6 +271,7 @@ public:
|
|||
private:
|
||||
void updateMenuOptions(LLMenuGL* menu);
|
||||
void updateRenamerPosition();
|
||||
static void onIdleUpdateMenu(void* user_data);
|
||||
|
||||
protected:
|
||||
LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container.
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ set(viewer_SOURCE_FILES
|
|||
lldrawpooltree.cpp
|
||||
lldrawpoolwater.cpp
|
||||
lldrawpoolwlsky.cpp
|
||||
lldrawpoolwaterexclusion.cpp
|
||||
lldynamictexture.cpp
|
||||
llemote.cpp
|
||||
llenvironment.cpp
|
||||
|
|
@ -1088,6 +1089,7 @@ set(viewer_HEADER_FILES
|
|||
lldrawpooltree.h
|
||||
lldrawpoolwater.h
|
||||
lldrawpoolwlsky.h
|
||||
lldrawpoolwaterexclusion.h
|
||||
lldynamictexture.h
|
||||
llemote.h
|
||||
llenvironment.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file simpleColorF.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
in vec4 vertex_color;
|
||||
in vec4 vertex_position;
|
||||
|
||||
uniform vec4 waterPlane;
|
||||
uniform float waterSign;
|
||||
|
||||
void waterClip(vec3 pos)
|
||||
{
|
||||
// TODO: make this less branchy
|
||||
if (waterSign > 0)
|
||||
{
|
||||
if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) > 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
frag_color = vertex_color;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file simpleNoAtmosV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
uniform vec4 color;
|
||||
|
||||
in vec3 position;
|
||||
|
||||
out vec4 vertex_color;
|
||||
out vec4 vertex_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
//transform vertex
|
||||
vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0));
|
||||
vertex_position = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
gl_Position = vertex_position;
|
||||
vertex_color = color;
|
||||
}
|
||||
|
|
@ -789,9 +789,6 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
|
|||
probeIndex[probeInfluences++] = 0;
|
||||
|
||||
doProbeSample(ambenv, glossenv, tc, pos, norm, glossiness, false, amblit);
|
||||
|
||||
// fudge factor to get PBR water at a similar luminance ot legacy water
|
||||
glossenv *= 0.4;
|
||||
}
|
||||
|
||||
void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
|
||||
|
|
|
|||
|
|
@ -35,13 +35,25 @@ vec4 getWaterFogView(vec3 pos);
|
|||
|
||||
uniform int above_water;
|
||||
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5;
|
||||
float depth = getDepth(tc.xy);
|
||||
float mask = texture(exclusionTex, tc.xy).r;
|
||||
|
||||
if (above_water > 0)
|
||||
{
|
||||
// Just discard if we're in the exclusion mask.
|
||||
// The previous invisiprim hack we're replacing would also crank up water fog desntiy.
|
||||
// But doing that makes exclusion surfaces very slow as we'd need to render even more into the mask.
|
||||
// - Geenz 2025-02-06
|
||||
if (mask < 1)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
// we want to depth test when the camera is above water, but some GPUs have a hard time
|
||||
// with depth testing against render targets that are bound for sampling in the same shader
|
||||
// so we do it manually here
|
||||
|
|
@ -51,12 +63,14 @@ void main()
|
|||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vec4 pos = getPositionWithDepth(tc, depth);
|
||||
|
||||
vec4 fogged = getWaterFogView(pos.xyz);
|
||||
fogged.a = max(pow(fogged.a, 1.7), 0);
|
||||
|
||||
frag_color = max(fogged, vec4(0)); //output linear since local lights will be added to this shader's results
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
out vec4 frag_color;
|
||||
|
||||
uniform sampler2D bumpMap;
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
#ifdef TRANSPARENT_WATER
|
||||
uniform sampler2D screenTex;
|
||||
|
|
@ -59,6 +60,9 @@ void mirrorClip(vec3 position);
|
|||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
vec2 screen_tc = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
|
||||
float water_mask = texture(exclusionTex, screen_tc).r;
|
||||
|
||||
vec4 color;
|
||||
|
||||
//get detail normals
|
||||
|
|
@ -68,8 +72,8 @@ void main()
|
|||
vec3 wavef = normalize(wave1+wave2+wave3);
|
||||
|
||||
//figure out distortion vector (ripply)
|
||||
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
|
||||
distort = distort+wavef.xy*refScale;
|
||||
vec2 distort = screen_tc;
|
||||
distort = mix(distort, distort+wavef.xy*refScale, water_mask);
|
||||
|
||||
#ifdef TRANSPARENT_WATER
|
||||
vec4 fb = texture(screenTex, distort);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
// class3/environment/waterF.glsl
|
||||
|
||||
#define WATER_MINIMAL 1
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
#ifdef HAS_SUN_SHADOW
|
||||
|
|
@ -86,7 +88,7 @@ uniform sampler2D screenTex;
|
|||
uniform sampler2D depthMap;
|
||||
#endif
|
||||
|
||||
uniform sampler2D refTex;
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
uniform float sunAngle;
|
||||
uniform float sunAngle2;
|
||||
|
|
@ -122,6 +124,9 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
|
|||
vec3 srgb_to_linear(vec3 col);
|
||||
vec3 linear_to_srgb(vec3 col);
|
||||
|
||||
vec3 atmosLighting(vec3 light);
|
||||
vec3 scaleSoftClip(vec3 light);
|
||||
|
||||
vec3 vN, vT, vB;
|
||||
|
||||
vec3 transform_normal(vec3 vNt)
|
||||
|
|
@ -148,7 +153,7 @@ void generateWaveNormals(out vec3 wave1, out vec3 wave2, out vec3 wave3)
|
|||
|
||||
vec2 bigwave = vec2(refCoord.w, view.w);
|
||||
|
||||
vec3 wave1_a = texture(bumpMap, bigwave, -2).xyz * 2.0 - 1.0;
|
||||
vec3 wave1_a = texture(bumpMap, bigwave).xyz * 2.0 - 1.0;
|
||||
vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz * 2.0 - 1.0;
|
||||
vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz * 2.0 - 1.0;
|
||||
|
||||
|
|
@ -183,6 +188,7 @@ void calculateFresnelFactors(out vec3 df3, out vec2 df2, vec3 viewVec, vec3 wave
|
|||
void main()
|
||||
{
|
||||
mirrorClip(vary_position);
|
||||
|
||||
vN = vary_normal;
|
||||
vT = vary_tangent;
|
||||
vB = cross(vN, vT);
|
||||
|
|
@ -202,6 +208,7 @@ void main()
|
|||
|
||||
generateWaveNormals(wave1, wave2, wave3);
|
||||
|
||||
float dmod = sqrt(dist);
|
||||
vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
|
||||
|
||||
vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
|
||||
|
|
@ -216,7 +223,7 @@ void main()
|
|||
vec3 up = transform_normal(vec3(0,0,1));
|
||||
float vdu = -dot(viewVec, up)*2;
|
||||
|
||||
vec3 wave_ibl = wavef;
|
||||
vec3 wave_ibl = wavef * normScale;
|
||||
wave_ibl.z *= 2.0;
|
||||
wave_ibl = transform_normal(normalize(wave_ibl));
|
||||
|
||||
|
|
@ -233,8 +240,6 @@ void main()
|
|||
float dist2 = dist;
|
||||
dist = max(dist, 5.0);
|
||||
|
||||
float dmod = sqrt(dist);
|
||||
|
||||
//figure out distortion vector (ripply)
|
||||
vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0) * 2;
|
||||
|
||||
|
|
@ -247,6 +252,8 @@ void main()
|
|||
|
||||
float shadow = 1.0f;
|
||||
|
||||
float water_mask = texture(exclusionTex, distort).r;
|
||||
|
||||
#ifdef HAS_SUN_SHADOW
|
||||
shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, distort);
|
||||
#endif
|
||||
|
|
@ -254,23 +261,31 @@ void main()
|
|||
calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
|
||||
|
||||
vec3 sunlit_linear = srgb_to_linear(sunlit);
|
||||
|
||||
float fade = 0;
|
||||
#ifdef TRANSPARENT_WATER
|
||||
float depth = texture(depthMap, distort2).r;
|
||||
vec4 fb = texture(screenTex, distort2);
|
||||
vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0));
|
||||
float depth = texture(depthMap, distort).r;
|
||||
|
||||
if (refPos.z > pos.z-0.05)
|
||||
vec3 refPos = getPositionWithNDC(vec3(distort*2.0-vec2(1.0), depth*2.0-1.0));
|
||||
|
||||
// Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect".
|
||||
fade = max(0,min(1, (pos.z - refPos.z) / 10)) * water_mask;
|
||||
distort2 = mix(distort, distort2, min(1, fade * 10));
|
||||
depth = texture(depthMap, distort2).r;
|
||||
|
||||
refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
|
||||
|
||||
if (pos.z < refPos.z - 0.05)
|
||||
{
|
||||
//we sampled an above water sample, don't distort
|
||||
distort2 = distort;
|
||||
fb = texture(screenTex, distort2);
|
||||
depth = texture(depthMap, distort2).r;
|
||||
refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
|
||||
}
|
||||
|
||||
vec4 fb = texture(screenTex, distort2);
|
||||
|
||||
#else
|
||||
vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0));
|
||||
|
||||
if (water_mask < 1)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
float metallic = 1.0;
|
||||
|
|
@ -280,13 +295,18 @@ void main()
|
|||
vec3 irradiance = vec3(0);
|
||||
vec3 radiance = vec3(0);
|
||||
vec3 legacyenv = vec3(0);
|
||||
|
||||
// TODO: Make this an option.
|
||||
#ifdef WATER_MINIMAL
|
||||
sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit);
|
||||
//sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, 1, true, amblit);
|
||||
//sampleReflectionProbesLegacy(irradiance, radiance, legacyenv, distort2, pos.xyz, wave_ibl.xyz, gloss, 1, false, amblit);
|
||||
#elif WATER_MINIMAL_PLUS
|
||||
sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, 1, false, amblit);
|
||||
#endif
|
||||
|
||||
vec3 diffuseColor = vec3(0);
|
||||
vec3 specularColor = vec3(0);
|
||||
calcDiffuseSpecular(vec3(1), metallic, diffuseColor, specularColor);
|
||||
vec3 specular_linear = srgb_to_linear(specular);
|
||||
calcDiffuseSpecular(specular_linear, metallic, diffuseColor, specularColor);
|
||||
|
||||
vec3 v = -normalize(pos.xyz);
|
||||
|
||||
|
|
@ -302,14 +322,22 @@ void main()
|
|||
|
||||
pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc);
|
||||
|
||||
vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)) * sunlit_linear * 2.75 * shadow;
|
||||
vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)) * sunlit_linear * shadow;
|
||||
|
||||
vec3 color = vec3(0);
|
||||
color = mix(fb.rgb, radiance * df2.y, df2.x * 0.99999) + punctual.rgb;
|
||||
|
||||
color = mix(fb.rgb, radiance * df2.x, df2.x * 0.99999) + punctual.rgb;
|
||||
// This looks super janky, but we do this to restore water haze in the distance.
|
||||
// These values were finagled in to try and bring back some of the distant brightening on legacy water. Also works reasonably well on PBR skies such as PBR midday.
|
||||
color += color * min(vec3(4),pow(1 - atten, vec3(1.35)) * 16 * fade);
|
||||
|
||||
// We shorten the fade here at the shoreline so it doesn't appear too soft from a distance.
|
||||
fade *= 60;
|
||||
fade = min(1, fade);
|
||||
color = mix(fb.rgb, color, fade);
|
||||
|
||||
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05);
|
||||
|
||||
frag_color = max(vec4(color.rgb, spec), vec4(0));
|
||||
frag_color = min(vec4(1),max(vec4(color.rgb, spec * water_mask), vec4(0)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,8 +359,9 @@ void LLConversationItemSession::clearParticipants()
|
|||
|
||||
void LLConversationItemSession::clearAndDeparentModels()
|
||||
{
|
||||
for (LLFolderViewModelItem* child : mChildren)
|
||||
for (child_list_t::iterator it = mChildren.begin(); it != mChildren.end();)
|
||||
{
|
||||
LLFolderViewModelItem* child = *it;
|
||||
if (child->getNumRefs() == 0)
|
||||
{
|
||||
// LLConversationItemParticipant can be created but not assigned to any view,
|
||||
|
|
@ -372,8 +373,8 @@ void LLConversationItemSession::clearAndDeparentModels()
|
|||
// Model is still assigned to some view/widget
|
||||
child->setParent(NULL);
|
||||
}
|
||||
it = mChildren.erase(it);
|
||||
}
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "lldrawpooltree.h"
|
||||
#include "lldrawpoolterrain.h"
|
||||
#include "lldrawpoolwater.h"
|
||||
#include "lldrawpoolwaterexclusion.h"
|
||||
#include "llface.h"
|
||||
#include "llviewerobjectlist.h" // For debug listing.
|
||||
#include "pipeline.h"
|
||||
|
|
@ -119,6 +120,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
|
|||
case POOL_GLTF_PBR_ALPHA_MASK:
|
||||
poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK);
|
||||
break;
|
||||
case POOL_WATEREXCLUSION:
|
||||
poolp = new LLDrawPoolWaterExclusion();
|
||||
break;
|
||||
default:
|
||||
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
// based on fill rate and likelihood to occlude future passes (faster, large occluders first).
|
||||
//
|
||||
POOL_SKY = 1,
|
||||
POOL_WATEREXCLUSION,
|
||||
POOL_WL_SKY,
|
||||
POOL_SIMPLE,
|
||||
POOL_FULLBRIGHT,
|
||||
|
|
@ -140,7 +141,7 @@ public:
|
|||
PASS_GRASS,
|
||||
PASS_FULLBRIGHT,
|
||||
PASS_FULLBRIGHT_RIGGED,
|
||||
PASS_INVISIBLE,
|
||||
PASS_INVISIBLE, // Formerly, invisiprims. Now, water exclusion surfaces.
|
||||
PASS_INVISIBLE_RIGGED,
|
||||
PASS_INVISI_SHINY,
|
||||
PASS_INVISI_SHINY_RIGGED,
|
||||
|
|
|
|||
|
|
@ -249,6 +249,8 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass)
|
|||
gGL.getTexUnit(bumpTex2)->bind(tex_b);
|
||||
}
|
||||
|
||||
shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask);
|
||||
|
||||
// bind reflection texture from RenderTarget
|
||||
S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
|
||||
|
||||
|
|
@ -320,30 +322,11 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass)
|
|||
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
|
||||
LLVOWater* water = nullptr;
|
||||
for (LLFace* const& face : mDrawFace)
|
||||
{
|
||||
if (!face) continue;
|
||||
water = static_cast<LLVOWater*>(face->getViewerObject());
|
||||
if (!water) continue;
|
||||
|
||||
if ((bool)edge == (bool)water->getIsEdgePatch())
|
||||
{
|
||||
face->renderIndexed();
|
||||
|
||||
// Note non-void water being drawn, updates required
|
||||
if (!edge) // SL-16461 remove !LLPipeline::sUseOcclusion check
|
||||
{
|
||||
sNeedsReflectionUpdate = true;
|
||||
sNeedsDistortionUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
pushWaterPlanes(edge);
|
||||
|
||||
shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||
shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);
|
||||
shader->disableTexture(LLShaderMgr::BUMP_MAP);
|
||||
shader->disableTexture(LLShaderMgr::WATER_REFTEX);
|
||||
|
||||
// clean up
|
||||
gPipeline.unbindDeferredShader(*shader);
|
||||
|
|
@ -358,6 +341,31 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass)
|
|||
gGL.setColorMask(true, false);
|
||||
}
|
||||
|
||||
void LLDrawPoolWater::pushWaterPlanes(int pass)
|
||||
{
|
||||
LLVOWater* water = nullptr;
|
||||
for (LLFace* const& face : mDrawFace)
|
||||
{
|
||||
if (!face)
|
||||
continue;
|
||||
water = static_cast<LLVOWater*>(face->getViewerObject());
|
||||
if (!water)
|
||||
continue;
|
||||
|
||||
if ((bool)pass == (bool)water->getIsEdgePatch())
|
||||
{
|
||||
face->renderIndexed();
|
||||
|
||||
// Note non-void water being drawn, updates required
|
||||
if (!pass) // SL-16461 remove !LLPipeline::sUseOcclusion check
|
||||
{
|
||||
sNeedsReflectionUpdate = true;
|
||||
sNeedsDistortionUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerTexture *LLDrawPoolWater::getDebugTexture()
|
||||
{
|
||||
return LLViewerTextureManager::getFetchedTexture(IMG_SMOKE);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ public:
|
|||
void setOpaqueTexture(const LLUUID& opaqueTextureId);
|
||||
void setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId);
|
||||
|
||||
void pushWaterPlanes(int pass);
|
||||
|
||||
protected:
|
||||
void renderOpaqueLegacyWater();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @file lldrawpool.cpp
|
||||
* @brief LLDrawPoolMaterials class implementation
|
||||
* @author Jonathan "Geenz" Goodman
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "lldrawpoolwaterexclusion.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "pipeline.h"
|
||||
#include "llglcommonfunc.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "lldrawpoolwater.h"
|
||||
|
||||
LLDrawPoolWaterExclusion::LLDrawPoolWaterExclusion() : LLRenderPass(LLDrawPool::POOL_WATEREXCLUSION)
|
||||
{
|
||||
LL_INFOS("DPInvisible") << "Creating water exclusion draw pool" << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
void LLDrawPoolWaterExclusion::render(S32 pass)
|
||||
{ // render invisiprims
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; // LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE);
|
||||
|
||||
if (gPipeline.shadersLoaded())
|
||||
{
|
||||
gDrawColorProgram.bind();
|
||||
}
|
||||
|
||||
|
||||
LLGLDepthTest depth(GL_TRUE);
|
||||
gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 1, 1, 1, 1);
|
||||
|
||||
LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER);
|
||||
if (pwaterpool)
|
||||
{
|
||||
// Just treat our water planes as double sided for the purposes of generating the exclusion mask.
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
pwaterpool->pushWaterPlanes(0);
|
||||
|
||||
// Take care of the edge water tiles.
|
||||
pwaterpool->pushWaterPlanes(1);
|
||||
}
|
||||
|
||||
gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 0, 0, 0, 1);
|
||||
|
||||
static LLStaticHashedString waterSign("waterSign");
|
||||
gDrawColorProgram.uniform1f(waterSign, 1.f);
|
||||
|
||||
pushBatches(LLRenderPass::PASS_INVISIBLE, false, false);
|
||||
|
||||
|
||||
if (gPipeline.shadersLoaded())
|
||||
{
|
||||
gDrawColorProgram.unbind();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file lldrawpoolwaterexclusion.h
|
||||
* @brief LLDrawPoolWaterExclusion class definition
|
||||
* @author Jonathan "Geenz" Goodman
|
||||
*
|
||||
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, 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$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLDRAWPOOLWATEREXCLUSION_H
|
||||
#define LL_LLDRAWPOOLWATEREXCLUSION_H
|
||||
|
||||
#include "v4coloru.h"
|
||||
#include "v2math.h"
|
||||
#include "v3math.h"
|
||||
#include "llvertexbuffer.h"
|
||||
#include "lldrawpool.h"
|
||||
|
||||
class LLViewerTexture;
|
||||
class LLDrawInfo;
|
||||
class LLGLSLShader;
|
||||
|
||||
class LLDrawPoolWaterExclusion : public LLRenderPass
|
||||
{
|
||||
public:
|
||||
LLDrawPoolWaterExclusion();
|
||||
|
||||
enum
|
||||
{
|
||||
VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX
|
||||
};
|
||||
|
||||
virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
|
||||
|
||||
virtual void prerender() {}
|
||||
|
||||
virtual void render(S32 pass = 0);
|
||||
virtual void beginRenderPass(S32 pass) {}
|
||||
virtual void endRenderPass(S32 pass) {}
|
||||
virtual S32 getNumPasses() { return 1; }
|
||||
};
|
||||
|
||||
#endif // LL_LLDRAWPOOLWATEREXCLUSION_H
|
||||
|
|
@ -4638,14 +4638,9 @@ void LLFolderBridge::staticFolderOptionsMenu()
|
|||
|
||||
bool LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
|
||||
{
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
model->collectDescendentsIf(mUUID,
|
||||
cat_array,
|
||||
item_array,
|
||||
return model->hasMatchingDescendents(mUUID,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_type);
|
||||
return !item_array.empty();
|
||||
}
|
||||
|
||||
void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items)
|
||||
|
|
@ -4866,21 +4861,26 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
//Added by aura to force inventory pull on right-click to display folder options correctly. 07-17-06
|
||||
mCallingCards = mWearables = false;
|
||||
|
||||
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
|
||||
if (checkFolderForContentsOfType(model, is_callingcard))
|
||||
if (gInventory.getRootFolderID() != mUUID)
|
||||
{
|
||||
mCallingCards=true;
|
||||
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
|
||||
if (checkFolderForContentsOfType(model, is_callingcard))
|
||||
{
|
||||
mCallingCards = true;
|
||||
}
|
||||
|
||||
const std::vector<LLAssetType::EType> types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE };
|
||||
LLIsOneOfTypes is_wearable(types);
|
||||
|
||||
if (checkFolderForContentsOfType(model, is_wearable))
|
||||
{
|
||||
mWearables = true;
|
||||
}
|
||||
}
|
||||
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
|
||||
if (checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture) )
|
||||
else
|
||||
{
|
||||
mWearables=true;
|
||||
// Assume that there are wearables in the root folder
|
||||
mWearables = true;
|
||||
}
|
||||
}
|
||||
// [SL:KB] - Patch: Inventory-Misc | Checked: 2011-05-28 (Catznip-2.6.0a) | Added: Catznip-2.6.0a
|
||||
|
|
@ -4901,13 +4901,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
LLFolderType::EType type = category->getPreferredType();
|
||||
const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
|
||||
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object(LLAssetType::AT_OBJECT);
|
||||
LLIsType is_gesture(LLAssetType::AT_GESTURE);
|
||||
const std::vector<LLAssetType::EType> types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE };
|
||||
LLIsOneOfTypes is_wearable(types);
|
||||
|
||||
if (checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture))
|
||||
if (checkFolderForContentsOfType(model, is_wearable))
|
||||
{
|
||||
mWearables = true;
|
||||
}
|
||||
|
|
@ -5071,14 +5068,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
|
|||
|
||||
// wearables related functionality for folders.
|
||||
//is_wearable
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
const std::vector<LLAssetType::EType> types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE };
|
||||
LLIsOneOfTypes is_wearable(types);
|
||||
|
||||
if (mWearables ||
|
||||
checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture) )
|
||||
checkFolderForContentsOfType(model, is_wearable))
|
||||
{
|
||||
// Only enable add/replace outfit for non-system folders.
|
||||
if (!is_system_folder)
|
||||
|
|
|
|||
|
|
@ -2795,6 +2795,22 @@ bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLIsOneOfTypes::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
for (LLAssetType::EType &type : mTypes)
|
||||
{
|
||||
if (type == LLAssetType::AT_CATEGORY)
|
||||
{
|
||||
if (cat) return true;
|
||||
}
|
||||
if (item)
|
||||
{
|
||||
if (item->getType() == type) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
if(mType == LLAssetType::AT_CATEGORY)
|
||||
|
|
|
|||
|
|
@ -252,6 +252,24 @@ protected:
|
|||
LLAssetType::EType mType;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLIsOneOfTypes
|
||||
//
|
||||
// Implementation of a LLInventoryCollectFunctor which returns true if
|
||||
// the type is one of the types passed in during construction.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLIsOneOfTypes : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLIsOneOfTypes(const std::vector<LLAssetType::EType> &types) : mTypes(types) {}
|
||||
virtual ~LLIsOneOfTypes() {}
|
||||
virtual bool operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item);
|
||||
protected:
|
||||
std::vector <LLAssetType::EType> mTypes;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLIsNotType
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1438,6 +1438,47 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
|
|||
// [/RLVa:KB]
|
||||
}
|
||||
|
||||
bool LLInventoryModel::hasMatchingDescendents(const LLUUID& id,
|
||||
bool include_trash,
|
||||
LLInventoryCollectFunctor& matches)
|
||||
{
|
||||
if (!include_trash)
|
||||
{
|
||||
const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (trash_id.notNull() && (trash_id == id))
|
||||
return false;
|
||||
}
|
||||
cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
|
||||
if (cat_array)
|
||||
{
|
||||
for (auto& cat : *cat_array)
|
||||
{
|
||||
if (matches(cat, NULL))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (hasMatchingDescendents(cat->getUUID(), include_trash, matches))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
|
||||
|
||||
if (item_array)
|
||||
{
|
||||
for (auto& item : *item_array)
|
||||
{
|
||||
if (matches(NULL, item))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
|
||||
{
|
||||
const LLInventoryObject *obj = getObject(object_id);
|
||||
|
|
|
|||
|
|
@ -306,6 +306,9 @@ public:
|
|||
// item_array_t& items,
|
||||
// bool include_trash,
|
||||
// LLInventoryCollectFunctor& add);
|
||||
bool hasMatchingDescendents(const LLUUID& id,
|
||||
bool include_trash,
|
||||
LLInventoryCollectFunctor& add);
|
||||
|
||||
// Collect all items in inventory that are linked to item_id.
|
||||
// Assumes item_id is itself not a linked item.
|
||||
|
|
|
|||
|
|
@ -1424,6 +1424,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory()
|
|||
LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
|
||||
if (fchild
|
||||
&& fchild->getViewModelItem()
|
||||
// Is this right? Name might be localized,
|
||||
// use FT_ROOT_INVENTORY or gInventory.getRootFolderID()?
|
||||
&& fchild->getViewModelItem()->getName() == "My Inventory")
|
||||
{
|
||||
fchild->setOpen(true);
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ LLGLSLShader gReflectionProbeDisplayProgram;
|
|||
LLGLSLShader gCopyProgram;
|
||||
LLGLSLShader gCopyDepthProgram;
|
||||
LLGLSLShader gPBRTerrainBakeProgram;
|
||||
LLGLSLShader gDrawColorProgram;
|
||||
|
||||
//object shaders
|
||||
LLGLSLShader gObjectPreviewProgram;
|
||||
|
|
@ -3402,6 +3403,17 @@ bool LLViewerShaderMgr::loadShadersInterface()
|
|||
success = gCopyDepthProgram.createShader();
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
gDrawColorProgram.mName = "Draw Color Shader";
|
||||
gDrawColorProgram.mShaderFiles.clear();
|
||||
gDrawColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoAtmosV.glsl", GL_VERTEX_SHADER));
|
||||
gDrawColorProgram.mShaderFiles.push_back(make_pair("objects/simpleColorF.glsl", GL_FRAGMENT_SHADER));
|
||||
gDrawColorProgram.clearPermutations();
|
||||
gDrawColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
|
||||
success = gDrawColorProgram.createShader();
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("LocalTerrainPaintEnabled"))
|
||||
{
|
||||
if (success)
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ extern LLGLSLShader gReflectionProbeDisplayProgram;
|
|||
extern LLGLSLShader gCopyProgram;
|
||||
extern LLGLSLShader gCopyDepthProgram;
|
||||
extern LLGLSLShader gPBRTerrainBakeProgram;
|
||||
extern LLGLSLShader gDrawColorProgram;
|
||||
|
||||
//output tex0[tc0] - tex1[tc1]
|
||||
extern LLGLSLShader gTwoTextureCompareProgram;
|
||||
|
|
|
|||
|
|
@ -3661,18 +3661,7 @@ void LLViewerMediaTexture::setPlaying(bool playing)
|
|||
for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
|
||||
{
|
||||
LLFace* facep = *iter;
|
||||
const LLTextureEntry* te = facep->getTextureEntry();
|
||||
if (te && te->getGLTFMaterial())
|
||||
{
|
||||
// PBR material, switch emissive and basecolor
|
||||
switchTexture(LLRender::EMISSIVE_MAP, *iter);
|
||||
switchTexture(LLRender::BASECOLOR_MAP, *iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// blinn-phong material, switch diffuse map only
|
||||
switchTexture(LLRender::DIFFUSE_MAP, *iter);
|
||||
}
|
||||
switchTexture(LLRender::DIFFUSE_MAP, facep);
|
||||
}
|
||||
}
|
||||
else //stop playing this media
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ void LLVoiceClient::setNonSpatialVoiceModule(const std::string &voice_server_typ
|
|||
|
||||
void LLVoiceClient::setHidden(bool hidden)
|
||||
{
|
||||
LL_INFOS("Voice") << "( " << (hidden ? "true" : "false") << " )" << LL_ENDL;
|
||||
#ifdef OPENSIM
|
||||
LLWebRTCVoiceClient::getInstance()->setHidden(hidden && LLGridManager::getInstance()->isInSecondLife());
|
||||
LLVivoxVoiceClient::getInstance()->setHidden(hidden && LLGridManager::getInstance()->isInSecondLife());
|
||||
|
|
|
|||
|
|
@ -345,6 +345,8 @@ void LLWebRTCVoiceClient::updateSettings()
|
|||
static LLCachedControl<std::string> sOutputDevice(gSavedSettings, "VoiceOutputAudioDevice");
|
||||
setRenderDevice(sOutputDevice);
|
||||
|
||||
LL_INFOS("Voice") << "Input device: " << std::quoted(sInputDevice()) << ", output device: " << std::quoted(sOutputDevice()) << LL_ENDL;
|
||||
|
||||
static LLCachedControl<F32> sMicLevel(gSavedSettings, "AudioLevelMic");
|
||||
setMicGain(sMicLevel);
|
||||
|
||||
|
|
@ -896,7 +898,7 @@ void LLWebRTCVoiceClient::OnConnectionShutDown(const std::string &channelID, con
|
|||
{
|
||||
if (mSession && mSession->mChannelID == channelID)
|
||||
{
|
||||
LL_DEBUGS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL;
|
||||
LL_INFOS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
mSession->removeAllParticipants(regionID);
|
||||
|
|
@ -1504,6 +1506,11 @@ bool LLWebRTCVoiceClient::compareChannels(const LLSD &channelInfo1, const LLSD &
|
|||
// we're muting the mic, so tell each session such
|
||||
void LLWebRTCVoiceClient::setMuteMic(bool muted)
|
||||
{
|
||||
if (mMuteMic != muted)
|
||||
{
|
||||
LL_INFOS("Voice") << "( " << (muted ? "true" : "false") << " )" << LL_ENDL;
|
||||
}
|
||||
|
||||
mMuteMic = muted;
|
||||
// when you're hidden, your mic is always muted.
|
||||
if (!mHidden)
|
||||
|
|
@ -1552,14 +1559,10 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled)
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE;
|
||||
|
||||
LL_DEBUGS("Voice")
|
||||
<< "( " << (enabled ? "enabled" : "disabled") << " )"
|
||||
<< " was "<< (mVoiceEnabled ? "enabled" : "disabled")
|
||||
<< " coro "<< (mIsCoroutineActive ? "active" : "inactive")
|
||||
<< LL_ENDL;
|
||||
|
||||
if (enabled != mVoiceEnabled)
|
||||
{
|
||||
LL_INFOS("Voice") << "( " << (enabled ? "enabled" : "disabled") << " )"
|
||||
<< ", coro: " << (mIsCoroutineActive ? "active" : "inactive") << LL_ENDL;
|
||||
// TODO: Refactor this so we don't call into LLVoiceChannel, but simply
|
||||
// use the status observer
|
||||
mVoiceEnabled = enabled;
|
||||
|
|
@ -2485,7 +2488,7 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connectio
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE;
|
||||
|
||||
LL_DEBUGS("Voice") << "Disconnecting voice." << LL_ENDL;
|
||||
LL_INFOS("Voice") << "Disconnecting voice." << LL_ENDL;
|
||||
if (connection->mWebRTCDataInterface)
|
||||
{
|
||||
connection->mWebRTCDataInterface->unsetDataObserver(connection.get());
|
||||
|
|
@ -2593,6 +2596,7 @@ void LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
|
|||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
LL_INFOS("Voice") << "Voice connection request: " << (status ? "Success" : status.toString()) << LL_ENDL;
|
||||
if (status)
|
||||
{
|
||||
OnVoiceConnectionRequestSuccess(result);
|
||||
|
|
|
|||
|
|
@ -6078,7 +6078,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
if (is_pbr)
|
||||
{
|
||||
// tell texture streaming system to ignore blinn-phong textures
|
||||
facep->setTexture(LLRender::DIFFUSE_MAP, nullptr);
|
||||
// except the special case of the diffuse map containing a
|
||||
// media texture that will be reused for swapping on to the pbr face
|
||||
if (!facep->hasMedia())
|
||||
{
|
||||
facep->setTexture(LLRender::DIFFUSE_MAP, nullptr);
|
||||
}
|
||||
facep->setTexture(LLRender::NORMAL_MAP, nullptr);
|
||||
facep->setTexture(LLRender::SPECULAR_MAP, nullptr);
|
||||
|
||||
|
|
@ -7073,8 +7078,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
|
|||
{ //shiny
|
||||
if (tex && tex->getPrimaryFormat() == GL_ALPHA) // <FS:Beq/> [FIRE-34534] guard additional cases of tex == null
|
||||
{ //invisiprim+shiny
|
||||
registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY);
|
||||
registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
|
||||
if (!facep->getViewerObject()->isAttachment() && !facep->getViewerObject()->isRiggedMesh())
|
||||
{
|
||||
registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY);
|
||||
registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
|
||||
}
|
||||
}
|
||||
else if (!hud_group)
|
||||
{ //deferred rendering
|
||||
|
|
@ -7110,7 +7118,10 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
|
|||
{ //not alpha and not shiny
|
||||
if (!is_alpha && tex && tex->getPrimaryFormat() == GL_ALPHA) // <FS:Beq/> FIRE-34540 bugsplat crash caused by tex==nullptr. This stops the crash, but should we continue and leave the face unregistered instead of falling through?
|
||||
{ //invisiprim
|
||||
registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
|
||||
if (!facep->getViewerObject()->isAttachment() && !facep->getViewerObject()->isRiggedMesh())
|
||||
{
|
||||
registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
|
||||
}
|
||||
}
|
||||
else if (fullbright || bake_sunlight)
|
||||
{ //fullbright
|
||||
|
|
|
|||
|
|
@ -473,6 +473,7 @@ void LLPipeline::init()
|
|||
stop_glerror();
|
||||
|
||||
//create render pass pools
|
||||
getPool(LLDrawPool::POOL_WATEREXCLUSION);
|
||||
getPool(LLDrawPool::POOL_ALPHA_PRE_WATER);
|
||||
getPool(LLDrawPool::POOL_ALPHA_POST_WATER);
|
||||
getPool(LLDrawPool::POOL_SIMPLE);
|
||||
|
|
@ -732,6 +733,8 @@ void LLPipeline::cleanup()
|
|||
// don't delete wl sky pool it was handled above in the for loop
|
||||
//delete mWLSkyPool;
|
||||
mWLSkyPool = NULL;
|
||||
delete mWaterExclusionPool;
|
||||
mWaterExclusionPool = nullptr;
|
||||
|
||||
releaseGLBuffers();
|
||||
|
||||
|
|
@ -1013,6 +1016,15 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
|
|||
{LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("mPostMapBuffer"); // <FS:Beq/> improve Tracy scoping
|
||||
mPostMap.allocate(resX, resY, screenFormat);
|
||||
} // <FS:Beq/> improve Tracy scoping
|
||||
// The water exclusion mask needs its own depth buffer so we can take care of the problem of multiple water planes.
|
||||
// Should we ever make water not just a plane, it also aids with that as well as the water planes will be rendered into the mask.
|
||||
// Why do we do this? Because it saves us some janky logic in the exclusion shader when we generate the mask.
|
||||
// Regardless, this should always only be an R8 texture unless we choose to start having multiple kinds of exclusion that 8 bits can't handle.
|
||||
// - Geenz 2025-02-06
|
||||
bool success = mWaterExclusionMask.allocate(resX, resY, GL_R8, true);
|
||||
|
||||
assert(success);
|
||||
|
||||
// used to scale down textures
|
||||
// See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown
|
||||
{LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DownResBuffer");// <FS:Beq/> create an independent preview screen target
|
||||
|
|
@ -1294,6 +1306,8 @@ void LLPipeline::releaseGLBuffers()
|
|||
|
||||
mSceneMap.release();
|
||||
|
||||
mWaterExclusionMask.release();
|
||||
|
||||
mPostMap.release();
|
||||
|
||||
mFXAAMap.release();
|
||||
|
|
@ -1806,6 +1820,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
|
|||
poolp = mPBRAlphaMaskPool;
|
||||
break;
|
||||
|
||||
case LLDrawPool::POOL_WATEREXCLUSION:
|
||||
poolp = mWaterExclusionPool;
|
||||
break;
|
||||
|
||||
default:
|
||||
llassert(0);
|
||||
LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL;
|
||||
|
|
@ -4238,6 +4256,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)
|
|||
}
|
||||
}
|
||||
|
||||
// Render all of our geometry that's required after our deferred pass.
|
||||
// This is gonna be stuff like alpha, water, etc.
|
||||
void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
|
||||
|
|
@ -4254,6 +4274,10 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
|
|||
|
||||
bool done_atmospherics = LLPipeline::sRenderingHUDs; //skip atmospherics on huds
|
||||
bool done_water_haze = done_atmospherics;
|
||||
bool done_water_exclusion = false;
|
||||
|
||||
// do water exclusion just before water pass.
|
||||
U32 water_exclusion_pass = LLDrawPool::POOL_WATEREXCLUSION;
|
||||
|
||||
// do atmospheric haze just before post water alpha
|
||||
U32 atmospherics_pass = LLDrawPool::POOL_ALPHA_POST_WATER;
|
||||
|
|
@ -4292,6 +4316,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
|
|||
|
||||
cur_type = poolp->getType();
|
||||
|
||||
if (cur_type >= water_exclusion_pass && !done_water_exclusion)
|
||||
{ // do water exclusion against depth buffer before rendering alpha
|
||||
doWaterExclusionMask();
|
||||
done_water_exclusion = true;
|
||||
}
|
||||
|
||||
if (cur_type >= atmospherics_pass && !done_atmospherics)
|
||||
{ // do atmospherics against depth buffer before rendering alpha
|
||||
doAtmospherics();
|
||||
|
|
@ -5371,6 +5401,17 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
|
|||
}
|
||||
break;
|
||||
|
||||
case LLDrawPool::POOL_WATEREXCLUSION:
|
||||
if (mWaterExclusionPool)
|
||||
{
|
||||
llassert(0);
|
||||
LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water Exclusion Pool" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mWaterExclusionPool = new_poolp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
llassert(0);
|
||||
|
|
@ -5493,6 +5534,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
|
|||
mPBRAlphaMaskPool = NULL;
|
||||
break;
|
||||
|
||||
case LLDrawPool::POOL_WATEREXCLUSION:
|
||||
llassert(poolp == mWaterExclusionPool);
|
||||
mWaterExclusionPool = nullptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
llassert(0);
|
||||
LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL;
|
||||
|
|
@ -7991,7 +8037,7 @@ bool LLPipeline::renderSnapshotFrame(LLRenderTarget* src, LLRenderTarget* dst)
|
|||
{
|
||||
float frame_width = w;
|
||||
float frame_height = frame_width / snapshot_aspect;
|
||||
// Centre this box in [0..1]×[0..1]
|
||||
// Centre this box in [0..1]×[0..1]
|
||||
float y_offset = 0.5f * (h - frame_height);
|
||||
left = 0.f;
|
||||
top = y_offset / h;
|
||||
|
|
@ -8002,7 +8048,7 @@ bool LLPipeline::renderSnapshotFrame(LLRenderTarget* src, LLRenderTarget* dst)
|
|||
{
|
||||
float frame_height = h;
|
||||
float frame_width = h * snapshot_aspect;
|
||||
// Centre this box in [0..1]×[0..1]
|
||||
// Centre this box in [0..1]×[0..1]
|
||||
float x_offset = 0.5f * (w - frame_width);
|
||||
left = x_offset / w;
|
||||
top = 0.f;
|
||||
|
|
@ -9258,6 +9304,7 @@ void LLPipeline::renderDeferredLighting()
|
|||
LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
|
||||
LLPipeline::RENDER_TYPE_TERRAIN,
|
||||
LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_WATEREXCLUSION,
|
||||
END_RENDER_TYPES);
|
||||
|
||||
renderGeomPostDeferred(*LLViewerCamera::getInstance());
|
||||
|
|
@ -9396,6 +9443,8 @@ void LLPipeline::doWaterHaze()
|
|||
static LLStaticHashedString above_water_str("above_water");
|
||||
haze_shader.uniform1i(above_water_str, sUnderWaterRender ? -1 : 1);
|
||||
|
||||
haze_shader.bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &mWaterExclusionMask);
|
||||
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
LLGLDepthTest depth(GL_FALSE);
|
||||
|
|
@ -9426,6 +9475,17 @@ void LLPipeline::doWaterHaze()
|
|||
}
|
||||
}
|
||||
|
||||
void LLPipeline::doWaterExclusionMask()
|
||||
{
|
||||
mWaterExclusionMask.bindTarget();
|
||||
glClearColor(1, 1, 1, 1);
|
||||
mWaterExclusionMask.clear();
|
||||
mWaterExclusionPool->render();
|
||||
|
||||
mWaterExclusionMask.flush();
|
||||
glClearColor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
|
||||
{
|
||||
//construct frustum
|
||||
|
|
|
|||
|
|
@ -337,6 +337,9 @@ public:
|
|||
// should be called just before rendering pre-water alpha objects
|
||||
void doWaterHaze();
|
||||
|
||||
// Generate the water exclusion surface mask.
|
||||
void doWaterExclusionMask();
|
||||
|
||||
void postDeferredGammaCorrect(LLRenderTarget* screen_target);
|
||||
|
||||
void generateSunShadow(LLCamera& camera);
|
||||
|
|
@ -506,6 +509,7 @@ public:
|
|||
RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
|
||||
RENDER_TYPE_CONTROL_AV = LLDrawPool::POOL_CONTROL_AV, // Animesh
|
||||
RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
|
||||
RENDER_TYPE_WATEREXCLUSION = LLDrawPool::POOL_WATEREXCLUSION,
|
||||
RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER,
|
||||
RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
|
||||
RENDER_TYPE_GLTF_PBR = LLDrawPool::POOL_GLTF_PBR,
|
||||
|
|
@ -733,6 +737,7 @@ public:
|
|||
LLRenderTarget mSpotShadow[2];
|
||||
|
||||
LLRenderTarget mPbrBrdfLut;
|
||||
LLRenderTarget mWaterExclusionMask;
|
||||
|
||||
// copy of the color/depth buffer just before gamma correction
|
||||
// for use by SSR
|
||||
|
|
@ -979,6 +984,7 @@ protected:
|
|||
LLDrawPool* mWLSkyPool = nullptr;
|
||||
LLDrawPool* mPBROpaquePool = nullptr;
|
||||
LLDrawPool* mPBRAlphaMaskPool = nullptr;
|
||||
LLDrawPool* mWaterExclusionPool = nullptr;
|
||||
|
||||
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue