SL-17285 Add proper reflection probe support to LLVOVolume, LLPrimitive, and LLPanelVolume

master
Dave Parks 2022-06-02 18:42:38 -05:00
parent 3b3d3d88d1
commit 220afbcda0
16 changed files with 519 additions and 73 deletions

View File

@ -81,6 +81,14 @@ const F32 LIGHT_MIN_CUTOFF = 0.0f;
const F32 LIGHT_DEFAULT_CUTOFF = 0.0f;
const F32 LIGHT_MAX_CUTOFF = 180.f;
// reflection probes
const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f;
const F32 REFLECTION_PROBE_MAX_AMBIANCE = 1.f;
const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f;
const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f;
const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f;
const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f;
// "Tension" => [0,10], increments of 0.1
const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f;
const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f;
@ -1811,6 +1819,93 @@ bool LLLightParams::fromLLSD(LLSD& sd)
//============================================================================
LLReflectionProbeParams::LLReflectionProbeParams()
{
mType = PARAMS_REFLECTION_PROBE;
}
BOOL LLReflectionProbeParams::pack(LLDataPacker& dp) const
{
dp.packF32(mAmbiance, "ambiance");
dp.packF32(mClipDistance, "clip_distance");
dp.packU8(mVolumeType, "volume_type");
return TRUE;
}
BOOL LLReflectionProbeParams::unpack(LLDataPacker& dp)
{
F32 ambiance;
F32 clip_distance;
U8 volume_type;
dp.unpackF32(ambiance, "ambiance");
setAmbiance(ambiance);
dp.unpackF32(clip_distance, "clip_distance");
setClipDistance(clip_distance);
dp.unpackU8(volume_type, "volume_type");
setVolumeType((EInfluenceVolumeType)volume_type);
return TRUE;
}
bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const
{
if (data.mType != PARAMS_REFLECTION_PROBE)
{
return false;
}
const LLReflectionProbeParams* param = (const LLReflectionProbeParams*)&data;
if (param->mAmbiance != mAmbiance)
{
return false;
}
if (param->mClipDistance != mClipDistance)
{
return false;
}
if (param->mVolumeType != mVolumeType)
{
return false;
}
return true;
}
void LLReflectionProbeParams::copy(const LLNetworkData& data)
{
const LLReflectionProbeParams* param = (LLReflectionProbeParams*)&data;
mType = param->mType;
mAmbiance = param->mAmbiance;
mClipDistance = param->mClipDistance;
mVolumeType = param->mVolumeType;
}
LLSD LLReflectionProbeParams::asLLSD() const
{
LLSD sd;
sd["ambiance"] = getAmbiance();
sd["clip_distance"] = getClipDistance();
sd["volume_type"] = getVolumeType();
return sd;
}
bool LLReflectionProbeParams::fromLLSD(LLSD& sd)
{
if (!sd.has("ambiance") ||
!sd.has("clip_distance") ||
!sd.has("volume_type"))
{
return false;
}
setAmbiance((F32)sd["ambiance"].asReal());
setClipDistance((F32)sd["clip_distance"].asReal());
setVolumeType((EInfluenceVolumeType)sd["volume_type"].asInteger());
return true;
}
//============================================================================
LLFlexibleObjectData::LLFlexibleObjectData()
{
mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS;

View File

@ -108,6 +108,7 @@ public:
PARAMS_MESH = 0x60,
PARAMS_EXTENDED_MESH = 0x70,
PARAMS_RENDER_MATERIAL = 0x80,
PARAMS_REFLECTION_PROBE = 0x90,
};
public:
@ -171,6 +172,49 @@ public:
F32 getCutoff() const { return mCutoff; }
};
extern const F32 REFLECTION_PROBE_MIN_AMBIANCE;
extern const F32 REFLECTION_PROBE_MAX_AMBIANCE;
extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE;
extern const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE;
extern const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE;
extern const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
class LLReflectionProbeParams : public LLNetworkData
{
public:
enum EInfluenceVolumeType : U8
{
VOLUME_TYPE_SPHERE = 0, // use a sphere influence volume
VOLUME_TYPE_BOX = 1, // use a box influence volume
DEFAULT_VOLUME_TYPE = VOLUME_TYPE_SPHERE
};
protected:
F32 mAmbiance = REFLECTION_PROBE_DEFAULT_AMBIANCE;
F32 mClipDistance = REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
EInfluenceVolumeType mVolumeType = DEFAULT_VOLUME_TYPE;
public:
LLReflectionProbeParams();
/*virtual*/ BOOL pack(LLDataPacker& dp) const;
/*virtual*/ BOOL unpack(LLDataPacker& dp);
/*virtual*/ bool operator==(const LLNetworkData& data) const;
/*virtual*/ void copy(const LLNetworkData& data);
// LLSD implementations here are provided by Eddy Stryker.
// NOTE: there are currently unused in protocols
LLSD asLLSD() const;
operator LLSD() const { return asLLSD(); }
bool fromLLSD(LLSD& sd);
void setAmbiance(F32 ambiance) { mAmbiance = llclamp(ambiance, REFLECTION_PROBE_MIN_AMBIANCE, REFLECTION_PROBE_MAX_AMBIANCE); }
void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); }
void setVolumeType(EInfluenceVolumeType type) { mVolumeType = llclamp(type, VOLUME_TYPE_SPHERE, VOLUME_TYPE_BOX); }
F32 getAmbiance() const { return mAmbiance; }
F32 getClipDistance() const { return mClipDistance; }
EInfluenceVolumeType getVolumeType() const { return mVolumeType; }
};
//-------------------------------------------------
// This structure is also used in the part of the
// code that creates new flexible objects.

View File

@ -1,5 +1,5 @@
/**
* @file class2/deferred/reflectionProbeF.glsl
* @file class3/deferred/reflectionProbeF.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
@ -42,6 +42,8 @@ layout (std140, binding = 1) uniform ReflectionProbes
mat4 refBox[REFMAP_COUNT];
// list of bounding spheres for reflection probes sorted by distance to camera (closest first)
vec4 refSphere[REFMAP_COUNT];
// extra parameters (currently only .x used for probe ambiance)
vec4 refParams[REFMAP_COUNT];
// index of cube map in reflectionProbes for a corresponding reflection probe
// e.g. cube map channel of refSphere[2] is stored in refIndex[2]
// refIndex.x - cubemap channel in reflectionProbes
@ -55,9 +57,6 @@ layout (std140, binding = 1) uniform ReflectionProbes
// number of reflection probes present in refSphere
int refmapCount;
// intensity of ambient light from reflection probes
float reflectionAmbiance;
};
// Inputs
@ -335,7 +334,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i)
}
}
vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight)
{
float wsum = 0.0;
vec3 col = vec3(0,0,0);
@ -360,7 +359,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
float atten = 1.0-max(d2-r2, 0.0)/(rr-r2);
w *= atten;
w *= p; // boost weight based on priority
col += refcol*w;
col += refcol*w*max(minweight, refParams[i].x);
wsum += w;
}
@ -383,7 +382,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
float w = 1.0/d2;
w *= w;
col += refcol*w;
col += refcol*w*max(minweight, refParams[i].x);
wsum += w;
}
}
@ -399,7 +398,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod)
{
vec3 col = sampleProbes(pos, dir, lod);
vec3 col = sampleProbes(pos, dir, lod, 0.f);
//desaturate
vec3 hcol = col *0.5;
@ -413,7 +412,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod)
col *= 0.333333;
return col*reflectionAmbiance;
return col;
}
@ -445,12 +444,12 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l
if (glossiness > 0.0)
{
float lod = (1.0-glossiness)*reflection_lods;
glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
glossenv = sampleProbes(pos, normalize(refnormpersp), lod, 1.f);
}
if (envIntensity > 0.0)
{
legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0);
legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, 1.f);
}
}

View File

@ -145,6 +145,16 @@ BOOL LLPanelVolume::postBuild()
getChild<LLUICtrl>("Light Ambiance")->setValidateBeforeCommit( precommitValidate);
}
// REFLECTION PROBE Parameters
{
childSetCommitCallback("Reflection Probe Checkbox Ctrl", onCommitIsReflectionProbe, this);
childSetCommitCallback("Probe Shape Type Combo Ctrl", onCommitProbe, this);
childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
}
// PHYSICS Parameters
{
// PhysicsShapeType combobox
@ -360,6 +370,40 @@ void LLPanelVolume::getState( )
getChildView("Light Ambiance")->setEnabled(false);
}
// Reflection Probe
BOOL is_probe = volobjp && volobjp->getIsReflectionProbe();
getChild<LLUICtrl>("Reflection Probe Checkbox Ctrl")->setValue(is_probe);
getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp);
bool probe_enabled = is_probe && editable && single_volume;
getChildView("Probe Volume Type Ctrl")->setEnabled(probe_enabled);
getChildView("Probe Ambiance")->setEnabled(probe_enabled);
getChildView("Probe Near Clip")->setEnabled(probe_enabled);
if (!probe_enabled)
{
getChild<LLComboBox>("Probe Volume Type Ctrl", true)->clear();
getChild<LLSpinCtrl>("Probe Ambiance", true)->clear();
getChild<LLSpinCtrl>("Probe Near Clip", true)->clear();
}
else
{
std::string volume_type;
if (volobjp->getReflectionProbeVolumeType() == LLReflectionProbeParams::VOLUME_TYPE_BOX)
{
volume_type = "Box";
}
else
{
volume_type = "Sphere";
}
getChild<LLComboBox>("Probe Volume Type Ctrl", true)->setValue(volume_type);
getChild<LLSpinCtrl>("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
getChild<LLSpinCtrl>("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
}
// Animated Mesh
BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject();
getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh);
@ -647,6 +691,10 @@ void LLPanelVolume::clearCtrls()
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
getChildView("Reflection Probe Checkbox Ctrl")->setEnabled(false);;
getChildView("Probe Volume Type Ctrl")->setEnabled(false);
getChildView("Probe Ambiance")->setEnabled(false);
getChildView("Probe Near Clip")->setEnabled(false);
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
getChildView("FlexNumSections")->setEnabled(false);
@ -684,6 +732,20 @@ void LLPanelVolume::sendIsLight()
LL_INFOS() << "update light sent" << LL_ENDL;
}
void LLPanelVolume::sendIsReflectionProbe()
{
LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
BOOL value = getChild<LLUICtrl>("Reflection Probe Checkbox Ctrl")->getValue();
volobjp->setIsReflectionProbe(value);
LL_INFOS() << "update reflection probe sent" << LL_ENDL;
}
void LLPanelVolume::sendIsFlexible()
{
LLViewerObject* objectp = mObject;
@ -927,6 +989,35 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
}
//static
void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
{
LLPanelVolume* self = (LLPanelVolume*)userdata;
LLViewerObject* objectp = self->mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
}
LLVOVolume* volobjp = (LLVOVolume*)objectp;
volobjp->setReflectionProbeAmbiance((F32)self->getChild<LLUICtrl>("Probe Ambiance")->getValue().asReal());
volobjp->setReflectionProbeNearClip((F32)self->getChild<LLUICtrl>("Probe Near Clip")->getValue().asReal());
std::string shape_type = self->getChild<LLUICtrl>("Probe Volume Type Ctrl")->getValue().asString();
LLReflectionProbeParams::EInfluenceVolumeType volume_type = LLReflectionProbeParams::DEFAULT_VOLUME_TYPE;
if (shape_type == "Sphere")
{
volume_type = LLReflectionProbeParams::VOLUME_TYPE_SPHERE;
}
else if (shape_type == "Box")
{
volume_type = LLReflectionProbeParams::VOLUME_TYPE_BOX;
}
volobjp->setReflectionProbeVolumeType(volume_type);
}
// static
void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
{
@ -949,6 +1040,15 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item
}
//----------------------------------------------------------------------------
// static
void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata)
{
LLPanelVolume* self = (LLPanelVolume*)userdata;
self->sendIsReflectionProbe();
}
//----------------------------------------------------------------------------
// static
void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
{

View File

@ -56,12 +56,15 @@ public:
void refresh();
void sendIsLight();
void sendIsReflectionProbe();
void sendIsFlexible();
static bool precommitValidate(const LLSD& data);
static void onCommitIsLight( LLUICtrl* ctrl, void* userdata);
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata);
static void onCommitProbe(LLUICtrl* ctrl, void* userdata);
void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
void onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata);

View File

@ -35,7 +35,6 @@ extern F32SecondsImplicit gFrameTimeSeconds;
LLReflectionMap::LLReflectionMap()
{
mLastUpdateTime = gFrameTimeSeconds;
}
void LLReflectionMap::update(U32 resolution, U32 face)
@ -52,7 +51,7 @@ void LLReflectionMap::update(U32 resolution, U32 face)
{
resolution /= 2;
}
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face);
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip());
}
bool LLReflectionMap::shouldUpdate()
@ -215,6 +214,35 @@ bool LLReflectionMap::intersects(LLReflectionMap* other)
return dist < r2;
}
extern LLControlGroup gSavedSettings;
F32 LLReflectionMap::getAmbiance()
{
static LLCachedControl<F32> minimum_ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f);
F32 ret = 0.f;
if (mViewerObject && mViewerObject->getVolume())
{
ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance();
}
return llmax(ret, minimum_ambiance());
}
F32 LLReflectionMap::getNearClip()
{
const F32 MINIMUM_NEAR_CLIP = 0.1f;
F32 ret = 0.f;
if (mViewerObject && mViewerObject->getVolume())
{
ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeNearClip();
}
return llmax(ret, MINIMUM_NEAR_CLIP);
}
bool LLReflectionMap::getBox(LLMatrix4& box)
{
if (mViewerObject)
@ -224,25 +252,8 @@ bool LLReflectionMap::getBox(LLMatrix4& box)
{
LLVOVolume* vobjp = (LLVOVolume*)mViewerObject;
U8 profile = volume->getProfileType();
U8 path = volume->getPathType();
if (profile == LL_PCODE_PROFILE_SQUARE &&
path == LL_PCODE_PATH_LINE)
if (vobjp->getReflectionProbeVolumeType() == LLReflectionProbeParams::VOLUME_TYPE_BOX)
{
// nope
/*box = vobjp->getRelativeXform();
box *= vobjp->mDrawable->getRenderMatrix();
LLMatrix4 modelview(gGLModelView);
box *= modelview;
box.invert();*/
// nope
/*box = LLMatrix4(gGLModelView);
box *= vobjp->mDrawable->getRenderMatrix();
box *= vobjp->getRelativeXform();
box.invert();*/
glh::matrix4f mv(gGLModelView);
glh::matrix4f scale;
LLVector3 s = vobjp->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));

View File

@ -55,9 +55,15 @@ public:
// return true if given Reflection Map's influence volume intersect's with this one's
bool intersects(LLReflectionMap* other);
// Get the ambiance value to use for this probe
F32 getAmbiance();
// Get the near clip plane distance to use for this probe
F32 getNearClip();
// get the encoded bounding box of this probe's influence volume
// will only return a box if this probe has a volume with a square
// profile and a linear path
// will only return a box if this probe is associated with a VOVolume
// with its reflection probe influence volume to to VOLUME_TYPE_BOX
// return false if no bounding box (treat as sphere influence volume)
bool getBox(LLMatrix4& box);

View File

@ -127,18 +127,12 @@ void LLReflectionMapManager::update()
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
// process kill list
for (int i = 0; i < mProbes.size(); )
for (auto& probe : mKillList)
{
auto& iter = std::find(mKillList.begin(), mKillList.end(), mProbes[i]);
if (iter != mKillList.end())
auto& iter = std::find(mProbes.begin(), mProbes.end(), probe);
if (iter != mProbes.end())
{
deleteProbe(i);
mProbes.erase(mProbes.begin() + i);
mKillList.erase(iter);
}
else
{
++i;
deleteProbe(iter - mProbes.begin());
}
}
@ -275,7 +269,7 @@ LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* gr
{
OctreeNode* node = group->getOctreeNode();
F32 size = node->getSize().getF32ptr()[0];
if (size >= 7.f && size <= 17.f)
if (size >= 15.f && size <= 17.f)
{
return addProbe(group);
}
@ -514,15 +508,15 @@ void LLReflectionMapManager::updateUniforms()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
// structure for packing uniform buffer object
// see class2/deferred/softenLightF.glsl
// see class3/deferred/reflectionProbeF.glsl
struct ReflectionProbeData
{
LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed
LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space
LLVector4 refParams[LL_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance)
GLint refIndex[LL_REFLECTION_PROBE_COUNT][4];
GLint refNeighbor[4096];
GLint refmapCount;
GLfloat reflectionAmbiance;
};
mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT);
@ -530,9 +524,6 @@ void LLReflectionMapManager::updateUniforms()
ReflectionProbeData rpd;
static LLCachedControl<F32> ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f);
rpd.reflectionAmbiance = ambiance;
// load modelview matrix into matrix 4a
LLMatrix4a modelview;
modelview.loadu(gGLModelView);
@ -573,6 +564,8 @@ void LLReflectionMapManager::updateUniforms()
rpd.refIndex[count][3] = -rpd.refIndex[count][3];
}
rpd.refParams[count].set(refmap->getAmbiance(), 0.f, 0.f, 0.f);
S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
{
//LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors");

View File

@ -3400,6 +3400,7 @@ void LLTextureFetch::sendRequestListToSimulators()
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
}
S32 packet = req->mLastPacket + 1;
LL_INFOS() << req->mID << ": " << req->mImagePriority << LL_ENDL;
gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard);

View File

@ -1082,7 +1082,6 @@ void display_cube_face()
gPipeline.mBackfaceCull = TRUE;
LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
gViewerWindow->setup3DViewport();
if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))

View File

@ -6028,6 +6028,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
{
new_block = new LLRenderMaterialParams();
break;
}
case LLNetworkData::PARAMS_REFLECTION_PROBE:
{
new_block = new LLReflectionProbeParams();
break;
}
default:
{

View File

@ -5270,7 +5270,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
void display_cube_face();
BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face)
BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip)
{
// NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
@ -5299,6 +5299,7 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
camera->setView(F_PI_BY_TWO);
camera->yaw(0.0);
camera->setOrigin(origin);
camera->setNear(near_clip);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

View File

@ -368,7 +368,9 @@ public:
// origin - vantage point to take the snapshot from
// cubearray - cubemap array for storing the results
// index - cube index in the array to use (cube index, not face-layer)
BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face);
// face - which cube face to update
// near_clip - near clip setting to use
BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip);
// special implementation of simpleSnapshot for reflection maps

View File

@ -985,7 +985,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
// Add it to the pipeline mLightSet
gPipeline.setLight(mDrawable, TRUE);
}
if (getIsReflectionProbe())
{
updateReflectionProbePtr();
}
updateRadius();
bool force_update = true; // avoid non-alpha mDistance update being optimized away
mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
@ -3496,6 +3501,121 @@ F32 LLVOVolume::getLightCutoff() const
}
}
void LLVOVolume::setIsReflectionProbe(BOOL is_probe)
{
BOOL was_probe = getIsReflectionProbe();
if (is_probe != was_probe)
{
if (is_probe)
{
setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, TRUE, true);
}
else
{
setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, FALSE, true);
}
}
updateReflectionProbePtr();
}
void LLVOVolume::setReflectionProbeAmbiance(F32 ambiance)
{
LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
if (param_block)
{
if (param_block->getAmbiance() != ambiance)
{
param_block->setAmbiance(ambiance);
parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
}
}
}
void LLVOVolume::setReflectionProbeNearClip(F32 near_clip)
{
LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
if (param_block)
{
if (param_block->getClipDistance() != near_clip)
{
param_block->setClipDistance(near_clip);
parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
}
}
}
void LLVOVolume::setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type)
{
LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
if (param_block)
{
if (param_block->getVolumeType() != volume_type)
{
param_block->setVolumeType(volume_type);
parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
}
}
}
BOOL LLVOVolume::getIsReflectionProbe() const
{
// HACK - make this object a Reflection Probe if a certain UUID is detected
static LLCachedControl<std::string> reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", "");
LLUUID probe_id(reflection_probe_id);
for (U8 i = 0; i < getNumTEs(); ++i)
{
if (getTE(i)->getID() == probe_id)
{
return true;
}
}
// END HACK
return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
}
F32 LLVOVolume::getReflectionProbeAmbiance() const
{
const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
if (param_block)
{
return param_block->getAmbiance();
}
else
{
return 0.f;
}
}
F32 LLVOVolume::getReflectionProbeNearClip() const
{
const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
if (param_block)
{
return param_block->getClipDistance();
}
else
{
return 0.f;
}
}
LLReflectionProbeParams::EInfluenceVolumeType LLVOVolume::getReflectionProbeVolumeType() const
{
const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
if (param_block)
{
return param_block->getVolumeType();
}
else
{
return LLReflectionProbeParams::DEFAULT_VOLUME_TYPE;
}
}
U32 LLVOVolume::getVolumeInterfaceID() const
{
if (mVolumeImpl)
@ -4381,6 +4501,23 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
gPipeline.setLight(mDrawable, is_light);
}
}
updateReflectionProbePtr();
}
void LLVOVolume::updateReflectionProbePtr()
{
if (getIsReflectionProbe())
{
if (mReflectionProbe.isNull())
{
mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this);
}
}
else if (mReflectionProbe.notNull())
{
mReflectionProbe = nullptr;
}
}
void LLVOVolume::setSelected(BOOL sel)
@ -5690,24 +5827,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
bool is_pbr = false;
#endif
// HACK - make this object a Reflection Probe if a certain UUID is detected
static LLCachedControl<std::string> reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", "");
if (facep->getTextureEntry()->getID() == LLUUID(reflection_probe_id))
{
if (!vobj->mIsReflectionProbe)
{
vobj->mIsReflectionProbe = true;
vobj->mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(vobj);
}
}
else
{
// not a refleciton probe any more
vobj->mIsReflectionProbe = false;
vobj->mReflectionProbe = nullptr;
}
// END HACK
//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
// batch, it will recover its vertex buffer reference from the spatial group
facep->setVertexBuffer(NULL);

View File

@ -178,6 +178,9 @@ public:
/*virtual*/ void parameterChanged(U16 param_type, bool local_origin);
/*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin);
// update mReflectionProbe based on isReflectionProbe()
void updateReflectionProbePtr();
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num, const EObjectUpdateType update_type,
@ -281,6 +284,17 @@ public:
F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
F32 getLightCutoff() const;
// Reflection Probes
void setIsReflectionProbe(BOOL is_probe);
void setReflectionProbeAmbiance(F32 ambiance);
void setReflectionProbeNearClip(F32 near_clip);
void setReflectionProbeVolumeType(LLReflectionProbeParams::EInfluenceVolumeType volume_type);
BOOL getIsReflectionProbe() const;
F32 getReflectionProbeAmbiance() const;
F32 getReflectionProbeNearClip() const;
LLReflectionProbeParams::EInfluenceVolumeType getReflectionProbeVolumeType() const;
// Flexible Objects
U32 getVolumeInterfaceID() const;
virtual BOOL isFlexible() const;

View File

@ -2353,7 +2353,7 @@ even though the user gets a free copy.
layout="topleft"
left="10"
name="Light Intensity"
top_pad="3"
top_delta="32"
width="128" />
<spinner bottom_delta="0"
decimal_digits="3"
@ -2420,7 +2420,61 @@ even though the user gets a free copy.
mouse_opaque="true"
name="Light Ambiance"
width="120" />
<text
<check_box
height="16"
label="Reflection Probe"
layout="topleft"
left="10"
name="Reflection Probe Checkbox Ctrl"
tool_tip="Adjusts how objects within this volume receive reflections when PBR is enabled"
top_pad="15"
width="60" />
<combo_box
height="19"
top_delta="0"
left="144"
follows="left|top"
name="Probe Volume Type Ctrl"
tool_tip="Choose the probe influence volume"
width="108">
<combo_box.item
label="Sphere"
name="Sphere"
value="Sphere" />
<combo_box.item
label="Box"
name="Box"
value="Box"/>
</combo_box>
<spinner bottom_delta="19"
decimal_digits="3"
follows="left|top"
height="16"
increment="0.05"
initial_value="0"
label="Ambiance"
label_width="55"
left="10"
max_val="1"
min_val="0"
mouse_opaque="true"
name="Probe Ambiance"
width="120" />
<spinner bottom_delta="0"
decimal_digits="3"
follows="left|top"
height="16"
increment="0.05"
initial_value="0"
label="Near Clip"
label_width="55"
left="144"
max_val="1024"
min_val="0"
mouse_opaque="true"
name="Probe Near Clip"
width="120" />
<text
type="string"
length="1"
follows="left|top"