parent
db485adbeb
commit
d8dd4d9c0c
|
|
@ -404,6 +404,11 @@ S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright)
|
|||
return mTextureList.setFullbright(index, fullbright);
|
||||
}
|
||||
|
||||
S32 LLPrimitive::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target)
|
||||
{
|
||||
return mTextureList.setRenderableTarget(te, target);
|
||||
}
|
||||
|
||||
S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags)
|
||||
{
|
||||
return mTextureList.setMediaFlags(index, media_flags);
|
||||
|
|
|
|||
|
|
@ -485,6 +485,7 @@ public:
|
|||
virtual S32 setTETexGen(const U8 te, const U8 texgen);
|
||||
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 flags);
|
||||
virtual S32 setTEGlow(const U8 te, const F32 glow);
|
||||
virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
|
||||
|
|
|
|||
|
|
@ -341,6 +341,16 @@ S32 LLPrimTextureList::setFullbright(const U8 index, const U8 fullbright)
|
|||
return TEM_CHANGE_NONE;
|
||||
}
|
||||
|
||||
S32 LLPrimTextureList::setRenderableTarget(const U8 index, const U8 target)
|
||||
{
|
||||
if (index < mEntryList.size())
|
||||
{
|
||||
return mEntryList[index]->setRenderableTarget((LLTextureEntry::eRenderableTarget)target);
|
||||
}
|
||||
|
||||
return TEM_CHANGE_NONE;
|
||||
}
|
||||
|
||||
S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags)
|
||||
{
|
||||
if (index < mEntryList.size())
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ public:
|
|||
S32 setTexGen(const U8 index, const U8 texgen);
|
||||
S32 setShiny(const U8 index, const U8 shiny);
|
||||
S32 setFullbright(const U8 index, const U8 t);
|
||||
S32 setRenderableTarget(const U8 index, const U8 target);
|
||||
S32 setMediaFlags(const U8 index, const U8 media_flags);
|
||||
S32 setGlow(const U8 index, const F32 glow);
|
||||
S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID);
|
||||
|
|
|
|||
|
|
@ -504,6 +504,16 @@ S32 LLTextureEntry::setFullbright(U8 fullbright)
|
|||
return TEM_CHANGE_NONE;
|
||||
}
|
||||
|
||||
S32 LLTextureEntry::setRenderableTarget(eRenderableTarget target)
|
||||
{
|
||||
if (getRenderableTarget() != target) {
|
||||
mRenderableTarget = target;
|
||||
return TEM_CHANGE_TEXTURE;
|
||||
}
|
||||
|
||||
return TEM_CHANGE_NONE;
|
||||
}
|
||||
|
||||
S32 LLTextureEntry::setShiny(U8 shiny)
|
||||
{
|
||||
shiny &= TEM_SHINY_MASK;
|
||||
|
|
@ -685,6 +695,15 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
|
|||
mMaterialUpdatePending = true;
|
||||
}
|
||||
mMaterial = pMaterialParams;
|
||||
|
||||
// TODO: GZ: We should avoid magic UUIDs in the future, but for development we're using one for the time being. Remove this later.
|
||||
if (mMaterial->getSpecularID().asString() == "da7ecda1-e780-423f-ce27-26df7dc69cb6")
|
||||
{
|
||||
setRenderableTarget(RT_MIRROR);
|
||||
} else {
|
||||
setRenderableTarget(RT_DISABLED);
|
||||
}
|
||||
|
||||
return TEM_CHANGE_TEXTURE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,12 @@ public:
|
|||
TEX_GEN_SPHERICAL = 0x04,
|
||||
TEX_GEN_CYLINDRICAL = 0x06
|
||||
} eTexGen;
|
||||
|
||||
|
||||
typedef enum e_renderable_target {
|
||||
RT_DISABLED = 0x00,
|
||||
RT_MIRROR = 0x02
|
||||
} eRenderableTarget;
|
||||
|
||||
LLTextureEntry();
|
||||
LLTextureEntry(const LLUUID& tex_id);
|
||||
|
|
@ -134,7 +140,9 @@ public:
|
|||
S32 setGlow(F32 glow);
|
||||
S32 setMaterialID(const LLMaterialID& pMaterialID);
|
||||
S32 setMaterialParams(const LLMaterialPtr pMaterialParams);
|
||||
|
||||
|
||||
S32 setRenderableTarget(eRenderableTarget target);
|
||||
|
||||
virtual const LLUUID &getID() const { return mID; }
|
||||
const LLColor4 &getColor() const { return mColor; }
|
||||
const F32 getAlpha() const { return mColor.mV[VALPHA]; }
|
||||
|
|
@ -152,6 +160,7 @@ public:
|
|||
|
||||
U8 getBumpmap() const { return mBump & TEM_BUMP_MASK; }
|
||||
U8 getFullbright() const { return (mBump>>TEM_FULLBRIGHT_SHIFT) & TEM_FULLBRIGHT_MASK; }
|
||||
eRenderableTarget getRenderableTarget() const { return mRenderableTarget; }
|
||||
U8 getShiny() const { return (mBump>>TEM_SHINY_SHIFT) & TEM_SHINY_MASK; }
|
||||
U8 getBumpShiny() const { return mBump & TEM_BUMP_SHINY_MASK; }
|
||||
U8 getBumpShinyFullbright() const { return mBump; }
|
||||
|
|
@ -233,6 +242,7 @@ protected:
|
|||
LLColor4 mColor;
|
||||
U8 mBump; // Bump map, shiny, and fullbright
|
||||
U8 mMediaFlags; // replace with web page, movie, etc.
|
||||
eRenderableTarget mRenderableTarget;
|
||||
F32 mGlow;
|
||||
bool mMaterialUpdatePending;
|
||||
LLMaterialID mMaterialID;
|
||||
|
|
|
|||
|
|
@ -1184,12 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const
|
|||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
S32 index = mTexture[uniform];
|
||||
if (index != -1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public:
|
|||
bool hasAlphaMask = false;
|
||||
bool hasReflectionProbes = false;
|
||||
bool attachNothing = false;
|
||||
bool hasHeroProbes = false;
|
||||
};
|
||||
|
||||
// ============= Structure for caching shader uniforms ===============
|
||||
|
|
|
|||
|
|
@ -238,6 +238,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (features->hasHeroProbes)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/heroProbesUtil.glsl"))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (features->hasShadows)
|
||||
{
|
||||
|
|
@ -1260,6 +1268,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("sceneDepth");
|
||||
mReservedUniforms.push_back("reflectionProbes");
|
||||
mReservedUniforms.push_back("irradianceProbes");
|
||||
mReservedUniforms.push_back("heroProbes");
|
||||
mReservedUniforms.push_back("cloud_noise_texture");
|
||||
mReservedUniforms.push_back("cloud_noise_texture_next");
|
||||
mReservedUniforms.push_back("fullbright");
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ public:
|
|||
SCENE_DEPTH, // "sceneDepth"
|
||||
REFLECTION_PROBES, // "reflectionProbes"
|
||||
IRRADIANCE_PROBES, // "irradianceProbes"
|
||||
HERO_PROBE, // "heroProbes"
|
||||
CLOUD_NOISE_MAP, // "cloud_noise_texture"
|
||||
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
|
||||
FULLBRIGHT, // "fullbright"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue