summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl12
-rw-r--r--indra/newview/llpanelface.cpp18
-rw-r--r--indra/newview/llpanelface.h4
-rw-r--r--indra/newview/llreflectionmap.h11
-rw-r--r--indra/newview/llreflectionmapmanager.cpp135
-rw-r--r--indra/newview/llreflectionmapmanager.h15
-rw-r--r--indra/newview/llselectmgr.cpp41
-rw-r--r--indra/newview/llselectmgr.h1
-rw-r--r--indra/newview/llviewerobject.cpp22
-rw-r--r--indra/newview/llviewerobject.h1
-rw-r--r--indra/newview/llviewershadermgr.cpp2
-rw-r--r--indra/newview/llvovolume.cpp10
-rw-r--r--indra/newview/llvovolume.h1
-rw-r--r--indra/newview/pipeline.cpp7
16 files changed, 270 insertions, 29 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2b2a2d9d1b..270d5e6869 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9175,6 +9175,17 @@
<real>0.00</real>
</array>
</map>
+ <key>RenderMirrors</key>
+ <map>
+ <key>Comment</key>
+ <string>Renders realtime mirrors.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RenderScreenSpaceReflections</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 1b2a34ef01..298ddf92a7 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n,
uniform samplerCubeArray reflectionProbes;
uniform samplerCubeArray irradianceProbes;
+
uniform sampler2D sceneMap;
uniform int cube_snapshot;
uniform float max_probe_lod;
@@ -70,6 +71,9 @@ layout (std140) uniform ReflectionProbes
// number of reflection probes present in refSphere
int refmapCount;
+
+ vec4 heroPosition[1];
+ int heroProbeCount;
};
// Inputs
@@ -513,6 +517,10 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
v = env_mat * v;
+#if defined(HERO_PROBES)
+ vec3 mirror = textureLod(heroProbes, vec4(v.xyz, 0), lod).rgb;
+#endif
+
vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y;
return ret.rgb;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 4ef003e0cb..a63d445115 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -32,6 +32,14 @@ uniform sampler2D specularRect;
uniform sampler2D normalMap;
uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+uniform samplerCubeArray heroProbes;
+
+layout (std140) uniform HeroProbeData
+{
+ vec4 heroPosition[1];
+ int heroProbeCount;
+};
+
const float M_PI = 3.14159265;
#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
@@ -290,7 +298,7 @@ void main()
vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom));
color = fogged.rgb;
#endif
-
- frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results
+ frag_color.rgb = textureLod(heroProbes, vec4(norm.xyz, 0), 0).rgb;
+ //frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results
frag_color.a = 0.0;
}
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 7d6015f557..6b737b6895 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -592,6 +592,17 @@ void LLPanelFace::sendFullbright()
LLSelectMgr::getInstance()->selectionSetFullbright( fullbright );
}
+void LLPanelFace::sendMirror()
+{
+ LLCheckBoxCtrl* mCheckMirror = getChild<LLCheckBoxCtrl>("checkbox mirror");
+
+ if (!mCheckMirror)
+ return;
+
+ LLTextureEntry::eRenderableTarget target = mCheckMirror->get() ? LLTextureEntry::RT_MIRROR : LLTextureEntry::RT_DISABLED;
+ LLSelectMgr::getInstance()->selectionSetRenderableTarget(target);
+}
+
void LLPanelFace::sendColor()
{
@@ -1686,6 +1697,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChild<LLUICtrl>("shinyOffsetV")->setValue(offset_y);
getChild<LLUICtrl>("glossiness")->setValue(material->getSpecularLightExponent());
getChild<LLUICtrl>("environment")->setValue(material->getEnvironmentIntensity());
+ getChild<LLUICtrl>("mirror")->setValue(material->getEnvironmentIntensity());
updateShinyControls(!material->getSpecularID().isNull(), true);
}
@@ -2994,6 +3006,12 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata)
self->sendFullbright();
}
+void LLPanelFace::onCommitMirror(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->sendMirror();
+}
+
// static
void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata)
{
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 106259b84a..f6d6d99d9f 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -138,6 +138,7 @@ protected:
void sendTexGen(); // applies and sends bump map
void sendShiny(U32 shininess); // applies and sends shininess
void sendFullbright(); // applies and sends full bright
+ void sendMirror();
void sendGlow();
void alignTestureLayer();
@@ -227,7 +228,8 @@ protected:
static void onCommitShiny( LLUICtrl* ctrl, void* userdata);
static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata);
static void onCommitFullbright( LLUICtrl* ctrl, void* userdata);
- static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
+ static void onCommitMirror(LLUICtrl* ctrl, void* userdata);
+ static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata);
static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo);
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index 7ea0fe6187..831a6358ee 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -36,6 +36,15 @@ class alignas(16) LLReflectionMap : public LLRefCount
{
LL_ALIGN_NEW
public:
+
+ enum class ProbeType
+ {
+ ALL = 0,
+ RADIANCE,
+ IRRADIANCE,
+ REFLECTION
+ };
+
// allocate an environment map of the given resolution
LLReflectionMap();
@@ -127,5 +136,7 @@ public:
GLuint mOcclusionQuery = 0;
bool mOccluded = false;
U32 mOcclusionPendingFrames = 0;
+
+ ProbeType mType;
};
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index e30aba3df7..8e7d073167 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -130,6 +130,13 @@ void LLReflectionMapManager::update()
U32 targetRes = mProbeResolution * 4; // super sample
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
}
+
+ if (!mHeroRenderTarget.isComplete())
+ {
+ U32 color_fmt = GL_RGB16F;
+ U32 targetRes = mHeroProbeResolution * 2;
+ mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
+ }
if (mMipChain.empty())
{
@@ -315,7 +322,7 @@ void LLReflectionMapManager::update()
mRadiancePass = mRealtimeRadiancePass;
for (U32 i = 0; i < 6; ++i)
{
- updateProbeFace(closestDynamic, i);
+ updateProbeFace(closestDynamic, i, mProbeResolution);
}
mRealtimeRadiancePass = !mRealtimeRadiancePass;
@@ -354,6 +361,10 @@ void LLReflectionMapManager::update()
oldestOccluded->autoAdjustOrigin();
oldestOccluded->mLastUpdateTime = gFrameTimeSeconds;
}
+
+
+ doHeroProbeUpdate();
+
}
LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
@@ -528,7 +539,7 @@ void LLReflectionMapManager::doProbeUpdate()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(mUpdatingProbe != nullptr);
- updateProbeFace(mUpdatingProbe, mUpdatingFace);
+ updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution);
if (++mUpdatingFace == 6)
{
@@ -547,6 +558,21 @@ void LLReflectionMapManager::doProbeUpdate()
}
}
+void LLReflectionMapManager::doHeroProbeUpdate()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(mHeroProbe != nullptr);
+
+ touch_default_probe(mHeroProbe);
+
+ for (int i = 0; i < 6; i++)
+ {
+ gPipeline.mRT = &gPipeline.mAuxillaryRT;
+ mHeroProbe->update(mHeroProbeResolution, i);
+ gPipeline.mRT = &gPipeline.mMainRT;
+ }
+}
+
// Do the reflection map update render passes.
// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
@@ -555,10 +581,20 @@ void LLReflectionMapManager::doProbeUpdate()
// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe.
// In effect this simulates single-bounce lighting.
-void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
+void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer<LLCubeMapArray> cubeArray)
{
// hacky hot-swap of camera specific render targets
gPipeline.mRT = &gPipeline.mAuxillaryRT;
+
+ LLRenderTarget* target = &mRenderTarget;
+
+ S32 sourceIdx = mReflectionProbeCount;
+
+ if (probeResolution == mHeroProbeResolution)
+ {
+ sourceIdx = 0;
+ target = &mHeroRenderTarget;
+ }
mLightScale = 1.f;
static LLCachedControl<F32> max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f);
@@ -577,20 +613,18 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY,
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);
+ probe->update(target->getWidth(), face);
gPipeline.popRenderTypeMask();
}
else
{
- probe->update(mRenderTarget.getWidth(), face);
+ probe->update(target->getWidth(), face);
}
gPipeline.mRT = &gPipeline.mMainRT;
- S32 sourceIdx = mReflectionProbeCount;
-
- if (probe != mUpdatingProbe)
+ if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION)
{ // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
sourceIdx += 1;
}
@@ -611,7 +645,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.loadIdentity();
gGL.flush();
- U32 res = mProbeResolution * 2;
+ U32 res = probeResolution * 2;
static LLStaticHashedString resScale("resScale");
static LLStaticHashedString direction("direction");
@@ -623,20 +657,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
// perform a gaussian blur on the super sampled render before downsampling
{
gGaussianProgram.bind();
- gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2));
+ gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 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();
+ target->bindTarget();
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- mRenderTarget.flush();
+ target->flush();
// vertical
gGaussianProgram.uniform2f(direction, 0.f, 1.f);
- gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);
+ gGL.getTexUnit(diffuseChannel)->bind(target);
screen_rt->bindTarget();
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@@ -644,7 +678,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
}
- S32 mips = log2((F32)mProbeResolution) + 0.5f;
+ S32 mips = log2((F32)probeResolution) + 0.5f;
gReflectionMipProgram.bind();
S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
@@ -663,7 +697,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
}
- gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));
+ gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2));
gPipeline.mScreenTriangleVB->setBuffer();
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@@ -675,14 +709,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
if (mip >= 0)
{
LL_PROFILE_GPU_ZONE("probe mip copy");
- mTexture->bind(0);
+ probe->mCubeArray->bind(0);
//glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res);
//if (i == 0)
//{
//glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
//}
- mTexture->unbind();
+ probe->mCubeArray->unbind();
}
mMipChain[i].flush();
}
@@ -695,7 +729,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gReflectionMipProgram.unbind();
}
- if (face == 5)
+ if (face == 5 && probe->mType != LLReflectionMap::ProbeType::REFLECTION)
{
mMipChain[0].bindTarget();
static LLStaticHashedString sSourceIdx("sourceIdx");
@@ -707,7 +741,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
mVertexBuffer->setBuffer();
S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
- mTexture->bind(channel);
+ probe->mCubeArray->bind(channel);
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
@@ -722,7 +756,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
gRadianceGenProgram.uniform1f(sMipLevel, i);
- gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
+ gRadianceGenProgram.uniform1i(sWidth, probeResolution);
for (int cf = 0; cf < 6; ++cf)
{ // for each cube face
@@ -752,7 +786,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
//generate irradiance map
gIrradianceGenProgram.bind();
S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
- mTexture->bind(channel);
+ probe->mCubeArray->bind(channel);
gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
@@ -787,7 +821,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
S32 res = mMipChain[i].getWidth();
mIrradianceMaps->bind(channel);
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
- mTexture->bind(channel);
+ probe->mCubeArray->bind(channel);
}
}
}
@@ -890,7 +924,7 @@ void LLReflectionMapManager::updateUniforms()
GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
// numbrer of active refmaps
- GLint refmapCount;
+ GLint refmapCount;
};
mReflectionMaps.resize(mReflectionProbeCount);
@@ -1068,7 +1102,7 @@ void LLReflectionMapManager::updateUniforms()
#endif
rpd.refmapCount = count;
-
+
//copy rpd into uniform buffer object
if (mUBO == 0)
{
@@ -1081,7 +1115,35 @@ void LLReflectionMapManager::updateUniforms()
glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
+
+ struct HeroProbeData
+ {
+ LLVector4 heroPosition[1];
+ GLint heroProbeCount = 1;
+ };
+
+ HeroProbeData hpd;
+
+ modelview.loadu(gGLModelView);
+
+ oa.set(0, 0, 0, 0);
+ hpd.heroProbeCount = 1;
+ modelview.affineTransform(mHeroProbe->mOrigin, oa);
+ hpd.heroPosition[0].set(oa.getF32ptr());
+
+ //copy rpd into uniform buffer object
+ if (mUBO == 0)
+ {
+ glGenBuffers(1, &mHeroUBO);
+ }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
+ glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ }
+
#if 0
if (!gCubeSnapshot)
{
@@ -1214,7 +1276,7 @@ void LLReflectionMapManager::initReflectionMaps()
{
U32 count = LL_MAX_REFLECTION_PROBE_COUNT;
- if (mTexture.isNull() || mReflectionProbeCount != count || mReset)
+ if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull())
{
mReset = false;
mReflectionProbeCount = count;
@@ -1263,6 +1325,22 @@ void LLReflectionMapManager::initReflectionMaps()
mDefaultProbe->mRadius = 4096.f;
mDefaultProbe->mProbeIndex = 0;
touch_default_probe(mDefaultProbe);
+
+ mHeroProbeResolution = 512;
+
+ mHeroArray = new LLCubeMapArray();
+ mHeroArray->allocate(mHeroProbeResolution, 3, 1);
+
+ if (mHeroProbe.isNull()) {
+ mHeroProbe = new LLReflectionMap();
+ }
+
+ mHeroProbe->mCubeIndex = 0;
+ mHeroProbe->mCubeArray = mHeroArray;
+ mHeroProbe->mDistance = 64.f;
+ mHeroProbe->mRadius = 4096.f;
+ mHeroProbe->mProbeIndex = 0;
+ touch_default_probe(mHeroProbe);
}
@@ -1291,11 +1369,13 @@ void LLReflectionMapManager::cleanup()
{
mVertexBuffer = nullptr;
mRenderTarget.release();
+ mHeroRenderTarget.release();
mMipChain.clear();
mTexture = nullptr;
mIrradianceMaps = nullptr;
+ mHeroArray = nullptr;
mProbes.clear();
mKillList.clear();
@@ -1306,9 +1386,14 @@ void LLReflectionMapManager::cleanup()
mDefaultProbe = nullptr;
mUpdatingProbe = nullptr;
+
+ mHeroProbe = nullptr;
glDeleteBuffers(1, &mUBO);
mUBO = 0;
+
+ glDeleteBuffers(1, &mHeroUBO);
+ mHeroUBO = 0;
// note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state
initCubeFree();
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 5a3901cae9..2ca9a8d598 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -125,11 +125,15 @@ private:
// render target for cube snapshots
// used to generate mipmaps without doing a copy-to-texture
LLRenderTarget mRenderTarget;
+
+ LLRenderTarget mHeroRenderTarget;
std::vector<LLRenderTarget> mMipChain;
// storage for reflection probe radiance maps (plus two scratch space cubemaps)
LLPointer<LLCubeMapArray> mTexture;
+
+ LLPointer<LLCubeMapArray> mHeroArray;
// vertex buffer for pushing verts to filter shaders
LLPointer<LLVertexBuffer> mVertexBuffer;
@@ -142,9 +146,11 @@ private:
// perform an update on the currently updating Probe
void doProbeUpdate();
+
+ void doHeroProbeUpdate();
// update the specified face of the specified probe
- void updateProbeFace(LLReflectionMap* probe, U32 face);
+ void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution);
// list of active reflection maps
std::vector<LLPointer<LLReflectionMap> > mProbes;
@@ -157,6 +163,9 @@ private:
// handle to UBO
U32 mUBO = 0;
+
+ // Hero UBO
+ U32 mHeroUBO = 0;
// list of maps being used for rendering
std::vector<LLReflectionMap*> mReflectionMaps;
@@ -176,12 +185,16 @@ private:
bool mRealtimeRadiancePass = false;
LLPointer<LLReflectionMap> mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0)
+
+ LLPointer<LLReflectionMap> mHeroProbe;
// number of reflection probes to use for rendering
U32 mReflectionProbeCount;
// resolution of reflection probes
U32 mProbeResolution = 128;
+
+ U32 mHeroProbeResolution = 512;
// maximum LoD of reflection probes (mip levels - 1)
F32 mMaxProbeLOD = 6.f;
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index dca341e5a2..19ce8f6a55 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2347,6 +2347,47 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright)
getSelection()->applyToObjects(&sendfunc);
}
+void LLSelectMgr::selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target)
+{
+ struct f : public LLSelectedTEFunctor
+ {
+ LLTextureEntry::eRenderableTarget mRenderableTarget;
+
+ f(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {}
+
+ bool apply(LLViewerObject* object, S32 te)
+ {
+ if (object->permModify())
+ {
+ object->setTERenderableTarget(te, mRenderableTarget);
+ }
+
+ return true;
+ }
+ } setfunc(target);
+
+ getSelection()->applyToTEs(&setfunc);
+
+ struct g : public LLSelectedObjectFunctor
+ {
+ LLTextureEntry::eRenderableTarget mRenderableTarget;
+
+ g(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {}
+
+ virtual bool apply(LLViewerObject* object)
+ {
+ if (object->permModify())
+ {
+ object->sendTEUpdate();
+ }
+
+ return true;
+ }
+ } sendfunc(target);
+
+ getSelection()->applyToObjects(&sendfunc);
+}
+
// This function expects media_data to be a map containing relevant
// media data name/value pairs (e.g. home_url, etc.)
void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data)
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index ca9a32f0db..93d750215b 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -653,6 +653,7 @@ public:
void selectionSetGlow(const F32 glow);
void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1);
void selectionRemoveMaterial();
+ void selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target);
void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE);
void selectionSetObjectName(const std::string& name);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index e67750af7c..8930b2453b 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -5284,6 +5284,28 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright)
return retval;
}
+S32 LLViewerObject::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target)
+{
+ S32 retval = 0;
+
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
+ }
+ else if (target != tep->getRenderableTarget())
+ {
+ retval = LLPrimitive::setTERenderableTarget(te, target);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ //gPipeline.markMirror(mDrawable);
+ }
+ }
+
+ return retval;
+}
+
S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags)
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bf82c43cd3..f4f596bfd0 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -359,6 +359,7 @@ public:
/*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics
/*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny );
/*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright );
+ /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target);
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags );
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 5eae1dfb18..f6f1cf6854 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -2228,6 +2228,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredSoftenProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
}
+
+ gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1");
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
{ //if using SSAO, take screen space light map into account as if shadows are enabled
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 8160785d75..8eacdd2162 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -2344,6 +2344,16 @@ S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
return res;
}
+S32 LLVOVolume::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget mirror)
+{
+ S32 res = LLViewerObject::setTERenderableTarget(te, mirror);
+ if (res)
+ {
+ //gPipeline.markMirror(mDrawable);
+ }
+ return res;
+}
+
S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump)
{
S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index acba18383f..f2162ef244 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -209,6 +209,7 @@ public:
/*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override;
/*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override;
/*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override;
+ /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) override;
/*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override;
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override;
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 38f27d4dfa..d6e0bf1b09 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8419,6 +8419,13 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)
mReflectionMapManager.mIrradianceMaps->bind(channel);
bound = true;
}
+
+ channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ if (channel > -1 && mReflectionMapManager.mHeroArray.notNull())
+ {
+ mReflectionMapManager.mHeroArray->bind(channel);
+ bound = true;
+ }
if (bound)
{