summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@geenzo.com>2023-10-16 08:45:48 -0700
committerJonathan "Geenz" Goodman <geenz@geenzo.com>2023-10-16 08:45:48 -0700
commite841c73a9972fc184487c061e8a80add3a18aff1 (patch)
tree2af618b6c72cc19f3b5a08f4901087b8229aa04a /indra
parente612d70fad8c6ec9335c109223211d516ebdf6f4 (diff)
Tons of masking changes and tweaks.
We now support masking mirrors in the GBuffer. We also now support the concept of one arbitrary clip plane. DRTVWR-583
Diffstat (limited to 'indra')
-rw-r--r--indra/llrender/llshadermgr.cpp4
-rw-r--r--indra/llrender/llshadermgr.h3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/materialF.glsl30
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl6
-rw-r--r--indra/newview/lldrawpoolmaterials.cpp13
-rw-r--r--indra/newview/llfetchedgltfmaterial.cpp1
-rw-r--r--indra/newview/llheroprobemanager.cpp33
-rw-r--r--indra/newview/llheroprobemanager.h11
-rw-r--r--indra/newview/llreflectionmap.cpp4
-rw-r--r--indra/newview/llreflectionmap.h2
-rw-r--r--indra/newview/llviewerdisplay.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp15
-rw-r--r--indra/newview/llviewerwindow.h3
15 files changed, 140 insertions, 31 deletions
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 645a78bfac..8ae23989c9 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -651,6 +651,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_MIRROR 1.0\n"); // bit 2
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
if (defines)
@@ -1256,6 +1257,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("emissiveColor");
mReservedUniforms.push_back("metallicFactor");
mReservedUniforms.push_back("roughnessFactor");
+ mReservedUniforms.push_back("mirror_flag");
+ mReservedUniforms.push_back("clipPlane");
+ mReservedUniforms.push_back("clipSign");
mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index a326a5593d..5824c03e2a 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -85,6 +85,9 @@ public:
EMISSIVE_COLOR, // "emissiveColor"
METALLIC_FACTOR, // "metallicFactor"
ROUGHNESS_FACTOR, // "roughnessFactor"
+ MIRROR_FLAG, // "mirror_flag"
+ CLIP_PLANE, // "clipPlane"
+ CLIP_SIGN, // "clipSign"
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
index 7cdddfe8db..65706e2c3f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
@@ -28,25 +28,18 @@
#define DIFFUSE_ALPHA_MODE_MASK 2
#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-#ifdef HAS_SKIN
uniform mat4 modelview_matrix;
uniform mat4 projection_matrix;
+uniform mat4 modelview_projection_matrix;
+
+#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
#else
uniform mat3 normal_matrix;
-uniform mat4 modelview_projection_matrix;
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#if !defined(HAS_SKIN)
-uniform mat4 modelview_matrix;
#endif
out vec3 vary_position;
-#endif
-
uniform mat4 texture_matrix0;
in vec3 position;
@@ -133,10 +126,8 @@ void main()
vertex_color = diffuse_color;
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
#if !defined(HAS_SKIN)
- vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
-#endif
+ vary_position = (projection_matrix*vec4(position.xyz, 1.0)).xyz;
#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
index faa273b834..9b98a37925 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -58,10 +58,37 @@ vec2 encode_normal(vec3 n);
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
+uniform vec4 clipPlane;
+uniform float clipSign;
+uniform float mirror_flag;
+void applyClip(vec3 pos)
+{
+ if (mirror_flag > 0)
+ {
+ // TODO: make this less branchy
+ if (clipSign > 0)
+ {
+ if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0)
+ {
+ discard;
+ }
+ }
+ else
+ {
+ if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0)
+ {
+ discard;
+ }
+ }
+ }
+}
+
uniform mat3 normal_matrix;
void main()
{
+ applyClip(vary_position);
+
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
if (basecolor.a < minimum_alpha)
{
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
index 319f2f25b7..af49e76984 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -51,6 +51,23 @@ vec3 linear_to_srgb(vec3 cs);
vec3 legacy_adjust(vec3 c);
vec3 legacy_adjust_fullbright(vec3 c);
+uniform vec4 clipPlane;
+uniform float clipSign;
+uniform float mirror_flag;
+void applyClip(vec3 pos)
+{
+ float funnyClip = 0;
+ if (mirror_flag > 0)
+ {
+ if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0)
+ {
+ discard;
+ }
+ }
+}
+
+in vec3 vary_position;
+
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
out vec4 frag_color;
@@ -72,12 +89,12 @@ uniform vec4 morphFactor;
uniform vec3 camPosLocal;
uniform mat3 env_mat;
+uniform float is_mirror;
+
uniform vec3 sun_dir;
uniform vec3 moon_dir;
in vec2 vary_fragcoord;
-in vec3 vary_position;
-
uniform mat4 proj_mat;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -291,6 +308,7 @@ float getShadow(vec3 pos, vec3 norm)
void main()
{
+ applyClip(vary_position);
waterClip();
// diffcol == diffuse map combined with vertex color
@@ -419,9 +437,15 @@ void main()
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
+
+ float flag = GBUFFER_FLAG_HAS_ATMOS;
+
+ if (mirror_flag > 0)
+ flag = 1;
+
frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials
frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent.
- frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
+ frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
frag_data[3] = vec4(0);
#endif
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 20a5ad66b6..d42388ae78 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -191,7 +191,7 @@ void main()
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
- if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR) || GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR))
{
vec3 orm = texture(specularRect, tc).rgb;
float perceptualRoughness = orm.g;
@@ -214,7 +214,9 @@ void main()
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
- color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor;
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR))
+ color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor;
if (do_atmospherics)
{
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index 6a7e05ac74..373103ce0a 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -190,6 +190,19 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
glUniform4fv(specular, 1, lastSpecular.mV);
}
+ if (gPipeline.mHeroProbeManager.isMirrorPass())
+ {
+ glUniform1f(LLShaderMgr::MIRROR_FLAG, 1);
+ }
+
+ LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.currentMirrorClip()[0],
+ gPipeline.mHeroProbeManager.currentMirrorClip()[1],
+ gPipeline.mHeroProbeManager.currentMirrorClip()[2],
+ gPipeline.mHeroProbeManager.currentMirrorClip()[3]);
+
+ mShader->uniform4fv(LLShaderMgr::CLIP_PLANE,
+ 1, clipPlane.mV);
+
LLVOAvatar* lastAvatar = nullptr;
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp
index 1fb3577dd7..9590066b55 100644
--- a/indra/newview/llfetchedgltfmaterial.cpp
+++ b/indra/newview/llfetchedgltfmaterial.cpp
@@ -128,6 +128,7 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex)
shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor);
shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor);
shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV);
+ shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0);
F32 normal_packed[8];
mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp
index 91d5f9b800..b6db123cd9 100644
--- a/indra/newview/llheroprobemanager.cpp
+++ b/indra/newview/llheroprobemanager.cpp
@@ -141,13 +141,13 @@ void LLHeroProbeManager::update()
U8 mode = mNearestHero->mirrorPlacementMode();
mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode);
- LLFace *face = mNearestHero->mDrawable->getFace(mode);
- LLVector3 hero_pos = face->getPositionAgent();
+ mCurrentFace = mNearestHero->mDrawable->getFace(mode);
+ LLVector3 hero_pos = mCurrentFace->getPositionAgent();
// Calculate the average normal.
- LLVector4a *posp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mPositions;
- U16 *indp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mIndices;
+ LLVector4a *posp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mPositions;
+ U16 *indp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mIndices;
// get first three vertices (first triangle)
LLVector4a v0 = posp[indp[0]];
LLVector4a v1 = posp[indp[1]];
@@ -158,14 +158,27 @@ void LLHeroProbeManager::update()
LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]);
face_normal.normalize();
- face_normal *= face->getXform()->getWorldRotation();
+ face_normal *= mCurrentFace->getXform()->getWorldRotation();
LLVector3 offset = camera_pos - hero_pos;
LLVector3 project = face_normal * (offset * face_normal);
LLVector3 reject = offset - project;
LLVector3 point = (reject - project) + hero_pos;
- near_clip = abs(dist_vec(hero_pos, point)) - gSavedSettings.getF32("RenderHeroProbeNearClipOffset");
+ glh::matrix4f mat = copy_matrix(gGLModelView);
+ glh::vec4f tc(face_normal.mV);
+ mat.mult_matrix_vec(tc);
+
+ LLVector3 mirror_normal;
+ mirror_normal.set(tc.v);
+
+ LLVector3 hero_pos_render;
+ tc = glh::vec4f(hero_pos.mV);
+
+ mat.mult_matrix_vec(tc);
+ hero_pos_render.set(tc.v);
+
+ mCurrentClipPlane.setVec(hero_pos_render, mirror_normal);
probe_pos.load3(point.mV);
}
@@ -189,7 +202,7 @@ void LLHeroProbeManager::update()
bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass();
gPipeline.mReflectionMapManager.mRadiancePass = true;
-
+ mRenderingMirror = true;
for (U32 j = 0; j < mProbes.size(); j++)
{
for (U32 i = 0; i < 6; ++i)
@@ -197,6 +210,7 @@ void LLHeroProbeManager::update()
updateProbeFace(mProbes[j], i, near_clip);
}
}
+ mRenderingMirror = false;
gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass;
}
@@ -563,3 +577,8 @@ void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep)
mHeroVOList.erase(drawablep);
}
}
+
+bool LLHeroProbeManager::isViableMirror(LLFace* face) const
+{
+ return face == mCurrentFace;
+}
diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h
index 4a243e6cf2..68cfdbfd99 100644
--- a/indra/newview/llheroprobemanager.h
+++ b/indra/newview/llheroprobemanager.h
@@ -70,6 +70,12 @@ public:
void registerHeroDrawable(LLVOVolume* drawablep);
void unregisterHeroDrawable(LLVOVolume* drawablep);
+
+ bool isViableMirror(LLFace* face) const;
+
+ bool isMirrorPass() const { return mRenderingMirror; }
+
+ LLPlane currentMirrorClip() const { return mCurrentClipPlane; }
private:
friend class LLPipeline;
@@ -94,6 +100,8 @@ private:
// vertex buffer for pushing verts to filter shaders
LLPointer<LLVertexBuffer> mVertexBuffer;
+ LLPlane mCurrentClipPlane;
+
// update the specified face of the specified probe
void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip);
@@ -124,8 +132,11 @@ private:
// if true, reset all probe render state on the next update (for teleports and sky changes)
bool mReset = false;
+
+ bool mRenderingMirror = false;
std::set<LLVOVolume*> mHeroVOList;
LLVOVolume* mNearestHero;
+ LLFace* mCurrentFace;
};
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
index 06624e8fea..5fc9851709 100644
--- a/indra/newview/llreflectionmap.cpp
+++ b/indra/newview/llreflectionmap.cpp
@@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap()
}
}
-void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip)
+void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
mLastUpdateTime = gFrameTimeSeconds;
@@ -66,7 +66,7 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 n
F32 clip = (near_clip > 0) ? near_clip : getNearClip();
- gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic);
+ gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane);
}
void LLReflectionMap::autoAdjustOrigin()
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index e97b28c855..9e888f20d0 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -52,7 +52,7 @@ public:
// update this environment map
// resolution - size of cube map to generate
- void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f);
+ void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f, bool useClipPlane = false, LLPlane clipPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1)));
// for volume partition probes, try to place this probe in the best spot
void autoAdjustOrigin();
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 04ca62e0ec..a1e7d69ae4 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1063,7 +1063,7 @@ void display_cube_face()
LLSpatialGroup::sNoDelete = TRUE;
S32 occlusion = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
+ LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
//gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data
static LLCullResult result;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ba2b6e1c7c..e0ec8eec25 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -5304,7 +5304,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, F32 near_clip, bool dynamic_render)
+BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render, bool useCustomClipPlane, LLPlane clipPlane)
{
// NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
@@ -5335,6 +5335,14 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
camera->setOrigin(origin);
camera->setNear(near_clip);
+ LLPlane previousClipPlane;
+
+ if (useCustomClipPlane)
+ {
+ previousClipPlane = camera->getUserClipPlane();
+ camera->setUserClipPlane(clipPlane);
+ }
+
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT);
U32 dynamic_render_types[] = {
@@ -5441,6 +5449,11 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
gPipeline.resetDrawOrders();
mWorldViewRectRaw = window_rect;
+
+ if (useCustomClipPlane)
+ {
+ camera->setUserClipPlane(previousClipPlane);
+ }
// restore original view/camera/avatar settings settings
*camera = saved_camera;
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 6e8a5b2f4e..4da6a1360f 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -374,7 +374,8 @@ public:
// index - cube index in the array to use (cube index, not face-layer)
// 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, bool render_avatars);
+ BOOL cubeSnapshot(const LLVector3 &origin, LLCubeMapArray *cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars,
+ bool customCullingPlane = false, LLPlane cullingPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1)));
// special implementation of simpleSnapshot for reflection maps