summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/integration_tests/llui_libtest/CMakeLists.txt3
-rw-r--r--indra/llmath/llcamera.cpp28
-rw-r--r--indra/llmath/llcamera.h16
-rw-r--r--indra/llmath/llrect.h1
-rw-r--r--indra/llmath/llvolume.cpp11
-rw-r--r--indra/llprimitive/llprimitive.cpp77
-rw-r--r--indra/llprimitive/llprimitive.h25
-rw-r--r--indra/llrender/llgl.cpp27
-rw-r--r--indra/llrender/llgl.h32
-rw-r--r--indra/llrender/llimagegl.cpp214
-rw-r--r--indra/llrender/llimagegl.h44
-rw-r--r--indra/llrender/llrender.cpp10
-rw-r--r--indra/llrender/llrender.h1
-rw-r--r--indra/llrender/llrendertarget.cpp59
-rw-r--r--indra/llrender/llrendertarget.h4
-rw-r--r--indra/llui/llfloater.cpp22
-rw-r--r--indra/llui/llmenugl.cpp8
-rw-r--r--indra/llui/lltabcontainer.cpp9
-rw-r--r--indra/llui/llui.cpp17
-rw-r--r--indra/llui/llui.h4
-rw-r--r--indra/llui/llview.cpp27
-rw-r--r--indra/llui/llview.h1
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/settings.xml670
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl42
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl28
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/giF.glsl165
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/giV.glsl22
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl64
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl178
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl66
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl79
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl69
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl177
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl111
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterF.glsl72
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl132
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl76
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl98
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl84
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl96
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl58
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl188
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl59
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl294
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl24
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl199
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl235
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl84
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giF.glsl190
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giV.glsl22
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl80
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl69
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl297
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl24
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/treeF.glsl18
-rw-r--r--indra/newview/gpu_table.txt5
-rw-r--r--indra/newview/llappviewer.cpp61
-rw-r--r--indra/newview/llappviewerwin32.cpp2
-rw-r--r--indra/newview/lldebugview.cpp12
-rw-r--r--indra/newview/lldrawable.cpp58
-rw-r--r--indra/newview/lldrawable.h5
-rw-r--r--indra/newview/lldrawpool.cpp9
-rw-r--r--indra/newview/lldrawpool.h7
-rw-r--r--indra/newview/lldrawpoolalpha.cpp60
-rw-r--r--indra/newview/lldrawpoolavatar.cpp8
-rw-r--r--indra/newview/lldrawpoolbump.cpp14
-rw-r--r--indra/newview/lldrawpoolsimple.cpp13
-rw-r--r--indra/newview/lldrawpoolterrain.cpp6
-rw-r--r--indra/newview/lldrawpooltree.cpp14
-rw-r--r--indra/newview/lldrawpoolwater.cpp52
-rw-r--r--indra/newview/lldrawpoolwater.h4
-rw-r--r--indra/newview/llface.cpp287
-rw-r--r--indra/newview/llface.h23
-rw-r--r--indra/newview/llfloaterpostcard.cpp4
-rw-r--r--indra/newview/llfloatersettingsdebug.cpp5
-rw-r--r--indra/newview/llfloaterwindlight.cpp7
-rw-r--r--indra/newview/llhudtext.cpp2
-rw-r--r--indra/newview/llmanip.cpp1
-rw-r--r--indra/newview/llpanelvolume.cpp125
-rw-r--r--indra/newview/llpanelvolume.h5
-rw-r--r--indra/newview/llspatialpartition.cpp730
-rw-r--r--indra/newview/llspatialpartition.h112
-rw-r--r--indra/newview/llstartup.cpp4
-rw-r--r--indra/newview/llsurface.cpp32
-rw-r--r--indra/newview/llsurfacepatch.cpp34
-rw-r--r--indra/newview/llsurfacepatch.h1
-rw-r--r--indra/newview/lltexlayer.h2
-rw-r--r--indra/newview/lltexlayerparams.cpp2
-rw-r--r--indra/newview/lltextureatlas.cpp422
-rw-r--r--indra/newview/lltextureatlas.h95
-rw-r--r--indra/newview/lltextureatlasmanager.cpp273
-rw-r--r--indra/newview/lltextureatlasmanager.h111
-rw-r--r--indra/newview/lltextureview.cpp229
-rw-r--r--indra/newview/lltextureview.h20
-rw-r--r--indra/newview/lltoolpie.h4
-rw-r--r--indra/newview/llviewercamera.cpp2
-rw-r--r--indra/newview/llviewercamera.h18
-rw-r--r--indra/newview/llviewercontrol.cpp4
-rw-r--r--indra/newview/llviewerdisplay.cpp99
-rw-r--r--indra/newview/llviewerjointmesh.cpp3
-rw-r--r--indra/newview/llviewermenu.cpp71
-rw-r--r--indra/newview/llviewermessage.cpp3
-rw-r--r--indra/newview/llviewerobject.cpp21
-rw-r--r--indra/newview/llviewerobject.h9
-rw-r--r--indra/newview/llviewerparceloverlay.cpp20
-rw-r--r--indra/newview/llviewerparceloverlay.h4
-rw-r--r--indra/newview/llviewerpartsource.cpp2
-rw-r--r--indra/newview/llviewershadermgr.cpp149
-rw-r--r--indra/newview/llviewershadermgr.h30
-rw-r--r--indra/newview/llviewertexture.cpp237
-rw-r--r--indra/newview/llviewertexture.h13
-rw-r--r--indra/newview/llviewerwindow.cpp21
-rw-r--r--indra/newview/llvlcomposition.cpp4
-rw-r--r--indra/newview/llvoavatar.cpp72
-rw-r--r--indra/newview/llvoavatar.h5
-rw-r--r--indra/newview/llvoavatarself.cpp4
-rw-r--r--indra/newview/llvoclouds.cpp5
-rw-r--r--indra/newview/llvopartgroup.cpp12
-rw-r--r--indra/newview/llvosurfacepatch.cpp14
-rw-r--r--indra/newview/llvosurfacepatch.h1
-rw-r--r--indra/newview/llvotree.cpp7
-rw-r--r--indra/newview/llvovolume.cpp253
-rw-r--r--indra/newview/llvovolume.h13
-rw-r--r--indra/newview/llvowater.cpp3
-rw-r--r--indra/newview/llwaterparammanager.cpp7
-rw-r--r--indra/newview/llwlparammanager.cpp5
-rw-r--r--indra/newview/llworldmap.cpp1
-rw-r--r--indra/newview/llworldmapview.cpp6
-rw-r--r--indra/newview/pipeline.cpp3567
-rw-r--r--indra/newview/pipeline.h134
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml39
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml193
170 files changed, 11616 insertions, 1500 deletions
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index 84e3477ce6..452d37d3be 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -57,6 +57,8 @@ if (DARWIN)
find_library(COCOA_LIBRARY Cocoa)
set(OS_LIBRARIES ${COCOA_LIBRARY})
elseif (WINDOWS)
+ #ll_stack_trace needs this now...
+ list(APPEND WINDOWS_LIBRARIES dbghelp)
set(OS_LIBRARIES ${WINDOWS_LIBRARIES})
elseif (LINUX)
set(OS_LIBRARIES)
@@ -95,6 +97,7 @@ if (WINDOWS)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR}
)
+
endif (WINDOWS)
# Ensure people working on the viewer don't break this library
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 0f343bcefe..21ea4b2e7c 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -178,7 +178,7 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
U8 mask = 0;
S32 result = 2;
- if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
+ /*if (mFrustumCornerDist > 0.f && radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
{ //box is larger than frustum, check frustum quads against box planes
static const LLVector3 dir[] =
@@ -241,11 +241,15 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
result = 1;
}
}
- else
+ else*/
{
for (U32 i = 0; i < mPlaneCount; i++)
{
mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
@@ -294,6 +298,10 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& r
}
mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
@@ -437,6 +445,11 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)
int res = 2;
for (int i = 0; i < 6; i++)
{
+ if (mAgentPlanes[i].mask == 0xff)
+ {
+ continue;
+ }
+
float d = mAgentPlanes[i].p.dist(sphere_center);
if (d > radius)
@@ -622,6 +635,17 @@ U8 LLCamera::calcPlaneMask(const LLPlane& plane)
return mask;
}
+void LLCamera::ignoreAgentFrustumPlane(S32 idx)
+{
+ if (idx < 0 || idx > (S32) mPlaneCount)
+ {
+ return;
+ }
+
+ mAgentPlanes[idx].mask = 0xff;
+ mAgentPlanes[idx].p.clearVec();
+}
+
void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
{
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 23ee1157f9..0c81067919 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -93,6 +93,17 @@ public:
PLANE_TOP_MASK = (1<<PLANE_TOP),
PLANE_ALL_MASK = 0xf
};
+
+ enum
+ {
+ AGENT_PLANE_LEFT = 0,
+ AGENT_PLANE_RIGHT,
+ AGENT_PLANE_NEAR,
+ AGENT_PLANE_BOTTOM,
+ AGENT_PLANE_TOP,
+ AGENT_PLANE_FAR,
+ };
+
enum {
HORIZ_PLANE_LEFT = 0,
HORIZ_PLANE_RIGHT = 1,
@@ -132,7 +143,8 @@ private:
public:
LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
-
+ LLPlane getAgentPlane(U32 idx) { return mAgentPlanes[idx].p; }
+
public:
LLCamera();
LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
@@ -179,6 +191,8 @@ public:
// Return number of bytes copied.
size_t readFrustumFromBuffer(const char *buffer);
void calcAgentFrustumPlanes(LLVector3* frust);
+ void ignoreAgentFrustumPlane(S32 idx);
+
// Returns 1 if partly in, 2 if fully in.
// NOTE: 'center' is in absolute frame.
S32 sphereInFrustumOld(const LLVector3 &center, const F32 radius) const;
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index c03a331aff..2fa8cb3f16 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -42,6 +42,7 @@
template <class Type> class LLRectBase
{
public:
+ typedef Type tCoordType;
Type mLeft;
Type mTop;
Type mRight;
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index a0357a32cc..5cc0a596fd 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -84,6 +84,7 @@ const F32 SKEW_MIN = -0.95f;
const F32 SKEW_MAX = 0.95f;
const F32 SCULPT_MIN_AREA = 0.002f;
+const S32 SCULPT_MIN_AREA_DETAIL = 1;
BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)
{
@@ -2230,10 +2231,14 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
if (!data_is_empty)
{
sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type);
-
- if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+
+ // don't test lowest LOD to support legacy content DEV-33670
+ if (mDetail > SCULPT_MIN_AREA_DETAIL)
{
- data_is_empty = TRUE;
+ if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+ {
+ data_is_empty = TRUE;
+ }
}
}
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 33807e7545..b925d97b5c 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -1314,6 +1314,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 16);
case PARAMS_SCULPT:
return (size == 17);
+ case PARAMS_LIGHT_IMAGE:
+ return (size == 28);
}
return FALSE;
@@ -1646,3 +1648,78 @@ bool LLSculptParams::fromLLSD(LLSD& sd)
return false;
}
+//============================================================================
+
+LLLightImageParams::LLLightImageParams()
+{
+ mType = PARAMS_LIGHT_IMAGE;
+ mParams.setVec(F_PI*0.5f, 0.f, 0.f);
+}
+
+BOOL LLLightImageParams::pack(LLDataPacker &dp) const
+{
+ dp.packUUID(mLightTexture, "texture");
+ dp.packVector3(mParams, "params");
+
+ return TRUE;
+}
+
+BOOL LLLightImageParams::unpack(LLDataPacker &dp)
+{
+ dp.unpackUUID(mLightTexture, "texture");
+ dp.unpackVector3(mParams, "params");
+
+ return TRUE;
+}
+
+bool LLLightImageParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_LIGHT_IMAGE)
+ {
+ return false;
+ }
+
+ const LLLightImageParams *param = (const LLLightImageParams*)&data;
+ if ( (param->mLightTexture != mLightTexture) )
+ {
+ return false;
+ }
+
+ if ( (param->mParams != mParams ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void LLLightImageParams::copy(const LLNetworkData& data)
+{
+ const LLLightImageParams *param = (LLLightImageParams*)&data;
+ mLightTexture = param->mLightTexture;
+ mParams = param->mParams;
+}
+
+
+
+LLSD LLLightImageParams::asLLSD() const
+{
+ LLSD sd;
+
+ sd["texture"] = mLightTexture;
+ sd["params"] = mParams.getValue();
+
+ return sd;
+}
+
+bool LLLightImageParams::fromLLSD(LLSD& sd)
+{
+ if (sd.has("texture") && sd.has("params") && sd["params"].size() == 3)
+ {
+ setLightTexture( sd["texture"] );
+ setParams( LLVector3(sd["params"][0].asReal(), sd["params"][1].asReal(), sd["params"][2].asReal()) );
+ return true;
+ }
+
+ return false;
+}
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index b3a337ce5d..53095cc925 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -107,7 +107,8 @@ public:
{
PARAMS_FLEXIBLE = 0x10,
PARAMS_LIGHT = 0x20,
- PARAMS_SCULPT = 0x30
+ PARAMS_SCULPT = 0x30,
+ PARAMS_LIGHT_IMAGE = 0x40,
};
public:
@@ -267,6 +268,28 @@ public:
U8 getSculptType() { return mSculptType; }
};
+class LLLightImageParams : public LLNetworkData
+{
+protected:
+ LLUUID mLightTexture;
+ LLVector3 mParams;
+
+public:
+ LLLightImageParams();
+ /*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 asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setLightTexture(const LLUUID& id) { mLightTexture = id; }
+ LLUUID getLightTexture() const { return mLightTexture; }
+ void setParams(const LLVector3& params) { mParams = params; }
+ LLVector3 getParams() const { return mParams; }
+
+};
class LLPrimitive : public LLXform
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 7e1df0e565..e29688bf24 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -64,6 +64,8 @@ BOOL gDebugSession = FALSE;
BOOL gDebugGL = FALSE;
BOOL gClothRipple = FALSE;
BOOL gNoRender = FALSE;
+BOOL gGLActive = FALSE;
+
std::ofstream gFailLog;
@@ -107,6 +109,7 @@ LLMatrix4 gGLObliqueProjectionInverse;
#define LL_GL_NAME_POOLING 0
LLGLNamePool::pool_list_t LLGLNamePool::sInstances;
+std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
// ATI prototypes
@@ -1013,6 +1016,16 @@ void flush_glerror()
void assert_glerror()
{
+ if (!gGLActive)
+ {
+ //llwarns << "GL used while not active!" << llendl;
+
+ if (gDebugSession)
+ {
+ ll_fail("GL used while not active");
+ }
+ }
+
if (gNoRender || !gDebugGL)
{
return;
@@ -1258,8 +1271,10 @@ void LLGLState::checkTextureChannels(const std::string& msg)
};
GLint stackDepth = 0;
- LLMatrix4 identity;
- LLMatrix4 matrix;
+
+ glh::matrix4f mat;
+ glh::matrix4f identity;
+ identity.identity();
for (GLint i = 1; i < maxTextureUnits; i++)
{
@@ -1280,10 +1295,10 @@ void LLGLState::checkTextureChannels(const std::string& msg)
}
}
- glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix);
+ glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
stop_glerror();
- if (matrix != identity)
+ if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
@@ -1309,10 +1324,6 @@ void LLGLState::checkTextureChannels(const std::string& msg)
stop_glerror();
}
- glh::matrix4f mat;
- glh::matrix4f identity;
- identity.identity();
-
glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
stop_glerror();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 34dd982259..91421f3c95 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -37,6 +37,7 @@
#include <string>
#include <map>
+#include <list>
#include "llerror.h"
#include "v4color.h"
@@ -367,6 +368,35 @@ protected:
virtual void releaseName(GLuint name) = 0;
};
+/*
+ Interface for objects that need periodic GL updates applied to them.
+ Used to synchronize GL updates with GL thread.
+*/
+class LLGLUpdate
+{
+public:
+
+ static std::list<LLGLUpdate*> sGLQ;
+
+ BOOL mInQ;
+ LLGLUpdate()
+ : mInQ(FALSE)
+ {
+ }
+ virtual ~LLGLUpdate()
+ {
+ if (mInQ)
+ {
+ std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this);
+ if (iter != sGLQ.end())
+ {
+ sGLQ.erase(iter);
+ }
+ }
+ }
+ virtual void updateGL() = 0;
+};
+
extern LLMatrix4 gGLObliqueProjectionInverse;
#include "llglstates.h"
@@ -385,4 +415,6 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
extern BOOL gClothRipple;
extern BOOL gNoRender;
+extern BOOL gGLActive;
+
#endif // LL_LLGL_H
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 9d2cd4867a..dd64d753c7 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -44,7 +44,6 @@
#include "llgl.h"
#include "llrender.h"
-
//----------------------------------------------------------------------------
const F32 MIN_TEXTURE_LIFETIME = 10.f;
@@ -57,12 +56,25 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0;
S32 LLImageGL::sBoundTextureMemoryInBytes = 0;
S32 LLImageGL::sCurBoundTextureMemory = 0;
S32 LLImageGL::sCount = 0;
+std::list<U32> LLImageGL::sDeadTextureList;
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
F32 LLImageGL::sLastFrameTime = 0.f;
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
std::set<LLImageGL*> LLImageGL::sImageList;
+#if !LL_RELEASE_FOR_DOWNLOAD
+//-----------------------
+//debug use
+#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048
+std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+S32 LLImageGL::sCurTexSizeBar = -1 ;
+S32 LLImageGL::sCurTexPickSize = -1 ;
+LLPointer<LLImageGL> LLImageGL::sDefaultTexturep = NULL;
+//------------------------
+#endif
//**************************************************************************************
//below are functions for debug use
//do not delete them even though they are not currently being used.
@@ -198,6 +210,14 @@ void LLImageGL::updateStats(F32 current_time)
sLastFrameTime = current_time;
sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
sCurBoundTextureMemory = 0;
+
+#if !LL_RELEASE_FOR_DOWNLOAD
+ for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++)
+ {
+ sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ;
+ sTextureCurBoundCounter[i] = 0 ;
+ }
+#endif
}
//static
@@ -363,6 +383,10 @@ void LLImageGL::init(BOOL usemipmaps)
mGLTextureCreated = FALSE ;
mIsMask = FALSE;
mNeedsAlphaAndPickMask = TRUE ;
+
+ mDiscardLevelInAtlas = -1 ;
+ mTexelsInAtlas = 0 ;
+ mTexelsInGLTexture = 0 ;
}
void LLImageGL::cleanup()
@@ -523,7 +547,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
is_compressed = true;
}
- gGL.getTexUnit(0)->bind(this);
+ llverify(gGL.getTexUnit(0)->bind(this));
if (mUseMipMaps)
{
@@ -728,6 +752,92 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
llpushcallstacks ;
}
+BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
+{
+ if (gGLManager.mIsDisabled)
+ {
+ llwarns << "Trying to create a texture while GL is disabled!" << llendl;
+ return FALSE;
+ }
+ llassert(gGLManager.mInited);
+ stop_glerror();
+
+ if (discard_level < 0)
+ {
+ llassert(mCurrentDiscardLevel >= 0);
+ discard_level = mCurrentDiscardLevel;
+ }
+ discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
+
+ // Actual image width/height = raw image width/height * 2^discard_level
+ S32 w = raw_image->getWidth() << discard_level;
+ S32 h = raw_image->getHeight() << discard_level;
+
+ // setSize may call destroyGLTexture if the size does not match
+ setSize(w, h, raw_image->getComponents());
+
+ if( !mHasExplicitFormat )
+ {
+ switch (mComponents)
+ {
+ case 1:
+ // Use luminance alpha (for fonts)
+ mFormatInternal = GL_LUMINANCE8;
+ mFormatPrimary = GL_LUMINANCE;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 2:
+ // Use luminance alpha (for fonts)
+ mFormatInternal = GL_LUMINANCE8_ALPHA8;
+ mFormatPrimary = GL_LUMINANCE_ALPHA;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 3:
+ mFormatInternal = GL_RGB8;
+ mFormatPrimary = GL_RGB;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 4:
+ mFormatInternal = GL_RGBA8;
+ mFormatPrimary = GL_RGBA;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;
+ }
+ }
+
+ mCurrentDiscardLevel = discard_level;
+ mDiscardLevelInAtlas = discard_level;
+ mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
+ mLastBindTime = sLastFrameTime;
+ mGLTextureCreated = false ;
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth());
+ stop_glerror();
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
+
+ return TRUE ;
+}
+
+void LLImageGL::postAddToAtlas()
+{
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);
+ stop_glerror();
+}
+
BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
{
llpushcallstacks ;
@@ -832,7 +942,7 @@ BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S3
// Copy sub image from frame buffer
BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
- if (gGL.getTexUnit(0)->bind(this, true))
+ if (gGL.getTexUnit(0)->bind(this))
{
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
mGLTextureCreated = true;
@@ -854,13 +964,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
// static
void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
{
- glDeleteTextures(numTextures, (GLuint*)textures);
+ for (S32 i = 0; i < numTextures; i++)
+ {
+ sDeadTextureList.push_back(textures[i]);
+ }
}
// static
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels)
{
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels);
+ stop_glerror();
}
//create an empty GL texture: just create a texture name
@@ -895,12 +1009,12 @@ BOOL LLImageGL::createGLTexture()
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/)
{
- llpushcallstacks ;
if (gGLManager.mIsDisabled)
{
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
return FALSE;
}
+
mGLTextureCreated = false ;
llassert(gGLManager.mInited);
stop_glerror();
@@ -1023,12 +1137,21 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
if (old_name != 0)
{
sGlobalTextureMemoryInBytes -= mTextureMemory;
+#if !LL_RELEASE_FOR_DOWNLOAD
+ decTextureCounter(mTextureMemory / mComponents) ;
+#endif
+
LLImageGL::deleteTextures(1, &old_name);
stop_glerror();
}
mTextureMemory = getMipBytes(discard_level);
sGlobalTextureMemoryInBytes += mTextureMemory;
+ mTexelsInGLTexture = getWidth() * getHeight() ;
+
+#if !LL_RELEASE_FOR_DOWNLOAD
+ incTextureCounter(mTextureMemory / mComponents) ;
+#endif
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
@@ -1208,32 +1331,48 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
return TRUE ;
}
-void LLImageGL::destroyGLTexture()
+void LLImageGL::deleteDeadTextures()
{
- if (mTexName != 0)
+ while (!sDeadTextureList.empty())
{
- stop_glerror();
-
+ GLuint tex = sDeadTextureList.front();
+ sDeadTextureList.pop_front();
for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
{
- if (sCurrentBoundTextures[i] == mTexName)
+ if (sCurrentBoundTextures[i] == tex)
{
gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
stop_glerror();
}
}
- sGlobalTextureMemoryInBytes -= mTextureMemory;
- mTextureMemory = 0;
+ glDeleteTextures(1, &tex);
+ stop_glerror();
+ }
+}
+
+void LLImageGL::destroyGLTexture()
+{
+ if (mTexName != 0)
+ {
+ if(mTextureMemory)
+ {
+#if !LL_RELEASE_FOR_DOWNLOAD
+ decTextureCounter(mTextureMemory / mComponents) ;
+#endif
+ sGlobalTextureMemoryInBytes -= mTextureMemory;
+ mTextureMemory = 0;
+ }
LLImageGL::deleteTextures(1, &mTexName);
mTexName = 0;
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
mGLTextureCreated = FALSE ;
- stop_glerror();
}
}
+
+
//----------------------------------------------------------------------------
void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode)
@@ -1259,12 +1398,12 @@ void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
mFilterOption = option;
}
- if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
+ if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
{
gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option);
mTexOptionsDirty = false;
+ stop_glerror();
}
- stop_glerror();
}
BOOL LLImageGL::getIsResident(BOOL test_now)
@@ -1500,7 +1639,50 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
}
//----------------------------------------------------------------------------
-
+#if !LL_RELEASE_FOR_DOWNLOAD
+//for debug use
+//val is a "power of two" number
+S32 LLImageGL::getTextureCounterIndex(U32 val)
+{
+ //index range is [0, MAX_TEXTURE_LOG_SIZE].
+ if(val < 2)
+ {
+ return 0 ;
+ }
+ else if(val >= (1 << MAX_TEXTURE_LOG_SIZE))
+ {
+ return MAX_TEXTURE_LOG_SIZE ;
+ }
+ else
+ {
+ S32 ret = 0 ;
+ while(val >>= 1)
+ {
+ ++ret;
+ }
+ return ret ;
+ }
+}
+void LLImageGL::incTextureCounter(U32 val)
+{
+ sTextureLoadedCounter[getTextureCounterIndex(val)]++ ;
+}
+void LLImageGL::decTextureCounter(U32 val)
+{
+ sTextureLoadedCounter[getTextureCounterIndex(val)]-- ;
+}
+void LLImageGL::setCurTexSizebar(S32 index)
+{
+ sCurTexSizeBar = index ;
+ sCurTexPickSize = (1 << index) ;
+}
+void LLImageGL::resetCurTexSizebar()
+{
+ sCurTexSizeBar = -1 ;
+ sCurTexPickSize = -1 ;
+}
+//----------------------------------------------------------------------------
+#endif
// Manual Mip Generation
/*
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 987a1dc538..a094605607 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -42,7 +42,7 @@
#include "v2math.h"
#include "llrender.h"
-
+class LLTextureAtlas ;
#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20)
#define MEGA_BYTES_TO_BYTES(x) ((x) << 20)
@@ -52,6 +52,10 @@ class LLImageGL : public LLRefCount
{
friend class LLTexUnit;
public:
+ static std::list<U32> sDeadTextureList;
+
+ static void deleteDeadTextures();
+
// Size calculation
static S32 dataFormatBits(S32 dataformat);
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
@@ -69,7 +73,6 @@ public:
// Sometimes called externally for textures not using LLImageGL (should go away...)
static S32 updateBoundTexMem(const S32 delta);
-
static bool checkSize(S32 width, S32 height);
//for server side use only.
@@ -115,6 +118,7 @@ public:
void destroyGLTexture();
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
+ void setComponents(S8 ncomponents) { mComponents = ncomponents; }
S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
@@ -128,6 +132,7 @@ public:
S32 getMipBytes(S32 discard_level = -1) const;
BOOL getBoundRecently() const;
LLGLenum getPrimaryFormat() const { return mFormatPrimary; }
+ LLGLenum getFormatType() const { return mFormatType; }
BOOL getHasGLTexture() const { return mTexName != 0; }
LLGLuint getTexName() const { return mTexName; }
@@ -164,10 +169,20 @@ public:
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; }
+ LLGLenum getTexTarget()const { return mTarget ;}
+ S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;}
+ U32 getTexelsInAtlas()const { return mTexelsInAtlas ;}
+ U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;}
+
+
void init(BOOL usemipmaps);
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
void setNeedsAlphaAndPickMask(BOOL need_mask) {mNeedsAlphaAndPickMask = need_mask;}
+
+ BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
+ void postAddToAtlas() ;
+
public:
// Various GL/Rendering options
S32 mTextureMemory;
@@ -189,6 +204,10 @@ private:
U16 mHeight;
S8 mCurrentDiscardLevel;
+ S8 mDiscardLevelInAtlas;
+ U32 mTexelsInAtlas ;
+ U32 mTexelsInGLTexture;
+
protected:
LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
@@ -224,7 +243,26 @@ public:
static U32 sBindCount; // Tracks number of texture binds for current frame
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
static BOOL sGlobalUseAnisotropic;
- static LLImageGL* sDefaultGLTexture ;
+ static LLImageGL* sDefaultGLTexture ;
+ static BOOL sAutomatedTest;
+
+#if !LL_RELEASE_FOR_DOWNLOAD
+ //for debug use: show texture size distribution
+ //----------------------------------------
+ static LLPointer<LLImageGL> sDefaultTexturep; //default texture to replace normal textures
+ static std::vector<S32> sTextureLoadedCounter ;
+ static std::vector<S32> sTextureBoundCounter ;
+ static std::vector<S32> sTextureCurBoundCounter ;
+ static S32 sCurTexSizeBar ;
+ static S32 sCurTexPickSize ;
+
+ static S32 getTextureCounterIndex(U32 val) ;
+ static void incTextureCounter(U32 val) ;
+ static void decTextureCounter(U32 val) ;
+ static void setCurTexSizebar(S32 index) ;
+ static void resetCurTexSizebar();
+ //----------------------------------------
+#endif
#if DEBUG_MISS
BOOL mMissed; // Missed on last bind?
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index d577daf3f4..b74d824c9e 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -45,10 +45,11 @@ LLRender gGL;
// Handy copies of last good GL matrices
F64 gGLModelView[16];
F64 gGLLastModelView[16];
+F64 gGLLastProjection[16];
F64 gGLProjection[16];
S32 gGLViewport[4];
-static const U32 LL_NUM_TEXTURE_LAYERS = 8;
+static const U32 LL_NUM_TEXTURE_LAYERS = 16;
static GLenum sGLTextureType[] =
{
@@ -311,6 +312,11 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
if (bindDepth)
{
+ if (renderTarget->hasStencil())
+ {
+ llerrs << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << llendl;
+ }
+
bindManual(renderTarget->getUsage(), renderTarget->getDepth());
}
else
@@ -328,7 +334,7 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
{
return false;
}
-
+
if(mCurrTexture != texture)
{
gGL.flush();
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 74f87f6d40..cb2a4d4450 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -355,6 +355,7 @@ private:
extern F64 gGLModelView[16];
extern F64 gGLLastModelView[16];
+extern F64 gGLLastProjection[16];
extern F64 gGLProjection[16];
extern S32 gGLViewport[4];
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index dc052851ca..567e3a6c3e 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -204,7 +204,7 @@ void LLRenderTarget::allocateDepth()
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
+ LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32_ARB, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
}
@@ -382,7 +382,7 @@ void LLRenderTarget::flush(BOOL fetch_depth)
allocateDepth();
}
- gGL.getTexUnit(0)->bind(this, true);
+ gGL.getTexUnit(0)->bind(this);
glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
}
@@ -392,7 +392,11 @@ void LLRenderTarget::flush(BOOL fetch_depth)
{
#if !LL_DARWIN
+ stop_glerror();
+
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ stop_glerror();
if (mSampleBuffer)
{
@@ -434,7 +438,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
#endif
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glFlush();
}
}
@@ -442,6 +445,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
{
#if !LL_DARWIN
+ gGL.flush();
if (!source.mFBO || !mFBO)
{
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
@@ -453,12 +457,55 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
}
else
{
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO);
+ if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
+ {
+ stop_glerror();
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO);
+ gGL.getTexUnit(0)->bind(this, true);
+ stop_glerror();
+ glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
+ stop_glerror();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
+ }
+ else
+ {
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
+ stop_glerror();
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO);
+ stop_glerror();
+ check_framebuffer_status();
+ stop_glerror();
+ glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ stop_glerror();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
+ }
+ }
+#endif
+}
+//static
+void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
+ S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
+{
+#if !LL_DARWIN
+ if (!source.mFBO)
+ {
+ llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
+ }
+ {
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
+ stop_glerror();
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
+ check_framebuffer_status();
+ stop_glerror();
glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-
+ stop_glerror();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
}
#endif
}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 98b608f834..b7ebfc8f7f 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -121,6 +121,7 @@ public:
U32 getTexture(U32 attachment = 0) const;
U32 getDepth(void) const { return mDepth; }
+ BOOL hasStencil() const { return mStencil; }
void bindTexture(U32 index, S32 channel);
@@ -135,6 +136,9 @@ public:
void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
+ static void copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
+ S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
+
//Returns TRUE if target is ready to be rendered into.
//That is, if the target has been allocated with at least
//one renderable attachment (i.e. color buffer, depth buffer).
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 228e23b67e..81915731c3 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -602,6 +602,8 @@ void LLFloater::openFloater(const LLSD& key)
mOpenSignal(this, key);
onOpen(key);
+
+ dirtyRect();
}
void LLFloater::closeFloater(bool app_quitting)
@@ -667,7 +669,9 @@ void LLFloater::closeFloater(bool app_quitting)
}
}
}
-
+
+ dirtyRect();
+
// Close callback
mCloseSignal(this, LLSD(app_quitting));
@@ -1933,8 +1937,8 @@ void LLFloaterView::restoreAll()
LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor )
{
LLRect base_rect = reference_floater->getRect();
- S32 width = neighbor->getRect().getWidth();
- S32 height = neighbor->getRect().getHeight();
+ LLRect::tCoordType width = neighbor->getRect().getWidth();
+ LLRect::tCoordType height = neighbor->getRect().getHeight();
LLRect new_rect = neighbor->getRect();
LLRect expanded_base_rect = base_rect;
@@ -1953,10 +1957,10 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
}
}
- S32 left_margin = llmax(0, base_rect.mLeft);
- S32 right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
- S32 top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
- S32 bottom_margin = llmax(0, base_rect.mBottom);
+ LLRect::tCoordType left_margin = llmax(0, base_rect.mLeft);
+ LLRect::tCoordType right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
+ LLRect::tCoordType top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
+ LLRect::tCoordType bottom_margin = llmax(0, base_rect.mBottom);
// find position for floater in following order
// right->left->bottom->top
@@ -2262,8 +2266,8 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
// floater is hosted elsewhere, so ignore
return;
}
- S32 screen_width = getSnapRect().getWidth();
- S32 screen_height = getSnapRect().getHeight();
+ LLRect::tCoordType screen_width = getSnapRect().getWidth();
+ LLRect::tCoordType screen_height = getSnapRect().getHeight();
// convert to local coordinate frame
LLRect snap_rect_local = getLocalSnapRect();
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index e0bb6bd5d3..03374b856b 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -408,6 +408,12 @@ void LLMenuItemGL::onCommit( void )
{
getMenu()->clearHoverItem();
}
+
+ if (mHighlight != highlight)
+ {
+ dirtyRect();
+ }
+
mHighlight = highlight;
}
@@ -1233,6 +1239,8 @@ void LLMenuItemBranchGL::openMenu()
branch->translate( delta_x, delta_y );
branch->setVisible( TRUE );
branch->getParent()->sendChildToFront(branch);
+
+ dirtyRect();
}
}
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 720ca692f7..b6eed3ef18 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -329,10 +329,13 @@ void LLTabContainer::draw()
}
// Hide all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ if (getTabsHidden())
{
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( FALSE );
+ }
}
LLPanel::draw();
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 950eaf2ea7..000e85f78c 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -81,7 +81,8 @@ std::list<std::string> gUntranslated;
/*static*/ LLWindow* LLUI::sWindow = NULL;
/*static*/ LLHtmlHelp* LLUI::sHtmlHelp = NULL;
/*static*/ LLView* LLUI::sRootView = NULL;
-
+/*static*/ BOOL LLUI::sDirty = FALSE;
+/*static*/ LLRect LLUI::sDirtyRect;
/*static*/ std::vector<std::string> LLUI::sXUIPaths;
/*static*/ LLFrameTimer LLUI::sMouseIdleTimer;
@@ -1603,6 +1604,20 @@ void LLUI::cleanupClass()
sImageProvider->cleanUp();
}
+//static
+void LLUI::dirtyRect(LLRect rect)
+{
+ if (!sDirty)
+ {
+ sDirtyRect = rect;
+ sDirty = TRUE;
+ }
+ else
+ {
+ sDirtyRect.unionWith(rect);
+ }
+}
+
//static
void LLUI::translate(F32 x, F32 y, F32 z)
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 33338f30f9..fddf8192ad 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -174,6 +174,10 @@ public:
static void loadIdentity();
static void translate(F32 x, F32 y, F32 z = 0.0f);
+ static LLRect sDirtyRect;
+ static BOOL sDirty;
+ static void dirtyRect(LLRect rect);
+
// Return the ISO639 language name ("en", "ko", etc.) for the viewer UI.
// http://www.loc.gov/standards/iso639-2/php/code_list.php
static std::string getLanguage();
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 46510804f8..8d723877d6 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -143,6 +143,7 @@ LLView::LLView(const LLView::Params& p)
LLView::~LLView()
{
+ dirtyRect();
//llinfos << "Deleting view " << mName << ":" << (void*) this << llendl;
// llassert(LLView::sIsDrawing == FALSE);
@@ -602,6 +603,7 @@ void LLView::setVisible(BOOL visible)
if (!getParent() || getParent()->isInVisibleChain())
{
// tell all children of this view that the visibility may have changed
+ dirtyRect();
handleVisibilityChange( visible );
}
updateBoundingRect();
@@ -1297,7 +1299,7 @@ void LLView::drawChildren()
{
// Only draw views that are within the root view
localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect.overlaps(screenRect) )
+ if ( rootRect.overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
{
glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
@@ -1316,6 +1318,21 @@ void LLView::drawChildren()
gGL.getTexUnit(0)->disable();
}
+void LLView::dirtyRect()
+{
+ LLView* child = getParent();
+ LLView* parent = child ? child->getParent() : NULL;
+ LLView* cur = this;
+ while (child && parent && parent->getParent())
+ { //find third to top-most view
+ cur = child;
+ child = parent;
+ parent = parent->getParent();
+ }
+
+ LLUI::dirtyRect(cur->calcScreenRect());
+}
+
//Draw a box for debugging.
void LLView::drawDebugRect()
{
@@ -1529,6 +1546,8 @@ void LLView::updateBoundingRect()
{
if (isDead()) return;
+ LLRect cur_rect = mBoundingRect;
+
if (mUseBoundingRect)
{
mBoundingRect = calcBoundingRect();
@@ -1543,6 +1562,12 @@ void LLView::updateBoundingRect()
{
getParent()->updateBoundingRect();
}
+
+ if (mBoundingRect != cur_rect)
+ {
+ dirtyRect();
+ }
+
}
LLRect LLView::calcScreenRect() const
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 1f7e5afaae..bf3b5d0614 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -519,6 +519,7 @@ public:
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual void handleReshape(const LLRect& rect, bool by_user);
+ virtual void dirtyRect();
virtual void notifyParent(const LLSD& info);
virtual void notifyChildren(const LLSD& info);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 96aace9e2d..8a59b34332 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -372,6 +372,8 @@ set(viewer_SOURCE_FILES
lltexglobalcolor.cpp
lltexlayer.cpp
lltexlayerparams.cpp
+ lltextureatlas.cpp
+ lltextureatlasmanager.cpp
lltexturecache.cpp
lltexturectrl.cpp
lltexturefetch.cpp
@@ -830,6 +832,8 @@ set(viewer_HEADER_FILES
lltexglobalcolor.h
lltexlayer.h
lltexlayerparams.h
+ lltextureatlas.h
+ lltextureatlasmanager.h
lltexturecache.h
lltexturectrl.h
lltexturefetch.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index bbe69531b4..c794d7d319 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -2597,6 +2597,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>EnableTextureAtlas</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether to use texture atlas or not</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>EnableVoiceChat</key>
<map>
<key>Comment</key>
@@ -5513,42 +5524,56 @@
<key>Value</key>
<integer>1</integer>
</map>
-
- <key>RenderShadowGaussian</key>
+
+ <key>RenderShadowNearDist</key>
<map>
<key>Comment</key>
- <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string>
+ <string>Near clip plane of shadow camera (affects precision of depth shadows).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Vector3</string>
<key>Value</key>
<array>
- <real>2.0</real>
- <real>2.0</real>
- <real>0.0</real>
+ <real>256</real>
+ <real>256</real>
+ <real>256</real>
</array>
</map>
-
- <key>RenderShadowNearDist</key>
+ <key>RenderShadowClipPlanes</key>
<map>
<key>Comment</key>
- <string>Near clip plane of shadow camera (affects precision of depth shadows).</string>
+ <string>Near clip plane split distances for shadow map frusta.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Vector3</string>
<key>Value</key>
<array>
- <real>256</real>
- <real>256</real>
- <real>256</real>
+ <real>1.0</real>
+ <real>12.0</real>
+ <real>32.0</real>
</array>
</map>
- <key>RenderShadowClipPlanes</key>
+ <key>RenderShadowSplitExponent</key>
<map>
<key>Comment</key>
- <string>Near clip plane split distances for shadow map frusta.</string>
+ <string>Near clip plane split distances for shadow map frusta (x=perspective, y=ortho, z=transition rate).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>3.0</real>
+ <real>3.0</real>
+ <real>2.0</real>
+ </array>
+ </map>
+ <key>RenderShadowOrthoClipPlanes</key>
+ <map>
+ <key>Comment</key>
+ <string>Near clip plane split distances for orthographic shadow map frusta.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -5560,6 +5585,39 @@
<real>24.0</real>
</array>
</map>
+ <key>RenderShadowProjOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Amount to scale distance to virtual origin of shadow perspective projection.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>2.0</real>
+ </map>
+ <key>RenderShadowSlopeThreshold</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff slope value for points to affect perspective shadow generation</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
+ <key>RenderShadowProjExponent</key>
+ <map>
+ <key>Comment</key>
+ <string>Exponent applied to transition between ortho and perspective shadow projections based on viewing angle and light vector.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
<key>RenderSSAOScale</key>
<map>
<key>Comment</key>
@@ -5628,7 +5686,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>128</real>
+ <real>64</real>
</map>
<key>RenderCubeMap</key>
<map>
@@ -5707,7 +5765,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>RenderAnimateTrees</key>
<map>
<key>Comment</key>
@@ -5719,6 +5777,174 @@
<key>Value</key>
<integer>0</integer>
</map>
+
+ <key>RenderGIRange</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance to cut off GI effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>96</real>
+ </map>
+
+ <key>RenderGILuminance</key>
+ <map>
+ <key>Comment</key>
+ <string>Luminance factor of global illumination contribution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.075</real>
+ </map>
+
+ <key>RenderGIBrightness</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness factor of global illumination contribution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.3</real>
+ </map>
+
+ <key>RenderGINoise</key>
+ <map>
+ <key>Comment</key>
+ <string>Noise of position sampling for GI photon mapping.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.7</real>
+ </map>
+
+ <key>RenderGIAttenuation</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance attenuation factor for indirect lighting.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+
+ <key>RenderGIBlurBrightness</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness factor of global illumination blur effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.025</real>
+ </map>
+
+ <key>RenderGIBlurEdgeWeight</key>
+ <map>
+ <key>Comment</key>
+ <string>Edge weight for GI soften filter (sharpness).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.8</real>
+ </map>
+
+ <key>RenderGIBlurIncrement</key>
+ <map>
+ <key>Comment</key>
+ <string>Increment of scale for each pass of global illumination blur effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.8</real>
+ </map>
+
+ <key>RenderLuminanceScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Luminance value scalar for darkening effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+ <key>RenderSunLuminanceScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Sun Luminance value scalar for darkening effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+ <key>RenderSunLuminanceOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Sun Luminance value offset for darkening effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0</real>
+ </map>
+
+ <key>RenderLuminanceDetail</key>
+ <map>
+ <key>Comment</key>
+ <string>Mipmap level to use for luminance</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>16.0</real>
+ </map>
+
+ <key>RenderEdgeDepthCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff for depth difference that amounts to an edge.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.01</real>
+ </map>
+ <key>RenderEdgeNormCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff for normal difference that amounts to an edge.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.25</real>
+ </map>
+
<key>RenderDeferredAlphaSoften</key>
<map>
<key>Comment</key>
@@ -5741,6 +5967,178 @@
<key>Value</key>
<real>4</real>
</map>
+ <key>RenderDeferredSpotShadowBias</key>
+ <map>
+ <key>Comment</key>
+ <string>Bias value for spot shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>-64.0</real>
+ </map>
+ <key>RenderDeferredSpotShadowOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Offset value for spot shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.8</real>
+ </map>
+
+ <key>RenderShadowBias</key>
+ <map>
+ <key>Comment</key>
+ <string>Bias value for shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>-0.008</real>
+ </map>
+ <key>RenderShadowOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Offset value for shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.01</real>
+ </map>
+
+ <key>RenderShadowResolutionScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of shadow map resolution vs. screen resolution</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+
+
+ <key>RenderDeferredTreeShadowBias</key>
+ <map>
+ <key>Comment</key>
+ <string>Bias value for tree shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+ <key>RenderDeferredTreeShadowOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Offset value for tree shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+ <key>RenderHighlightFadeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Transition time for mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+
+ <key>RenderHighlightBrightness</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness of mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>4.0</real>
+ </map>
+
+ <key>RenderHighlightThickness</key>
+ <map>
+ <key>Comment</key>
+ <string>Thickness of mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.6</real>
+ </map>
+
+ <key>RenderHighlightColor</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness of mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Color4</string>
+ <key>Value</key>
+ <array>
+ <real>0.4</real>
+ <real>0.98</real>
+ <real>0.93</real>
+ <real>1.0</real>
+ </array>
+ </map>
+
+ <key>RenderSpecularResX</key>
+ <map>
+ <key>Comment</key>
+ <string>Spec map resolution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>128</real>
+ </map>
+
+ <key>RenderSpecularResY</key>
+ <map>
+ <key>Comment</key>
+ <string>Spec map resolution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>128</real>
+ </map>
+
+ <key>RenderSpecularExponent</key>
+ <map>
+ <key>Comment</key>
+ <string>Specular exponent for generating spec map</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1</real>
+ </map>
+
<key>RenderDeferred</key>
<map>
<key>Comment</key>
@@ -5752,6 +6150,31 @@
<key>Value</key>
<integer>0</integer>
</map>
+
+ <key>RenderDeferredShadow</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable shadows in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredGI</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable GI in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+
<key>RenderDeferredSunShadow</key>
<map>
<key>Comment</key>
@@ -5763,6 +6186,67 @@
<key>Value</key>
<integer>1</integer>
</map>
+
+ <key>RenderDeferredSun</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute sunlight shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredAtmospheric</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute atmospheric shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredBlurLight</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute shadow softening shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredLocalLights</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute local lighting shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredFullscreenLights</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute local lighting shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
<key>RenderDeferredSunWash</key>
<map>
<key>Comment</key>
@@ -5785,6 +6269,45 @@
<key>Value</key>
<real>-0.0001</real>
</map>
+ <key>RenderShadowErrorCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff error value to use ortho instead of perspective projection.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>5.0</real>
+ </map>
+ <key>RenderShadowFOVCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff FOV to use ortho instead of perspective projection.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.1</real>
+ </map>
+
+ <key>RenderShadowGaussian</key>
+ <map>
+ <key>Comment</key>
+ <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>3.0</real>
+ <real>2.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
+
<key>RenderShadowBlurSize</key>
<map>
<key>Comment</key>
@@ -5794,7 +6317,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>0.7</real>
+ <real>1.4</real>
</map>
<key>RenderShadowBlurSamples</key>
<map>
@@ -5805,8 +6328,106 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <real>5</real>
+ <real>4</real>
</map>
+ <key>RenderShadowBlurDistFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance scaler for shadow blur.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+
+ <key>RenderGIAmbiance</key>
+ <map>
+ <key>Comment</key>
+ <string>Ambiance factor of global illumination contribution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+
+ <key>RenderGIMinRenderSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Minimum size of objects to put into GI source map.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+
+ <key>RenderGIBlurColorCurve</key>
+ <map>
+ <key>Comment</key>
+ <string>Color curve for GI softening kernel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>1.0</real>
+ <real>0.6</real>
+ <real>0.02</real>
+ </array>
+ </map>
+
+ <key>RenderGIBlurPasses</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of GI softening kernel.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>4</real>
+ </map>
+
+ <key>RenderGIBlurSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of GI softening kernel.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>4.0</real>
+ </map>
+ <key>RenderGIBlurSamples</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of samples to take for each pass of GI blur (value range 1-16). Actual number of samples is value * 2 - 1.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>16</real>
+ </map>
+ <key>RenderGIBlurDistFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance scaler for GI blur.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
+
<key>RenderDynamicLOD</key>
<map>
<key>Comment</key>
@@ -6143,7 +6764,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>4096</integer>
+ <integer>8192</integer>
</map>
<key>RenderMaxVBOSize</key>
<map>
@@ -6354,6 +6975,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderUIBuffer</key>
+ <map>
+ <key>Comment</key>
+ <string>Cache ui render in a screen aligned buffer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderUnloadedAvatar</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index a91e9fa15b..4fb109d687 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -8,14 +8,10 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2D diffuseMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
uniform sampler2D noiseMap;
-uniform sampler2DRect positionMap;
+uniform sampler2DRect depthMap;
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
@@ -26,52 +22,42 @@ varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
+varying vec3 vary_light;
uniform float alpha_soften;
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
- vec3 samp_pos = texture2DRect(positionMap, frag).xyz;
+ vec3 samp_pos = getPosition(frag).xyz;
- float shadow = 1.0;
vec4 pos = vec4(vary_position, 1.0);
- if (pos.z > -shadow_clip.w)
- {
- if (pos.z < -shadow_clip.z)
- {
- vec4 lpos = shadow_matrix[3]*pos;
- shadow = shadow2DProj(shadowMap3, lpos).x;
- shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
- }
- else if (pos.z < -shadow_clip.y)
- {
- vec4 lpos = shadow_matrix[2]*pos;
- shadow = shadow2DProj(shadowMap2, lpos).x;
- }
- else if (pos.z < -shadow_clip.x)
- {
- vec4 lpos = shadow_matrix[1]*pos;
- shadow = shadow2DProj(shadowMap1, lpos).x;
- }
- else
- {
- vec4 lpos = shadow_matrix[0]*pos;
- shadow = shadow2DProj(shadowMap0, lpos).x;
- }
- }
-
- vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
+ vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
- if (samp_pos.z != 0.0)
+ if (samp_pos.z != 0.0 && gl_Color.a < 1.0)
{
float dist_factor = alpha_soften;
float a = gl_Color.a;
@@ -83,6 +69,7 @@ void main()
//gl_FragColor = gl_Color;
gl_FragColor = color;
//gl_FragColor = vec4(1,0,1,1);
+ //gl_FragColor = vec4(1,0,1,1)*shadow;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index b496bd674f..1a7d58b07b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -20,8 +20,11 @@ varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
+varying vec3 vary_light;
uniform float near_clip;
+uniform float shadow_offset;
+uniform float shadow_bias;
void main()
{
@@ -32,8 +35,9 @@ void main()
vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
- vary_position = pos.xyz;
+ vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias);
+
calcAtmospherics(pos.xyz);
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
@@ -54,6 +58,8 @@ void main()
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
col.rgb = scaleDownLight(col.rgb);
+ vary_light = gl_LightSource[0].position.xyz;
+
vary_ambient = col.rgb*gl_Color.rgb;
vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
index 6c94f5c5a7..ff64a6b0c3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
@@ -12,7 +12,7 @@ uniform sampler2DShadow shadowMap2;
uniform sampler2DShadow shadowMap3;
uniform sampler2D noiseMap;
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
vec3 atmosLighting(vec3 light);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 58aa5a9cb5..75df388941 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -8,13 +8,18 @@
uniform sampler2D diffuseMap;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
- gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 diff = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy);
+
+ if (diff.a < 0.2)
+ {
+ discard;
+ }
+
+ gl_FragData[0] = vec4(diff.rgb, 0.0);
gl_FragData[1] = vec4(0,0,0,0);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
index 27c09db922..00083eb6b3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
@@ -10,6 +10,7 @@ uniform sampler2D diffuseMap;
void main()
{
- gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy));
+ gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
+ //gl_FragColor = vec4(1,1,1,1);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
index 14da6b1ad4..8c8489d087 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
@@ -28,8 +28,7 @@ void main()
norm = normalize(norm);
pos = gl_ProjectionMatrix * pos;
- //smash geometry against near clip plane
- pos.z = max(pos.z, -1.0);
+ pos.z = max(pos.z, -pos.w+0.01);
gl_Position = pos;
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
index 12a7ff7f29..471a1f0407 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
@@ -10,7 +10,6 @@ mat4 getSkinnedTransform();
attribute vec4 weight;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
@@ -30,7 +29,6 @@ void main()
norm.z = dot(trans[2].xyz, gl_Normal);
norm = normalize(norm);
- vary_position = pos;
vary_normal = norm;
gl_Position = gl_ProjectionMatrix * pos;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 3c6700a871..bd5e9dd758 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -7,10 +7,12 @@
#extension GL_ARB_texture_rectangle : enable
-uniform sampler2DRect positionMap;
+uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
+uniform sampler2DRect giLightMap;
+uniform float dist_factor;
uniform float blur_size;
uniform vec2 delta;
uniform vec3 kern[32];
@@ -19,30 +21,52 @@ uniform float kern_scale;
varying vec2 vary_fragcoord;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
- vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
- vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz;
- vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ vec3 pos = getPosition(vary_fragcoord.xy).xyz;
+ vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+ dlt /= max(-pos.z*dist_factor, 1.0);
+
vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
- vec2 col = defined_weight * ccol;
+ vec4 col = defined_weight.xyxx * ccol;
for (int i = 1; i < kern_length; i++)
{
vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
- vec3 samppos = texture2DRect(positionMap, tc).xyz;
+ vec3 samppos = getPosition(tc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= 0.003)
{
- col += texture2DRect(lightMap, tc).rg*kern[i].xy;
+ col += texture2DRect(lightMap, tc)*kern[i].xyxx;
defined_weight += kern[i].xy;
}
}
- col /= defined_weight;
- gl_FragColor = vec4(col.r, col.g, 0.0, 1.0);
+
+ col /= defined_weight.xyxx;
+
+ gl_FragColor = col;
+
+ //gl_FragColor = ccol;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index a8712bc8cc..1c29dae5f7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -11,7 +11,6 @@ uniform sampler2D bumpMap;
varying vec3 vary_mat0;
varying vec3 vary_mat1;
varying vec3 vary_mat2;
-varying vec4 vary_position;
void main()
{
@@ -22,8 +21,7 @@ void main()
dot(norm,vary_mat1),
dot(norm,vary_mat2));
- gl_FragData[0].rgb = gl_Color.rgb*col;
- gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a);
- gl_FragData[2] = vec4(normalize(tnorm), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0);
+ gl_FragData[1] = vec4(col*gl_Color.a, gl_Color.a);
+ gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
index ba180922cc..9589912c6c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
@@ -8,7 +8,6 @@
varying vec3 vary_mat0;
varying vec3 vary_mat1;
varying vec3 vary_mat2;
-varying vec4 vary_position;
void main()
{
@@ -16,8 +15,6 @@ void main()
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz);
vec3 t = cross(b, n);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index f2ba2df69a..5895ebda84 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -8,13 +8,11 @@
uniform sampler2D diffuseMap;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb;
- gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0);
+ gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0);
gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 3413a7f9d6..44468cdfa2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -6,16 +6,13 @@
*/
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
//transform vertex
- gl_Position = ftransform();
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 2a811c5897..e518bddb98 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -8,14 +8,9 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2D diffuseMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
+uniform sampler2DRect depthMap;
uniform sampler2D noiseMap;
-uniform sampler2DRect positionMap;
-uniform mat4 shadow_matrix[4];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
@@ -30,12 +25,27 @@ varying vec3 vary_fragcoord;
uniform float alpha_soften;
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
- vec3 samp_pos = texture2DRect(positionMap, frag).xyz;
+ vec3 samp_pos = getPosition(frag).xyz;
float shadow = 1.0;
vec4 pos = vary_position;
@@ -46,10 +56,10 @@ void main()
color.rgb = fullbrightScaleSoftClip(color.rgb);
- if (samp_pos.z != 0.0)
+ if (samp_pos.z != 0.0 && color.a < 1.0)
{
float dist_factor = alpha_soften;
- float a = gl_Color.a;
+ float a = color.a;
a *= a;
dist_factor *= 1.0/(1.0-a);
color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index 6381a1ced8..aff51178b0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -12,12 +12,12 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
-varying vec4 vary_position;
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_normal;
varying vec3 vary_fragcoord;
uniform float near_clip;
+varying vec4 vary_position;
void main()
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
new file mode 100644
index 0000000000..b351eec6e5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
@@ -0,0 +1,165 @@
+/**
+ * @file giF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2D noiseMap;
+
+uniform sampler2D diffuseGIMap;
+uniform sampler2D normalGIMap;
+uniform sampler2D depthGIMap;
+
+uniform sampler2D lightFunc;
+
+// Inputs
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space
+uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space
+uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix
+uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space
+uniform float gi_radius;
+uniform float gi_intensity;
+uniform int gi_samples;
+uniform vec2 gi_kern[25];
+uniform vec2 gi_scale;
+uniform vec3 gi_quad;
+uniform vec3 gi_spec;
+uniform float gi_direction_weight;
+uniform float gi_light_offset;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec4 getGIPosition(vec2 gi_tc)
+{
+ float depth = texture2D(depthGIMap, gi_tc).a;
+ vec2 sc = gi_tc*2.0;
+ sc -= vec2(1.0, 1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = gi_inv_proj*ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 giAmbient(vec3 pos, vec3 norm)
+{
+ vec4 gi_c = gi_mat_proj * vec4(pos, 1.0);
+ gi_c.xyz /= gi_c.w;
+
+ vec4 gi_pos = gi_mat*vec4(pos,1.0);
+ vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz;
+ gi_norm = normalize(gi_norm);
+
+ vec2 tcx = gi_norm.xy;
+ vec2 tcy = gi_norm.yx;
+
+ vec4 eye_pos = gi_mat*vec4(0,0,0,1.0);
+
+ vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w);
+
+ //vec3 eye_dir = vec3(0,0,-1);
+ //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz;
+ //eye_dir = normalize(eye_dir);
+
+ //float round_x = gi_scale.x;
+ //float round_y = gi_scale.y;
+
+ vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5;
+ debug.xz = vec2(0.0,0.0);
+ //debug = fract(debug);
+
+ float round_x = 1.0/64.0;
+ float round_y = 1.0/64.0;
+
+ //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x;
+ //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y;
+
+ float fda = 0.0;
+ vec3 fdiff = vec3(0,0,0);
+
+ vec3 rcol = vec3(0,0,0);
+
+ float fsa = 0.0;
+
+ for (int i = -1; i < 2; i+=2 )
+ {
+ for (int j = -1; j < 2; j+=2)
+ {
+ vec2 tc = vec2(i, j)*0.75;
+ vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz;
+ //tc += gi_norm.xy*nz.z;
+ tc += nz.xy*2.0;
+ tc /= gi_samples;
+ tc += gi_c.xy;
+
+ vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0);
+ vec3 lpos = getGIPosition(tc.xy).xyz;
+
+ vec3 at = lpos-gi_pos.xyz;
+ float dist = dot(at,at);
+ float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0);
+
+ if (da > 0.0)
+ {
+ //add angular attenuation
+ vec3 ldir = at;
+ float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0);
+
+ float ld = -dot(ldir, lnorm);
+
+ if (ang_atten > 0.0 && ld < 0.0)
+ {
+ vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz;
+ da = da*ang_atten;
+ fda += da;
+ fdiff += diff*da;
+ }
+ }
+ }
+ }
+
+ fdiff /= max(gi_spec.y*fda, gi_quad.z);
+ fdiff = clamp(fdiff, vec3(0), vec3(1));
+
+ vec3 ret = fda*fdiff;
+ //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z;
+
+ //fda *= nz.z;
+
+ //rcol.rgb *= gi_intensity;
+ //return rcol.rgb+vary_AmblitColor.rgb*0.25;
+ //return vec4(debug, 0.0);
+ //return vec4(fda*fdiff, 0.0);
+ return clamp(ret,vec3(0.0), vec3(1.0));
+ //return debug.xyz;
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec4 pos = getPosition(pos_screen);
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+
+ gl_FragData[0].xyz = giAmbient(pos, norm);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
new file mode 100644
index 0000000000..71dcea9628
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
@@ -0,0 +1,22 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index 20a3f3df5b..8c140a7b4f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -9,12 +9,9 @@ uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform sampler2D specularMap;
-varying vec4 vary_position;
-
void main()
{
gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy);
- gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, vary_position.z);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
index 9c5ae31541..57532a30b3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
@@ -5,15 +5,11 @@
* $License$
*/
-varying vec4 vary_position;
-
void main()
{
//transform vertex
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
gl_FrontColor = gl_Color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
new file mode 100644
index 0000000000..e8b53b0293
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
@@ -0,0 +1,15 @@
+/**
+ * @file luminanceF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect diffuseMap;
+
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ gl_FragColor = texture2DRect(diffuseMap, vary_fragcoord.xy);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
new file mode 100644
index 0000000000..db8775f024
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
@@ -0,0 +1,20 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 3689d12840..797b9e9f3b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -7,13 +7,14 @@
#extension GL_ARB_texture_rectangle : enable
+uniform sampler2DRect depthMap;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
-uniform sampler2DRect positionMap;
uniform sampler2DRect normalMap;
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
uniform vec3 env_mat[3];
uniform float sun_wash;
@@ -23,24 +24,48 @@ uniform int light_count;
uniform vec4 light[16];
uniform vec4 light_col[16];
-varying vec3 vary_fragcoord;
+varying vec4 vary_fragcoord;
uniform vec2 screen_res;
+uniform float far_z;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
- vec3 pos = texture2DRect(positionMap, frag.xy).xyz;
- vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz);
+ vec3 pos = getPosition(frag.xy).xyz;
+ if (pos.z < far_z)
+ {
+ discard;
+ }
+
+ vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0);
vec4 spec = texture2DRect(specularRect, frag.xy);
vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
float noise = texture2D(noiseMap, frag.xy/128.0).b;
vec3 out_col = vec3(0,0,0);
+ vec3 npos = normalize(-pos);
for (int i = 0; i < light_count; ++i)
{
vec3 lv = light[i].xyz-pos;
float dist2 = dot(lv,lv);
- if (dist2 > light[i].w)
+ dist2 /= light[i].w;
+ if (dist2 > 1.0)
{
continue;
}
@@ -55,29 +80,38 @@ void main()
da = dot(norm, lv);
float fa = light_col[i].a+1.0;
- float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0);
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
dist_atten *= noise;
float lit = da * dist_atten;
vec3 col = light_col[i].rgb*lit*diff;
+ //vec3 col = vec3(dist2, light_col[i].a, lit);
if (spec.a > 0.0)
{
- vec3 ref = reflect(normalize(pos), norm);
- float sa = dot(ref,lv);
- sa = max(sa, 0.0);
- sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
- sa *= noise;
- col += da*sa*light_col[i].rgb*spec.rgb;
+ //vec3 ref = dot(pos+lv, norm);
+
+ float sa = dot(normalize(lv+npos),norm);
+
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*light_col[i].rgb*spec.rgb;
+ }
}
out_col += col;
}
- //attenuate point light contribution by SSAO component
- out_col *= texture2DRect(lightMap, frag.xy).g;
+ if (dot(out_col, out_col) <= 0.0)
+ {
+ discard;
+ }
gl_FragColor.rgb = out_col;
gl_FragColor.a = 0.0;
+
+ //gl_FragColor = vec4(0.1, 0.025, 0.025/4.0, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
new file mode 100644
index 0000000000..28bcd720c0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -0,0 +1,178 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex;
+ }
+
+ float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+ //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
+ float amb_da = proj_ambiance;
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.z+proj_near;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+ }
+ }
+ }
+ }
+
+ /*if (spec.a > 0.0)
+ {
+ //vec3 ref = reflect(normalize(pos), norm);
+ float sa = dot(normalize(lv-normalize(pos)),norm);;
+ //sa = max(sa, 0.0);
+ //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*lcol*spec.rgb;
+ }*/
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 52bad1f34c..78256e20cc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -9,33 +9,53 @@
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
-uniform sampler2DRect positionMap;
uniform sampler2DRect normalMap;
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2DRect depthMap;
uniform vec3 env_mat[3];
uniform float sun_wash;
varying vec4 vary_light;
-varying vec3 vary_fragcoord;
+varying vec4 vary_fragcoord;
uniform vec2 screen_res;
+uniform mat4 inv_proj;
+uniform vec4 viewport;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
+ sc /= viewport.zw;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
- vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
- frag *= screen_res;
- vec3 pos = texture2DRect(positionMap, frag).xyz;
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
vec3 lv = vary_light.xyz-pos;
float dist2 = dot(lv,lv);
- if (dist2 > vary_light.w)
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
{
discard;
}
- vec3 norm = texture2DRect(normalMap, frag).xyz;
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
float da = dot(norm, lv);
if (da < 0.0)
{
@@ -46,30 +66,32 @@ void main()
lv = normalize(lv);
da = dot(norm, lv);
- float noise = texture2D(noiseMap, frag/128.0).b;
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
- vec3 col = texture2DRect(diffuseRect, frag).rgb;
+ vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
float fa = gl_Color.a+1.0;
- float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0);
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
float lit = da * dist_atten * noise;
col = gl_Color.rgb*lit*col;
- vec4 spec = texture2DRect(specularRect, frag);
+ vec4 spec = texture2DRect(specularRect, frag.xy);
if (spec.a > 0.0)
{
- vec3 ref = reflect(normalize(pos), norm);
- float sa = dot(ref,lv);
- sa = max(sa, 0.0);
- sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
- sa *= noise;
- col += da*sa*gl_Color.rgb*spec.rgb;
+ float sa = dot(normalize(lv-normalize(pos)),norm);
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*gl_Color.rgb*spec.rgb;
+ }
}
- //attenuate point light contribution by SSAO component
- col *= texture2DRect(lightMap, frag.xy).g;
-
-
+ if (dot(col, col) <= 0.0)
+ {
+ discard;
+ }
+
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index a4edb88259..e815ca260f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -6,7 +6,7 @@
*/
varying vec4 vary_light;
-varying vec3 vary_fragcoord;
+varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform float near_clip;
@@ -14,10 +14,10 @@ uniform float near_clip;
void main()
{
//transform vertex
- gl_Position = ftransform();
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
+ vary_fragcoord = pos;
vec4 tex = gl_MultiTexCoord0;
tex.w = 1.0;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
new file mode 100644
index 0000000000..71de03663c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -0,0 +1,57 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect localLightMap;
+uniform sampler2DRect sunLightMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D luminanceMap;
+uniform sampler2DRect lightMap;
+
+uniform vec3 lum_quad;
+uniform float lum_lod;
+uniform vec4 ambient;
+
+uniform vec3 gi_quad;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb;
+ float luminance = lum.r;
+ luminance = luminance*lum_quad.y+lum_quad.z;
+
+ vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g;
+
+ vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb;
+ gi_col *= diff;
+
+ vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
+
+ vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+
+
+ sun_col *= 1.0/min(luminance, 1.0);
+ gi_col *= 1.0/luminance;
+
+ vec3 col = sun_col.rgb+gi_col+local_col;
+
+ gl_FragColor.rgb = col.rgb;
+ col.rgb = max(col.rgb-vec3(1.0,1.0,1.0), vec3(0.0, 0.0, 0.0));
+
+ gl_FragColor.a = 0.0; // max(dot(col.rgb,col.rgb)*lum_quad.x, sun_col.a);
+
+ //gl_FragColor.rgb = vec3(lum_lod);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
new file mode 100644
index 0000000000..9819232fd5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postDeferredV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
new file mode 100644
index 0000000000..9612aee405
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -0,0 +1,79 @@
+/**
+ * @file postgiF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D noiseMap;
+
+uniform vec2 kern[32];
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform int kern_length;
+uniform float kern_scale;
+uniform vec3 blur_quad;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ vec3 pos = getPosition(vary_fragcoord.xy).xyz;
+
+
+ vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec2 dlt = kern_scale * delta/(1.0+norm.xy*norm.xy);
+ dlt /= max(-pos.z*dist_factor, 1.0);
+ float defined_weight = kern[0].x;
+ vec3 col = vec3(0.0);
+
+ for (int i = 0; i < kern_length; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
+ vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0;
+
+ float d = dot(norm.xyz, sampNorm);
+
+ if (d > 0.8)
+ {
+ vec3 samppos = getPosition(tc.xy).xyz;
+ samppos -= pos;
+ if (dot(samppos,samppos) < -0.05*pos.z)
+ {
+ col += texture2DRect(giLightMap, tc).rgb*kern[i].x;
+ defined_weight += kern[i].x;
+ }
+ }
+ }
+
+ col /= defined_weight;
+
+ //col = ccol;
+
+ col = col*col*blur_quad.x + col*blur_quad.y + blur_quad.z;
+
+ gl_FragData[0].xyz = col;
+
+ //gl_FragColor = ccol;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
new file mode 100644
index 0000000000..6adcda82a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postgiV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
index b3758c3638..b0b31fd4ba 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
@@ -7,8 +7,11 @@
uniform sampler2D diffuseMap;
+varying vec4 post_pos;
void main()
{
gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a);
+
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
index aae1beeae3..7214d246a4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
@@ -5,13 +5,17 @@
* $License$
*/
+varying vec4 post_pos;
+
void main()
{
//transform vertex
vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex;
- //smash geometry against the near clip plane (great for ortho projections)
- pos.z = max(pos.z, -1.0);
- gl_Position = pos;
+
+ post_pos = pos;
+
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index d5671a6ce4..b4b0d0ce9d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -12,9 +12,9 @@ uniform sampler2DRect specularRect;
uniform sampler2DRect positionMap;
uniform sampler2DRect normalMap;
uniform sampler2DRect depthMap;
-uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
uniform float blur_size;
uniform float blur_fidelity;
@@ -38,9 +38,9 @@ uniform vec4 max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform vec3 env_mat[3];
-uniform mat4 shadow_matrix[3];
-uniform vec4 shadow_clip;
-uniform mat3 ssao_effect_mat;
+//uniform mat4 shadow_matrix[3];
+//uniform vec4 shadow_clip;
+//uniform mat3 ssao_effect_mat;
varying vec4 vary_light;
varying vec2 vary_fragcoord;
@@ -52,6 +52,22 @@ vec3 vary_AmblitColor;
vec3 vary_AdditiveColor;
vec3 vary_AtmosAttenuation;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
vec3 getPositionEye()
{
return vary_PositionEye;
@@ -162,17 +178,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
temp2.x += .25;
//increase ambient when there are more clouds
- vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
-
- /* decrease value and saturation (that in HSV, not HSL) for occluded areas
- * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
- * // The following line of code performs the equivalent of:
- * float ambAlpha = tmpAmbient.a;
- * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
- * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
- * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
- */
- tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
//haze color
setAdditiveColor(
@@ -235,36 +241,27 @@ vec3 scaleSoftClip(vec3 light)
void main()
{
vec2 tc = vary_fragcoord.xy;
- vec3 pos = texture2DRect(positionMap, tc).xyz;
- vec3 norm = texture2DRect(normalMap, tc).xyz;
- vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+ vec3 pos = getPosition(tc).xyz;
+ vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
- vec4 diffuse = vec4(texture2DRect(diffuseRect, tc).rgb, 1.0);
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
- float scol = scol_ambocc.r;
- float ambocc = scol_ambocc.g;
-
- calcAtmospherics(pos.xyz, ambocc);
+ calcAtmospherics(pos.xyz, 0.0);
vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(min(da, scol));
+ col += atmosAffectDirectionalLight(clamp(da, diffuse.a, 1.0));
col *= diffuse.rgb;
- if (spec.a > 0.2)
+ if (spec.a > 0.0)
{
- vec3 ref = reflect(pos.xyz, norm.xyz);
- vec3 rc;
- rc.x = dot(ref, env_mat[0]);
- rc.y = dot(ref, env_mat[1]);
- rc.z = dot(ref, env_mat[2]);
-
- vec3 refcol = textureCube(environmentMap, rc).rgb;
- col.rgb += refcol * spec.rgb;
+ vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(ref, vary_light.xyz);
+ col.rgb += vary_SunlitColor*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
}
col = atmosLighting(col);
@@ -272,8 +269,4 @@ void main()
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
- //gl_FragColor.rg = scol_ambocc.rg;
- //gl_FragColor.rgb = norm.rgb*0.5+0.5;
- //gl_FragColor.rgb = vec3(ambocc);
- //gl_FragColor.rgb = vec3(scol);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
new file mode 100644
index 0000000000..2a7234fd83
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -0,0 +1,177 @@
+/**
+ * @file spotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex;
+ }
+
+ float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+ //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
+ float amb_da = proj_ambiance;
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.z+proj_near;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+ }
+ }
+ }
+ }
+
+ /*if (spec.a > 0.0)
+ {
+ //vec3 ref = reflect(normalize(pos), norm);
+ float sa = dot(normalize(lv-normalize(pos)),norm);;
+ //sa = max(sa, 0.0);
+ //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*lcol*spec.rgb;
+ }*/
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
index d43fe6ca95..22bdd2c7f3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
@@ -7,17 +7,21 @@
#extension GL_ARB_texture_rectangle : enable
-uniform sampler2DRect positionMap;
-uniform sampler2DRect normalMap;
uniform sampler2DRect depthMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
+uniform sampler2DRect normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DRectShadow shadowMap4;
+uniform sampler2DRectShadow shadowMap5;
uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+
// Inputs
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform float ssao_radius;
uniform float ssao_max_radius;
@@ -27,6 +31,25 @@ uniform float ssao_factor_inv;
varying vec2 vary_fragcoord;
varying vec4 vary_light;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
//calculate decreases in ambient lighting when crowded out (SSAO)
float calcAmbientOcclusion(vec4 pos, vec3 norm)
{
@@ -54,7 +77,7 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
- vec3 samppos_world = texture2DRect(positionMap, samppos_screen).xyz;
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
vec3 diff = pos_world - samppos_world;
float dist2 = dot(diff, diff);
@@ -74,14 +97,18 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
- return 1.0 - (float(points != 0) * angle_hidden);
+ return (1.0 - (float(points != 0) * angle_hidden));
}
void main()
{
vec2 pos_screen = vary_fragcoord.xy;
- vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0);
- vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+
+ //try doing an unproject here
+
+ vec4 pos = getPosition(pos_screen);
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
{
@@ -90,35 +117,45 @@ void main()
}*/
float shadow = 1.0;
- float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+ float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+ vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0);
+
+ //vec3 debug = vec3(0,0,0);
+
if (dp_directional_light == 0.0)
{
// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
shadow = 0.0;
}
- else if (pos.z > -shadow_clip.w)
+ else if (spos.z > -shadow_clip.w)
{
- if (pos.z < -shadow_clip.z)
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
{
- vec4 lpos = shadow_matrix[3]*pos;
- shadow = shadow2DProj(shadowMap3, lpos).x;
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap3, lpos).x;
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
}
- else if (pos.z < -shadow_clip.y)
+ else if (spos.z < -shadow_clip.y)
{
- vec4 lpos = shadow_matrix[2]*pos;
- shadow = shadow2DProj(shadowMap2, lpos).x;
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap2, lpos).x;
}
- else if (pos.z < -shadow_clip.x)
+ else if (spos.z < -shadow_clip.x)
{
- vec4 lpos = shadow_matrix[1]*pos;
- shadow = shadow2DProj(shadowMap1, lpos).x;
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap1, lpos).x;
}
else
{
- vec4 lpos = shadow_matrix[0]*pos;
- shadow = shadow2DProj(shadowMap0, lpos).x;
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap0, lpos).x;
}
// take the most-shadowed value out of these two:
@@ -126,6 +163,17 @@ void main()
// * an unblurred dot product between the sun and this norm
// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
shadow = min(shadow, dp_directional_light);
+
+ /*debug.r = lpos.y / (lpos.w*screen_res.y);
+
+ lpos.xy /= lpos.w*32.0;
+ if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
+ {
+ debug.gb = vec2(0.5, 0.5);
+ }
+
+ debug += (1.0-shadow)*0.5;*/
+
}
else
{
@@ -135,5 +183,18 @@ void main()
gl_FragColor[0] = shadow;
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
- //gl_FragColor[2] is unused as of August 2008, may be used for debugging
+
+ //spotlight shadow 1
+ vec4 lpos = shadow_matrix[4]*spos;
+ lpos.xy *= screen_res;
+ gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x;
+
+ //spotlight shadow 2
+ lpos = shadow_matrix[5]*spos;
+ lpos.xy *= screen_res;
+ gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x;
+
+ //gl_FragColor.rgb = pos.xyz;
+ //gl_FragColor.b = shadow;
+ //gl_FragColor.rgb = debug;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 211b2e0397..3cccfb7202 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -12,7 +12,6 @@ uniform sampler2D detail_3;
uniform sampler2D alpha_ramp;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
@@ -28,9 +27,8 @@ void main()
float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a;
vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal );
- gl_FragData[0] = vec4(outColor.rgb, 1.0);
+ gl_FragData[0] = vec4(outColor.rgb, 0.0);
gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
index e9d6dcabff..3038b14772 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
@@ -6,7 +6,6 @@
*/
varying vec3 vary_normal;
-varying vec4 vary_position;
vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
{
@@ -27,7 +26,6 @@ void main()
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
// Transform and pass tex coords
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index bc2c9816dc..258acee08c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -8,13 +8,11 @@
uniform sampler2D diffuseMap;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
- gl_FragData[0] = gl_Color*col;
+ gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
gl_FragData[1] = vec4(0,0,0,0);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
index 9131d7c2b3..6b9dc2defb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
@@ -6,7 +6,6 @@
*/
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
@@ -14,8 +13,6 @@ void main()
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index 0a1f019e3d..d21575119d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -5,19 +5,21 @@
* $License$
*/
+#extension GL_ARB_texture_rectangle : enable
+
vec3 scaleSoftClip(vec3 inColor);
vec3 atmosTransport(vec3 inColor);
uniform sampler2D bumpMap;
uniform sampler2D screenTex;
uniform sampler2D refTex;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
uniform sampler2D noiseMap;
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform float sunAngle;
@@ -32,7 +34,8 @@ uniform vec3 normScale;
uniform float fresnelScale;
uniform float fresnelOffset;
uniform float blurMultiplier;
-
+uniform vec2 screen_res;
+uniform mat4 norm_mat; //region space to screen space
//bigWave is (refCoord.w, view.w);
varying vec4 refCoord;
@@ -88,7 +91,7 @@ void main()
refcol *= df1 * 0.333;
vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
- wavef.z *= max(-viewVec.z, 0.1);
+ //wavef.z *= max(-viewVec.z, 0.1);
wavef = normalize(wavef);
float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
@@ -101,10 +104,10 @@ void main()
refcol = mix(baseCol*df2, refcol, dweight);
//get specular component
- float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
+ //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
//harden specular
- spec = pow(spec, 128.0);
+ //spec = pow(spec, 128.0);
//figure out distortion vector (ripply)
vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
@@ -118,40 +121,21 @@ void main()
float shadow = 1.0;
vec4 pos = vary_position;
- vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
-
- if (pos.z > -shadow_clip.w)
- {
- vec4 spos = pos;
-
- if (pos.z < -shadow_clip.z)
- {
- vec4 lpos = (shadow_matrix[3]*spos);
- shadow = shadow2DProj(shadowMap3, lpos).x;
- }
- else if (pos.z < -shadow_clip.y)
- {
- vec4 lpos = (shadow_matrix[2]*spos);
- shadow = shadow2DProj(shadowMap2, lpos).x;
- }
- else if (pos.z < -shadow_clip.x)
- {
- vec4 lpos = (shadow_matrix[1]*spos);
- shadow = shadow2DProj(shadowMap1, lpos).x;
- }
- else
- {
- vec4 lpos = (shadow_matrix[0]*spos);
- shadow = shadow2DProj(shadowMap0, lpos).x;
- }
- }
-
- spec *= shadow;
- color.rgb += spec * specular;
-
- color.rgb = atmosTransport(color.rgb);
- color.rgb = scaleSoftClip(color.rgb);
- color.a = spec * sunAngle2;
+ //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
+ vec4 spos = pos;
+
+ //spec *= shadow;
+ //color.rgb += spec * specular;
+
+ //color.rgb = atmosTransport(color.rgb);
+ //color.rgb = scaleSoftClip(color.rgb);
+ //color.a = spec * sunAngle2;
- gl_FragColor = color;
+ //wavef.z = -0.25f;
+ wavef = normalize(wavef);
+ wavef = (norm_mat*vec4(wavef, 1.0)).xyz;
+
+ gl_FragData[0] = vec4(color.rgb, 0.75);
+ gl_FragData[1] = vec4(1,1,1, 0.8);
+ gl_FragData[2] = vec4(wavef*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
new file mode 100644
index 0000000000..ad16de6d81
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -0,0 +1,132 @@
+/**
+ * @file alphaF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2D diffuseMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2D noiseMap;
+uniform sampler2DRect depthMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_light;
+
+uniform float alpha_soften;
+
+uniform float shadow_bias;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
+
+ return shadow/5.0;
+}
+
+
+void main()
+{
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+ frag *= screen_res;
+
+ vec3 samp_pos = getPosition(frag).xyz;
+
+ float shadow = 1.0;
+ vec4 pos = vec4(vary_position, 1.0);
+
+ vec4 spos = pos;
+
+ if (spos.z > -shadow_clip.w)
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 1.5);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 1.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 1.5);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.5);
+ }
+ }
+
+ vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
+ vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ if (samp_pos.z != 0.0 && gl_Color.a < 1.0)
+ {
+ float dist_factor = alpha_soften;
+ float a = gl_Color.a;
+ a *= a;
+ dist_factor *= 1.0/(1.0-a);
+ color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
+ }
+
+ //gl_FragColor = gl_Color;
+ gl_FragColor = color;
+ //gl_FragColor = vec4(1,0,1,1)*shadow;
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
new file mode 100644
index 0000000000..5991e1f3b5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -0,0 +1,76 @@
+/**
+ * @file alphaV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+void calcAtmospherics(vec3 inPositionEye);
+
+float calcDirectionalLight(vec3 n, vec3 l);
+float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
+
+vec3 atmosAmbient(vec3 light);
+vec3 atmosAffectDirectionalLight(float lightIntensity);
+vec3 scaleDownLight(vec3 light);
+vec3 scaleUpLight(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_light;
+
+uniform float near_clip;
+uniform float shadow_offset;
+uniform float shadow_bias;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+
+ vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+ vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+
+ float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
+ vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
+
+ calcAtmospherics(pos.xyz);
+
+ //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
+ vec4 col;
+ col.a = gl_Color.a;
+
+ // Add windlight lights
+ col.rgb = atmosAmbient(vec3(0.));
+ col.rgb = scaleUpLight(col.rgb);
+
+ // Collect normal lights (need to be divided by two, as we later multiply by 2)
+ col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
+ col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
+ col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
+ col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
+ col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
+ col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
+ col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
+ col.rgb = scaleDownLight(col.rgb);
+
+ vary_light = gl_LightSource[0].position.xyz;
+
+ vary_ambient = col.rgb*gl_Color.rgb;
+ vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
+
+ col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
+
+ gl_FrontColor = col;
+
+ gl_FogFragCoord = pos.z;
+
+ pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
+
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl
new file mode 100644
index 0000000000..a81e4caf4c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl
@@ -0,0 +1,98 @@
+/**
+ * @file avatarAlphaF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2D diffuseMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2D noiseMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_position;
+varying vec3 vary_normal;
+
+uniform float shadow_bias;
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
+
+ return shadow/5.0;
+}
+
+void main()
+{
+ float shadow = 1.0;
+ vec4 pos = vec4(vary_position, 1.0);
+ vec3 norm = normalize(vary_normal);
+
+ //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
+
+ vec4 spos = pos;
+
+ if (spos.z > -shadow_clip.w)
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 1.5);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 1.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 1.5);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.5);
+ }
+ }
+
+
+ vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a);
+ vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ gl_FragColor = color;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
new file mode 100644
index 0000000000..a939499b17
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -0,0 +1,84 @@
+/**
+ * @file avatarAlphaV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+mat4 getSkinnedTransform();
+void calcAtmospherics(vec3 inPositionEye);
+
+float calcDirectionalLight(vec3 n, vec3 l);
+float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
+
+vec3 atmosAmbient(vec3 light);
+vec3 atmosAffectDirectionalLight(float lightIntensity);
+vec3 scaleDownLight(vec3 light);
+vec3 scaleUpLight(vec3 light);
+
+varying vec3 vary_position;
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_normal;
+
+uniform float near_clip;
+uniform float shadow_offset;
+uniform float shadow_bias;
+
+void main()
+{
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ vec4 pos;
+ vec3 norm;
+
+ mat4 trans = getSkinnedTransform();
+ pos.x = dot(trans[0], gl_Vertex);
+ pos.y = dot(trans[1], gl_Vertex);
+ pos.z = dot(trans[2], gl_Vertex);
+ pos.w = 1.0;
+
+ norm.x = dot(trans[0].xyz, gl_Normal);
+ norm.y = dot(trans[1].xyz, gl_Normal);
+ norm.z = dot(trans[2].xyz, gl_Normal);
+ norm = normalize(norm);
+
+ gl_Position = gl_ProjectionMatrix * pos;
+
+ float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
+ vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
+ vary_normal = norm;
+
+ calcAtmospherics(pos.xyz);
+
+ //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
+ vec4 col;
+ col.a = gl_Color.a;
+
+ // Add windlight lights
+ col.rgb = atmosAmbient(vec3(0.));
+ col.rgb = scaleUpLight(col.rgb);
+
+ // Collect normal lights (need to be divided by two, as we later multiply by 2)
+ col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
+ col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
+ col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
+ col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
+ col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
+ col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
+ col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
+ col.rgb = scaleDownLight(col.rgb);
+
+ vary_ambient = col.rgb*gl_Color.rgb;
+ vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
+
+ col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
+
+ gl_FrontColor = col;
+
+ gl_FogFragCoord = pos.z;
+
+}
+
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
new file mode 100644
index 0000000000..8bd702a8da
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
@@ -0,0 +1,96 @@
+/**
+ * @file blurLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2DRect edgeMap;
+
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform vec3 kern[4];
+uniform float kern_scale;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ vec3 pos = getPosition(vary_fragcoord.xy).xyz;
+ vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
+
+ vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+
+ dlt /= max(-pos.z*dist_factor, 1.0);
+
+ vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+ vec4 col = defined_weight.xyxx * ccol;
+
+ float e = 1.0;
+ for (int i = 0; i < 4; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
+
+ e = max(e, 0.0);
+
+ vec2 wght = kern[i].xy*e;
+
+ col += texture2DRect(lightMap, tc)*wght.xyxx;
+ defined_weight += wght;
+
+ e *= e;
+ e -= texture2DRect(edgeMap, tc.xy).a+
+ texture2DRect(edgeMap, tc.xy+dlt*0.333).a+
+ texture2DRect(edgeMap, tc.xy-dlt*0.333).a;
+ }
+
+
+ e = 1.0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
+
+ e = max(e, 0.0);
+
+ vec2 wght = kern[i].xy*e;
+
+ col += texture2DRect(lightMap, tc)*wght.xyxx;
+ defined_weight += wght;
+
+ e *= e;
+ e -= texture2DRect(edgeMap, tc.xy).a+
+ texture2DRect(edgeMap, tc.xy+dlt*0.333).a+
+ texture2DRect(edgeMap, tc.xy-dlt*0.333).a;
+ }
+
+
+ col /= defined_weight.xyxx;
+
+ gl_FragColor = col;
+
+ //gl_FragColor = ccol;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
new file mode 100644
index 0000000000..b7f07e5702
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file blurLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
new file mode 100644
index 0000000000..02beddd43b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
@@ -0,0 +1,58 @@
+/**
+ * @file edgeF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+
+uniform float gi_dist_cutoff;
+
+varying vec2 vary_fragcoord;
+
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+float getDepth(vec2 pos_screen)
+{
+ float z = texture2DRect(depthMap, pos_screen.xy).a;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ float depth = getDepth(vary_fragcoord.xy);
+
+ vec2 tc = vary_fragcoord.xy;
+
+ float sc = 0.75;
+
+ vec2 de;
+ de.x = (depth-getDepth(tc+vec2(sc, sc))) + (depth-getDepth(tc+vec2(-sc, -sc)));
+ de.y = (depth-getDepth(tc+vec2(-sc, sc))) + (depth-getDepth(tc+vec2(sc, -sc)));
+ de /= depth;
+ de *= de;
+ de = step(depth_cutoff, de);
+
+ vec2 ne;
+ ne.x = dot(texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb*2.0-1.0, norm);
+ ne.y = dot(texture2DRect(normalMap, tc+vec2(sc,sc)).rgb*2.0-1.0, norm);
+
+ ne = 1.0-ne;
+
+ ne = step(norm_cutoff, ne);
+
+ gl_FragColor.a = dot(de,de)+dot(ne,ne);
+ //gl_FragColor.a = dot(de,de);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
new file mode 100644
index 0000000000..f1938c92b8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file edgeV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
new file mode 100644
index 0000000000..651959413c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -0,0 +1,188 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ float shadow = 1.0;
+
+ if (proj_shadow_idx >= 0)
+ {
+ vec4 shd = texture2DRect(lightMap, frag.xy);
+ float sh[2];
+ sh[0] = shd.b;
+ sh[1] = shd.a;
+ shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+ if (dist_atten <= 0.0)
+ {
+ discard;
+ }
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ float amb_da = proj_ambiance;
+
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex*shadow;
+ amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod);
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.w;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+ }
+ }
+ }
+ }
+
+ //attenuate point light contribution by SSAO component
+ col *= texture2DRect(lightMap, frag.xy).g;
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl
new file mode 100644
index 0000000000..ee0e9d6367
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl
@@ -0,0 +1,59 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect localLightMap;
+uniform sampler2DRect sunLightMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D luminanceMap;
+uniform sampler2DRect lightMap;
+
+uniform vec3 gi_lum_quad;
+uniform vec3 sun_lum_quad;
+uniform vec3 lum_quad;
+uniform float lum_lod;
+uniform vec4 ambient;
+
+uniform vec3 gi_quad;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb;
+
+ float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z;
+
+ vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g;
+
+ vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb;
+ gi_col *= diff;
+
+ vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
+
+ vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+
+
+ float sun_lum = 1.0-lum;
+ sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z;
+
+ float gi_lum = lum;
+ gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z;
+ gi_col *= 1.0/gi_lum;
+
+ vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col;
+
+ gl_FragColor.rgb = col.rgb;
+ gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a);
+
+ //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl
new file mode 100644
index 0000000000..9819232fd5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postDeferredV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
new file mode 100644
index 0000000000..531f7376a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -0,0 +1,294 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+uniform vec3 gi_quad;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+uniform sampler2DRect depthMap;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 getPositionEye()
+{
+ return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+ return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+ return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+ return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+ return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+ vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+ vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+ vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+ vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+ vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+ vec3 P = inPositionEye;
+ setPositionEye(P);
+
+ //(TERRAIN) limit altitude
+ if (P.y > max_y.x) P *= (max_y.x / P.y);
+ if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+ vec3 tmpLightnorm = lightnorm.xyz;
+
+ vec3 Pn = normalize(P);
+ float Plen = length(P);
+
+ vec4 temp1 = vec4(0);
+ vec3 temp2 = vec3(0);
+ vec4 blue_weight;
+ vec4 haze_weight;
+ vec4 sunlight = sunlight_color;
+ vec4 light_atten;
+
+ //sunlight attenuation effect (hue and brightness) due to atmosphere
+ //this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ //I had thought blue_density and haze_density should have equal weighting,
+ //but attenuation due to haze_density tends to seem too strong
+
+ temp1 = blue_density + vec4(haze_density.r);
+ blue_weight = blue_density / temp1;
+ haze_weight = vec4(haze_density.r) / temp1;
+
+ //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+ temp2.y = max(0.0, tmpLightnorm.y);
+ temp2.y = 1. / temp2.y;
+ sunlight *= exp( - light_atten * temp2.y);
+
+ // main atmospheric scattering line integral
+ temp2.z = Plen * density_multiplier.x;
+
+ // Transparency (-> temp1)
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // compiler gets confused.
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+ //final atmosphere attenuation factor
+ setAtmosAttenuation(temp1.rgb);
+
+ //compute haze glow
+ //(can use temp2.x as temp because we haven't used it yet)
+ temp2.x = dot(Pn, tmpLightnorm.xyz);
+ temp2.x = 1. - temp2.x;
+ //temp2.x is 0 at the sun and increases away from sun
+ temp2.x = max(temp2.x, .03); //was glow.y
+ //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ temp2.x *= glow.x;
+ //higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ temp2.x = pow(temp2.x, glow.z);
+ //glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ //add "minimum anti-solar illumination"
+ temp2.x += .25;
+
+ //increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+
+ /* decrease value and saturation (that in HSV, not HSL) for occluded areas
+ * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+ * // The following line of code performs the equivalent of:
+ * float ambAlpha = tmpAmbient.a;
+ * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+ * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+ * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+ */
+ tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+ //haze color
+ setAdditiveColor(
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ + tmpAmbient)));
+
+ //brightness of surface both sunlight and ambient
+ setSunlitColor(vec3(sunlight * .5));
+ setAmblitColor(vec3(tmpAmbient * .25));
+ setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor();
+ return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor() * 2.0;
+ return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+ return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+ return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+ return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+ return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+ return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 pos = getPosition(tc).xyz;
+ vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+
+ float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
+
+ calcAtmospherics(pos.xyz, ambocc);
+
+ vec3 col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+
+ col *= diffuse.rgb;
+
+ if (spec.a > 0.0)
+ {
+ vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(ref, vary_light.xyz);
+ col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ gl_FragColor.rgb = col;
+
+ //gl_FragColor.rgb = gi_col.rgb;
+ gl_FragColor.a = 0.0;
+
+ //gl_FragColor.rg = scol_ambocc.rg;
+ //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
+ //gl_FragColor.rgb = norm.rgb*0.5+0.5;
+ //gl_FragColor.rgb = vec3(ambocc);
+ //gl_FragColor.rgb = vec3(scol);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
new file mode 100644
index 0000000000..ad8af4780d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -0,0 +1,24 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ vary_light = gl_MultiTexCoord0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
new file mode 100644
index 0000000000..d6534083cf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -0,0 +1,199 @@
+/**
+ * @file spotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ float shadow = 1.0;
+
+ if (proj_shadow_idx >= 0)
+ {
+ vec4 shd = texture2DRect(lightMap, frag.xy);
+ float sh[2];
+ sh[0] = shd.b;
+ sh[1] = shd.a;
+ shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+ }
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex*shadow;
+ }
+
+ float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+ //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
+ float amb_da = proj_ambiance;
+ if (da > 0.0)
+ {
+ amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ }
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.z+proj_near;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+ }
+ }
+ }
+ }
+
+ /*if (spec.a > 0.0)
+ {
+ //vec3 ref = reflect(normalize(pos), norm);
+ float sa = dot(normalize(lv-normalize(pos)),norm);;
+ //sa = max(sa, 0.0);
+ //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*lcol*spec.rgb;
+ }*/
+
+ //attenuate point light contribution by SSAO component
+ col *= texture2DRect(lightMap, frag.xy).g;
+
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
new file mode 100644
index 0000000000..a0026edcd2
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -0,0 +1,235 @@
+/**
+ * @file sunLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+uniform sampler2D noiseMap;
+
+uniform sampler2D lightFunc;
+
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm)
+{
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+ kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+ kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+ kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+ kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+ kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+ kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+ kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec3 pos_world = pos.xyz;
+ vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+
+ float angle_hidden = 0.0;
+ int points = 0;
+
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
+
+ vec3 diff = pos_world - samppos_world;
+ float dist2 = dot(diff, diff);
+
+ // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+ // --> solid angle shrinking by the square of distance
+ //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+ //(k should vary inversely with # of samples, but this is taken care of later)
+
+ //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
+ // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
+ angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+
+ // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
+ points = points + int(diff.z > -1.0);
+ }
+
+ angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+
+ return (1.0 - (float(points != 0) * angle_hidden));
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias*scl;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias*scl;
+
+ float cs = shadow2D(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ vec2 off = 1.5/proj_shadow_res;
+
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
+
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+
+ //try doing an unproject here
+
+ vec4 pos = getPosition(pos_screen);
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+
+ /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
+ {
+ gl_FragColor = vec4(0.0); // doesn't matter
+ return;
+ }*/
+
+ float shadow = 1.0;
+ float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+
+ vec4 spos = vec4(pos.xyz + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0);
+
+ if (spos.z > -shadow_clip.w)
+ {
+ if (dp_directional_light == 0.0)
+ {
+ // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
+ shadow = 0.0;
+ }
+ else
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 0.25);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 0.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 0.75);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.0);
+ }
+
+ // take the most-shadowed value out of these two:
+ // * the blurred sun shadow in the light (shadow) map
+ // * an unblurred dot product between the sun and this norm
+ // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
+ shadow = min(shadow, dp_directional_light);
+
+ //lpos.xy /= lpos.w*32.0;
+ //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
+ //{
+ // shadow = 0.0;
+ //}
+
+ }
+ }
+ else
+ {
+ // more distant than the shadow map covers
+ shadow = 1.0;
+ }
+
+ gl_FragColor[0] = shadow;
+ gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
+
+ //spotlight shadow 1
+ vec4 lpos = shadow_matrix[4]*spos;
+ gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x;
+
+ //spotlight shadow 2
+ lpos = shadow_matrix[5]*spos;
+ gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x;
+
+ //gl_FragColor.rgb = pos.xyz;
+ //gl_FragColor.b = shadow;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
new file mode 100644
index 0000000000..5081485c4b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
@@ -0,0 +1,25 @@
+/**
+ * @file sunLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ vary_light = gl_MultiTexCoord0;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
new file mode 100644
index 0000000000..7325825d6d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
@@ -0,0 +1,84 @@
+/**
+ * @file giDownsampleF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect giLightMap;
+
+uniform vec2 kern[32];
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform int kern_length;
+uniform float kern_scale;
+uniform vec3 blur_quad;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+float getDepth(vec2 pos_screen)
+{
+ float z = texture2DRect(depthMap, pos_screen.xy).a;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ float depth = getDepth(vary_fragcoord.xy);
+
+ vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy);
+ dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0);
+ float defined_weight = kern[0].x;
+ vec3 col = ccol*kern[0].x;
+
+ for (int i = 0; i < kern_length; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
+ vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0;
+
+ float d = dot(norm.xyz, sampNorm);
+
+ if (d > 0.5)
+ {
+ float sampdepth = getDepth(tc.xy);
+ sampdepth -= depth;
+ if (sampdepth*sampdepth < blur_quad.z)
+ {
+ col += texture2DRect(giLightMap, tc).rgb*kern[i].x;
+ defined_weight += kern[i].x;
+ }
+ }
+ }
+
+ col /= defined_weight;
+
+ //col = ccol;
+
+ col = col*blur_quad.y;
+
+ gl_FragData[0].xyz = col;
+
+ //gl_FragColor = ccol;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
new file mode 100644
index 0000000000..6adcda82a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postgiV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
new file mode 100644
index 0000000000..939710cb56
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
@@ -0,0 +1,190 @@
+/**
+ * @file giF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2DRect specularRect;
+
+uniform sampler2D noiseMap;
+
+uniform sampler2D diffuseGIMap;
+uniform sampler2D specularGIMap;
+uniform sampler2D normalGIMap;
+uniform sampler2D depthGIMap;
+
+uniform sampler2D lightFunc;
+
+// Inputs
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+uniform vec4 sunlight_color;
+
+uniform mat4 inv_proj;
+uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space
+uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space
+uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix
+uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space
+uniform float gi_sample_width;
+uniform float gi_noise;
+uniform float gi_attenuation;
+uniform float gi_range;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec4 getGIPosition(vec2 gi_tc)
+{
+ float depth = texture2D(depthGIMap, gi_tc).a;
+ vec2 sc = gi_tc*2.0;
+ sc -= vec2(1.0, 1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = gi_inv_proj*ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 giAmbient(vec3 pos, vec3 norm)
+{
+ vec4 gi_c = gi_mat_proj * vec4(pos, 1.0);
+ gi_c.xyz /= gi_c.w;
+
+ vec4 gi_pos = gi_mat*vec4(pos,1.0);
+ vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz;
+ gi_norm = normalize(gi_norm);
+
+ vec4 c_spec = texture2DRect(specularRect, vary_fragcoord.xy);
+ vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).rgb;
+ gi_pos.xyz += nz.x*gi_noise*gi_norm.xyz;
+ vec2 tcx = gi_norm.xy;
+ vec2 tcy = gi_norm.yx;
+
+ vec4 eye_pos = gi_mat*vec4(0,0,0,1.0);
+
+ vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz);
+ vec3 eye_ref = reflect(eye_dir, gi_norm);
+
+ float da = 0.0; //texture2DRect(lightMap, vary_fragcoord.xy).r*0.5;
+ vec3 fdiff = vec3(da);
+ float fda = da;
+
+ vec3 rcol = vec3(0,0,0);
+
+ float fsa = 0.0;
+
+
+ for (int i = -1; i <= 1; i += 2 )
+ {
+ for (int j = -1; j <= 1; j+= 2)
+ {
+ vec2 tc = vec2(i, j)*0.75+gi_norm.xy*nz.z;
+ tc += nz.xy*2.0;
+ tc *= gi_sample_width*0.25;
+ tc += gi_c.xy;
+
+ vec3 lnorm = -(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0);
+ vec3 lpos = getGIPosition(tc.xy).xyz;
+
+ vec3 at = lpos-gi_pos.xyz;
+ float dist = length(at);
+ float dist_atten = clamp(1.0/(gi_attenuation*dist), 0.0, 1.0);
+
+
+ if (dist_atten > 0.01)
+ { //possible contribution of indirect light to this surface
+ vec3 ldir = at;
+
+ float ld = -dot(ldir, lnorm);
+
+ if (ld < 0.0)
+ {
+ float ang_atten = dot(ldir, gi_norm);
+
+ if (ang_atten > 0.0)
+ {
+ vec4 spec = texture2D(specularGIMap, tc.xy);
+ at = normalize(at);
+ vec3 diff;
+
+ float da = 0.0;
+
+ //contribution from indirect source to visible pixel
+ vec3 ha = at;
+ ha.z -= 1.0;
+ ha = normalize(ha);
+ if (spec.a > 0.0)
+ {
+ float sa = dot(ha,lnorm);
+ da = texture2D(lightFunc, vec2(sa, spec.a)).a;
+ }
+ else
+ {
+ da = -lnorm.z;
+ }
+
+ diff = texture2D(diffuseGIMap, tc.xy).rgb+spec.rgb*spec.a*2.0;
+
+ if (da > 0.0)
+ { //contribution from visible pixel to eye
+ vec3 ha = normalize(at-eye_dir);
+ if (c_spec.a > 0.0)
+ {
+ float sa = dot(ha, gi_norm);
+ da = dist_atten*texture2D(lightFunc, vec2(sa, c_spec.a)).a;
+ }
+ else
+ {
+ da = dist_atten*dot(gi_norm, normalize(ldir));
+ }
+ fda += da;
+ fdiff += da*(c_spec.rgb*c_spec.a*2.0+vec3(1,1,1))*diff.rgb;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fdiff *= sunlight_color.rgb;
+
+ vec3 ret = fda*fdiff;
+
+ return clamp(ret,vec3(0.0), vec3(1.0));
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec4 pos = getPosition(pos_screen);
+
+ float rad = gi_range*0.5;
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+ float dist = max(length(pos.xyz)-rad, 0.0);
+
+ float da = clamp(1.0-dist/rad, 0.0, 1.0);
+
+ vec3 ambient = da > 0.0 ? giAmbient(pos.xyz, norm) : vec3(0);
+
+
+ gl_FragData[0].xyz = mix(vec3(0), ambient, da);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
new file mode 100644
index 0000000000..e0eeebf8b6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
@@ -0,0 +1,25 @@
+/**
+ * @file giFinalF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2D bloomMap;
+uniform sampler2DRect edgeMap;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+
+void main()
+{
+ vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+ vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ gl_FragColor = bloom + diff;
+ //gl_FragColor.rgb = vec3(texture2DRect(edgeMap, vary_fragcoord.xy).a);
+} \ No newline at end of file
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
new file mode 100644
index 0000000000..41a29c31bd
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file giFinalV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
new file mode 100644
index 0000000000..71dcea9628
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
@@ -0,0 +1,22 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
new file mode 100644
index 0000000000..406a7e07cf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
@@ -0,0 +1,19 @@
+/**
+ * @file luminanceF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect lightMap;
+uniform sampler2DRect diffuseRect;
+
+varying vec2 vary_fragcoord;
+void main()
+{
+ float i = texture2DRect(lightMap, vary_fragcoord.xy).r;
+ gl_FragColor.rgb = vec3(i);
+ gl_FragColor.a = 1.0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
new file mode 100644
index 0000000000..db8775f024
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
@@ -0,0 +1,20 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
new file mode 100644
index 0000000000..5e69bf36d9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
@@ -0,0 +1,80 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+
+uniform sampler2DRect localLightMap;
+uniform sampler2DRect sunLightMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2DRect edgeMap;
+
+uniform sampler2D luminanceMap;
+
+uniform sampler2DRect lightMap;
+
+uniform sampler2D lightFunc;
+uniform sampler2D noiseMap;
+
+uniform float sun_lum_scale;
+uniform float sun_lum_offset;
+uniform float lum_scale;
+uniform float lum_lod;
+uniform vec4 ambient;
+uniform float gi_brightness;
+uniform float gi_luminance;
+
+uniform vec4 sunlight_color;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec4 lcol = texture2DLod(luminanceMap, vec2(0.5, 0.5), lum_lod);
+
+ vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
+ vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+
+ float scol = texture2DRect(lightMap, vary_fragcoord.xy).r;
+
+ vec3 diff = texture2DRect(diffuseRect, vary_fragcoord.xy).rgb;
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ gi_col = gi_col*(diff.rgb+spec.rgb*spec.a);
+
+ float lum = 1.0-clamp(pow(lcol.r, gi_brightness)+sun_lum_offset, 0.0, 1.0);
+
+ lum *= sun_lum_scale;
+
+ sun_col *= 1.0+(lum*lum_scale*scol);
+
+ vec4 col;
+ col.rgb = gi_col+sun_col.rgb+local_col;
+
+ col.a = sun_col.a;
+
+ vec3 bcol = vec3(0,0,0);
+ float tweight = 0.0;
+ for (int i = 0; i < 16; i++)
+ {
+ float weight = (float(i)+1.0)/2.0;
+ bcol += texture2DLod(luminanceMap, vary_fragcoord.xy/screen_res, weight).rgb*weight*weight*weight;
+ tweight += weight*weight;
+ }
+
+ bcol /= tweight;
+ bcol *= gi_luminance;
+ col.rgb += bcol*lum;
+
+ gl_FragColor = col;
+ //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
new file mode 100644
index 0000000000..9819232fd5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postDeferredV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
new file mode 100644
index 0000000000..901b60af59
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
@@ -0,0 +1,69 @@
+/**
+ * @file postgiF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D giMip;
+uniform sampler2DRect edgeMap;
+
+
+uniform vec2 delta;
+uniform float kern_scale;
+uniform float gi_edge_weight;
+uniform float gi_blur_brightness;
+
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 dlt = kern_scale*delta;
+ float defined_weight = 0.0;
+ vec3 col = vec3(0.0);
+
+ float e = 1.0;
+
+ for (int i = 1; i < 8; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + float(i) * dlt;
+
+ e = max(e, 0.0);
+ float wght = e;
+
+ col += texture2DRect(giLightMap, tc).rgb*wght;
+ defined_weight += wght;
+
+ e *= e;
+ e -=(texture2DRect(edgeMap, tc.xy-dlt*0.25).a+
+ texture2DRect(edgeMap, tc.xy+dlt*0.25).a)*gi_edge_weight;
+ }
+
+ e = 1.0;
+
+ for (int i = 1; i < 8; i++)
+ {
+ vec2 tc = vary_fragcoord.xy - float(i) * dlt;
+
+ e = max(e,0.0);
+ float wght = e;
+
+ col += texture2DRect(giLightMap, tc).rgb*wght;
+ defined_weight += wght;
+
+ e *= e;
+ e -= (texture2DRect(edgeMap, tc.xy-dlt*0.25).a+
+ texture2DRect(edgeMap, tc.xy+dlt*0.25).a)*gi_edge_weight;
+
+ }
+
+ col /= max(defined_weight, 0.01);
+
+ gl_FragColor.rgb = col * gi_blur_brightness;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
new file mode 100644
index 0000000000..6adcda82a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postgiV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
new file mode 100644
index 0000000000..96a083b522
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -0,0 +1,297 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+uniform vec3 gi_quad;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+uniform sampler2DRect depthMap;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+uniform float gi_ambiance;
+
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 getPositionEye()
+{
+ return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+ return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+ return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+ return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+ return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+ vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+ vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+ vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+ vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+ vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+ vec3 P = inPositionEye;
+ setPositionEye(P);
+
+ //(TERRAIN) limit altitude
+ if (P.y > max_y.x) P *= (max_y.x / P.y);
+ if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+ vec3 tmpLightnorm = lightnorm.xyz;
+
+ vec3 Pn = normalize(P);
+ float Plen = length(P);
+
+ vec4 temp1 = vec4(0);
+ vec3 temp2 = vec3(0);
+ vec4 blue_weight;
+ vec4 haze_weight;
+ vec4 sunlight = sunlight_color;
+ vec4 light_atten;
+
+ //sunlight attenuation effect (hue and brightness) due to atmosphere
+ //this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ //I had thought blue_density and haze_density should have equal weighting,
+ //but attenuation due to haze_density tends to seem too strong
+
+ temp1 = blue_density + vec4(haze_density.r);
+ blue_weight = blue_density / temp1;
+ haze_weight = vec4(haze_density.r) / temp1;
+
+ //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+ temp2.y = max(0.0, tmpLightnorm.y);
+ temp2.y = 1. / temp2.y;
+ sunlight *= exp( - light_atten * temp2.y);
+
+ // main atmospheric scattering line integral
+ temp2.z = Plen * density_multiplier.x;
+
+ // Transparency (-> temp1)
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // compiler gets confused.
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+ //final atmosphere attenuation factor
+ setAtmosAttenuation(temp1.rgb);
+
+ //compute haze glow
+ //(can use temp2.x as temp because we haven't used it yet)
+ temp2.x = dot(Pn, tmpLightnorm.xyz);
+ temp2.x = 1. - temp2.x;
+ //temp2.x is 0 at the sun and increases away from sun
+ temp2.x = max(temp2.x, .03); //was glow.y
+ //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ temp2.x *= glow.x;
+ //higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ temp2.x = pow(temp2.x, glow.z);
+ //glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ //add "minimum anti-solar illumination"
+ temp2.x += .25;
+
+ //increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient*gi_ambiance + (vec4(1.) - ambient*gi_ambiance) * cloud_shadow.x * 0.5;
+
+ /* decrease value and saturation (that in HSV, not HSL) for occluded areas
+ * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+ * // The following line of code performs the equivalent of:
+ * float ambAlpha = tmpAmbient.a;
+ * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+ * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+ * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+ */
+ tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+ //haze color
+ setAdditiveColor(
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ + tmpAmbient)));
+
+ //brightness of surface both sunlight and ambient
+ setSunlitColor(vec3(sunlight * .5));
+ setAmblitColor(vec3(tmpAmbient * .25));
+ setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor();
+ return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor() * 2.0;
+ return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+ return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+ return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+ return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+ return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+ return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 pos = getPosition(tc).xyz;
+ vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+
+ float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ da = texture2D(lightFunc, vec2(da, 0.0)).a;
+
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
+
+ calcAtmospherics(pos.xyz, ambocc);
+
+ vec3 col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+
+ col *= diffuse.rgb;
+
+ if (spec.a > 0.0)
+ {
+ vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(ref, vary_light.xyz);
+ col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ gl_FragColor.rgb = col;
+
+ //gl_FragColor.rgb = gi_col.rgb;
+ gl_FragColor.a = 0.0;
+
+ //gl_FragColor.rg = scol_ambocc.rg;
+ //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
+ //gl_FragColor.rgb = norm.rgb*0.5+0.5;
+ //gl_FragColor.rgb = vec3(ambocc);
+ //gl_FragColor.rgb = vec3(scol);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
new file mode 100644
index 0000000000..ad8af4780d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
@@ -0,0 +1,24 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ vary_light = gl_MultiTexCoord0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
new file mode 100644
index 0000000000..258acee08c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
@@ -0,0 +1,18 @@
+/**
+ * @file treeF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2D diffuseMap;
+
+varying vec3 vary_normal;
+
+void main()
+{
+ vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
+ gl_FragData[1] = vec4(0,0,0,0);
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+}
diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt
index 733670f311..5c5c4e5b3c 100644
--- a/indra/newview/gpu_table.txt
+++ b/indra/newview/gpu_table.txt
@@ -162,8 +162,9 @@ Intel Montara .*Intel.*Montara.* 0 0
Intel Springdale .*Intel.*Springdale.* 0 0
Matrox .*Matrox.* 0 0
Mesa .*Mesa.* 0 0
-NVIDIA GT 120 .*NVIDIA.*GeForce.*GT.*12.* 3 1
-NVIDIA GT 130 .*NVIDIA.*GeForce.*GT.*13.* 3 1
+NVIDIA GT 120 .*NVIDIA.*GeForce.*GT.*12.* 2 1
+NVIDIA GT 130 .*NVIDIA.*GeForce.*GT.*13.* 3 1
+NVIDIA GTS 250 .*NVIDIA.*GeForce.*GTS.*25.* 3 1
NVIDIA GTX 260 .*NVIDIA.*GeForce.*GTX.*26.* 3 1
NVIDIA GTX 270 .*NVIDIA.*GeForce.*GTX.*27.* 3 1
NVIDIA GTX 280 .*NVIDIA.*GeForce.*GTX.*28.* 3 1
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 19e1273dc6..355660faa5 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -74,6 +74,7 @@
#include "llrender.h"
#include "lllocationhistory.h"
#include "llfasttimerview.h"
+
#include "llweb.h"
#include "llsecondlifeurls.h"
@@ -765,6 +766,7 @@ bool LLAppViewer::init()
//
// Initialize the window
//
+ gGLActive = TRUE;
initWindow();
// call all self-registered classes
@@ -869,12 +871,16 @@ bool LLAppViewer::init()
gSimFrames = (F32)gFrameCount;
LLViewerJoystick::getInstance()->init(false);
-
+ gGLActive = FALSE;
return true;
}
static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep");
+static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");
+static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");
+static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread");
+static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
@@ -914,6 +920,7 @@ bool LLAppViewer::mainLoop()
while (!LLApp::isExiting())
{
LLFastTimer::nextFrame(); // Should be outside of any timer instances
+
try
{
pingMainloopTimeout("Main:MiscNativeWindowEvents");
@@ -923,7 +930,7 @@ bool LLAppViewer::mainLoop()
LLFastTimer t2(FTM_MESSAGES);
gViewerWindow->mWindow->processMiscNativeEvents();
}
-
+
pingMainloopTimeout("Main:GatherInput");
if (gViewerWindow)
@@ -1007,10 +1014,11 @@ bool LLAppViewer::mainLoop()
if (!LLApp::isExiting())
{
pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
display();
-
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
+ gGLActive = FALSE;
}
}
@@ -1070,11 +1078,24 @@ bool LLAppViewer::mainLoop()
{
S32 work_pending = 0;
S32 io_pending = 0;
- work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
- work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
- work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
- io_pending += LLVFSThread::updateClass(1);
- io_pending += LLLFSThread::updateClass(1);
+ {
+ LLFastTimer ftm(FTM_TEXTURE_CACHE);
+ work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
+ }
+ {
+ LLFastTimer ftm(FTM_DECODE);
+ work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+ }
+ {
+ LLFastTimer ftm(FTM_DECODE);
+ work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+ }
+
+ {
+ LLFastTimer ftm(FTM_VFS);
+ io_pending += LLVFSThread::updateClass(1);
+ }
+
if (io_pending > 1000)
{
ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
@@ -1100,6 +1121,8 @@ bool LLAppViewer::mainLoop()
// if (LLThread::processorCount()==1) //pause() should only be required when on a single processor client...
if (run_multiple_threads == FALSE)
{
+ LLFastTimer ftm(FTM_PAUSE_THREADS);
+
LLAppViewer::getTextureCache()->pause();
LLAppViewer::getImageDecodeThread()->pause();
// LLAppViewer::getTextureFetch()->pause(); // Don't pause the fetch (IO) thread
@@ -3317,10 +3340,13 @@ void LLAppViewer::idle()
if (LLStartUp::getStartupState() < STATE_STARTED)
{
// Skip rest if idle startup returns false (essentially, no world yet)
+ gGLActive = TRUE;
if (!idle_startup())
{
+ gGLActive = FALSE;
return;
}
+ gGLActive = FALSE;
}
@@ -3419,10 +3445,8 @@ void LLAppViewer::idle()
// floating throughout the various object lists.
//
- stop_glerror();
idleNetwork();
- stop_glerror();
-
+
// Check for away from keyboard, kick idle agents.
idle_afk_check();
@@ -3512,8 +3536,6 @@ void LLAppViewer::idle()
LLHUDManager::getInstance()->sendEffects();
}
- stop_glerror();
-
////////////////////////////////////////
//
// Unpack layer data that we've received
@@ -3569,7 +3591,6 @@ void LLAppViewer::idle()
gWindVec.setVec(0.0f, 0.0f, 0.0f);
}
}
- stop_glerror();
//////////////////////////////////////
//
@@ -3584,7 +3605,6 @@ void LLAppViewer::idle()
LLWorld::getInstance()->updateParticles();
}
- stop_glerror();
if (LLViewerJoystick::getInstance()->getOverrideCamera())
{
@@ -3629,10 +3649,9 @@ void LLAppViewer::idle()
// forcibly quit if it has taken too long
if (mQuitRequested)
{
+ gGLActive = TRUE;
idleShutdown();
}
-
- stop_glerror();
}
void LLAppViewer::idleShutdown()
@@ -3771,7 +3790,6 @@ void LLAppViewer::idleNetwork()
llpushcallstacks ;
LLTimer check_message_timer;
// Read all available packets from network
- stop_glerror();
const S64 frame_count = gFrameCount; // U32->S64
F32 total_time = 0.0f;
@@ -3784,8 +3802,7 @@ void LLAppViewer::idleNetwork()
// server going down, so this is OK.
break;
}
- stop_glerror();
-
+
total_decoded++;
gPacketsIn++;
@@ -3825,9 +3842,7 @@ void LLAppViewer::idleNetwork()
// we want to clear the control after sending out all necessary agent updates
gAgent.resetControlFlags();
- stop_glerror();
-
-
+
// Decode enqueued messages...
S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 98d7ab712b..12cff32780 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -245,6 +245,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
}
#endif
+ gGLActive = TRUE;
+
viewer_app_ptr->cleanup();
#if WINDOWS_CRT_MEM_CHECKS
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index bd5b9c30a2..24a57cb0c1 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -102,6 +102,17 @@ LLDebugView::LLDebugView(const LLDebugView::Params& p)
gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp);
addChild(gTextureView);
//gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE);
+#if !LL_RELEASE_FOR_DOWNLOAD
+ r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100);
+ LLTextureSizeView::Params tsvp;
+ tsvp.name("gTextureSizeView");
+ tsvp.rect(r);
+ tsvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
+ tsvp.visible(false);
+ gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsvp);
+ addChild(gTextureSizeView);
+#endif
+
}
@@ -110,5 +121,6 @@ LLDebugView::~LLDebugView()
// These have already been deleted. Fix the globals appropriately.
gDebugView = NULL;
gTextureView = NULL;
+ gTextureSizeView = NULL;
}
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 7cc78aff92..4cf12a1533 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -678,6 +678,11 @@ BOOL LLDrawable::updateMoveDamped()
void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
{
+ if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
//switch LOD with the spatial group to avoid artifacts
//LLSpatialGroup* sg = getSpatialGroup();
@@ -695,19 +700,22 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
pos += volume->getRegion()->getOriginAgent();
}
- for (S32 i = 0; i < getNumFaces(); i++)
+ if (isState(LLDrawable::HAS_ALPHA))
{
- LLFace* facep = getFace(i);
- if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)
+ for (S32 i = 0; i < getNumFaces(); i++)
{
- LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f;
- LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
- LLVector3 at = camera.getAtAxis();
- for (U32 j = 0; j < 3; j++)
+ LLFace* facep = getFace(i);
+ if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)
{
- v.mV[j] -= box.mV[j] * at.mV[j];
+ LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f;
+ LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
+ const LLVector3& at = camera.getAtAxis();
+ for (U32 j = 0; j < 3; j++)
+ {
+ v.mV[j] -= box.mV[j] * at.mV[j];
+ }
+ facep->mDistance = v * camera.getAtAxis();
}
- facep->mDistance = v * camera.getAtAxis();
}
}
}
@@ -1002,8 +1010,8 @@ BOOL LLDrawable::isVisible() const
// Spatial Partition Bridging Drawable
//=======================================
-LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask)
-: LLSpatialPartition(data_mask, FALSE)
+LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)
+: LLSpatialPartition(data_mask, render_by_group, FALSE)
{
mDrawable = root;
root->setSpatialBridge(this);
@@ -1241,7 +1249,9 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
(camera_in.AABBInFrustumNoFarClip(center, size) &&
AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist)))
{
- if (!LLPipeline::sImpostorRender && LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
+ if (!LLPipeline::sImpostorRender &&
+ !LLPipeline::sShadowRender &&
+ LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
{
return;
}
@@ -1280,12 +1290,25 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update)
return;
}
- LLCamera camera = transformCamera(camera_in);
-
- mDrawable->updateDistance(camera, force_update);
-
if (mDrawable->getVObj())
{
+ if (mDrawable->getVObj()->isAttachment())
+ {
+ LLDrawable* parent = mDrawable->getParent();
+ if (parent && parent->getVObj())
+ {
+ LLVOAvatar* av = parent->getVObj()->asAvatar();
+ if (av && av->isImpostor())
+ {
+ return;
+ }
+ }
+ }
+
+ LLCamera camera = transformCamera(camera_in);
+
+ mDrawable->updateDistance(camera, force_update);
+
LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); iter++)
@@ -1427,9 +1450,8 @@ void LLDrawable::updateFaceSize(S32 idx)
}
LLBridgePartition::LLBridgePartition()
-: LLSpatialPartition(0, TRUE)
+: LLSpatialPartition(0, FALSE, 0)
{
- mRenderByGroup = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
mLODPeriod = 16;
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index c765980c30..986440397b 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -264,7 +264,8 @@ public:
BUILT = 0x08000000,
FORCE_INVISIBLE = 0x10000000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned)
CLEAR_INVISIBLE = 0x20000000, // clear FORCE_INVISIBLE next draw frame
- REBUILD_SHADOW = 0x40000000
+ REBUILD_SHADOW = 0x40000000,
+ HAS_ALPHA = 0x80000000,
} EDrawableFlags;
LLXformMatrix mXform;
@@ -299,7 +300,7 @@ private:
LLVector3d mPositionGroup;
F64 mBinRadius;
S32 mGeneration;
-
+
LLVector3 mCurrentScale;
static U32 sCurVisible; // Counter for what value of mVisible means currently visible
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 3a064a4e7d..976f02eeb7 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -279,7 +279,7 @@ S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage)
iter != face_list.end(); iter++)
{
LLFace *facep = *iter;
- gGL.getTexUnit(stage)->bind(facep->getTexture()) ;
+ gGL.getTexUnit(stage)->bind(facep->getTexture());
gGL.getTexUnit(0)->activate();
res += facep->renderIndexed();
}
@@ -474,14 +474,17 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
{
if (params.mTexture.notNull())
{
- gGL.getTexUnit(0)->bind(params.mTexture) ;
+ gGL.getTexUnit(0)->bind(params.mTexture.get());
if (params.mTextureMatrix)
{
glMatrixMode(GL_TEXTURE);
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
gPipeline.mTextureMatrixOps++;
}
- params.mTexture->addTextureStats(params.mVSize);
+ if(params.mTexture.notNull())//will be removed.
+ {
+ params.mTexture->addTextureStats(params.mVSize);
+ }
}
else
{
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 966de41df3..67870c10e9 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -61,12 +61,17 @@ public:
POOL_GRASS,
POOL_FULLBRIGHT,
POOL_BUMP,
- POOL_INVISIBLE,
+ POOL_INVISIBLE, // see below *
POOL_AVATAR,
POOL_WATER,
POOL_GLOW,
POOL_ALPHA,
NUM_POOL_TYPES,
+ // * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them
+ // - and the LLDrawPool types enum controls what order things are rendered in
+ // - so, it has absolute control over what invisprims block
+ // ...invisiprims being rendered in pool_invisible
+ // ...shiny/bump mapped objects in rendered in POOL_BUMP
};
LLDrawPool(const U32 type);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 88f79fc1b9..a5a29dea7b 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -87,22 +87,23 @@ void LLDrawPoolAlpha::beginDeferredPass(S32 pass)
void LLDrawPoolAlpha::endDeferredPass(S32 pass)
{
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f);
+
+}
+
+void LLDrawPoolAlpha::renderDeferred(S32 pass)
+{
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
{
LLFastTimer t(FTM_RENDER_GRASS);
gDeferredTreeProgram.bind();
LLGLEnable test(GL_ALPHA_TEST);
//render alpha masked objects
LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask());
+ gDeferredTreeProgram.unbind();
}
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
-void LLDrawPoolAlpha::renderDeferred(S32 pass)
-{
-
-}
-
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
{
@@ -260,6 +261,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
{
BOOL initialized_lighting = FALSE;
BOOL light_enabled = TRUE;
+ S32 diffuse_channel = 0;
+
//BOOL is_particle = FALSE;
BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders())
|| gPipeline.canUseWindLightShadersOnObjects();
@@ -290,19 +293,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
LLRenderPass::applyModelMatrix(params);
- if (params.mTexture.notNull())
- {
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->bind(params.mTexture) ;
- params.mTexture->addTextureStats(params.mVSize);
- if (params.mTextureMatrix)
- {
- glMatrixMode(GL_TEXTURE);
- glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
- }
- }
-
if (params.mFullbright)
{
// Turn off lighting if it hasn't already been so.
@@ -343,11 +333,13 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
if (deferred_render && current_shader != NULL)
{
gPipeline.unbindDeferredShader(*current_shader);
+ diffuse_channel = 0;
}
current_shader = target_shader;
if (deferred_render)
{
gPipeline.bindDeferredShader(*current_shader);
+ diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
else
{
@@ -356,11 +348,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
else if (!use_shaders && current_shader != NULL)
{
- LLGLSLShader::bindNoShader();
if (deferred_render)
{
gPipeline.unbindDeferredShader(*current_shader);
+ diffuse_channel = 0;
}
+ LLGLSLShader::bindNoShader();
current_shader = NULL;
}
@@ -368,6 +361,24 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
{
params.mGroup->rebuildMesh();
}
+
+
+ if (params.mTexture.notNull())
+ {
+ gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
+ if(params.mTexture.notNull())
+ {
+ params.mTexture->addTextureStats(params.mVSize);
+ }
+ if (params.mTextureMatrix)
+ {
+ gGL.getTexUnit(0)->activate();
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
+ }
+
params.mVertexBuffer->setBuffer(mask);
params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount/3);
@@ -382,6 +393,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
}
+ if (deferred_render && current_shader != NULL)
+ {
+ gPipeline.unbindDeferredShader(*current_shader);
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ }
+
if (!light_enabled)
{
gPipeline.enableLightsDynamic();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 565f906a3b..546b60f286 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -92,6 +92,7 @@ BOOL gAvatarEmbossBumpMap = FALSE;
static BOOL sRenderingSkinned = FALSE;
S32 normal_channel = -1;
S32 specular_channel = -1;
+S32 diffuse_channel = -1;
static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow");
@@ -388,6 +389,7 @@ void LLDrawPoolAvatar::beginFootShadow()
}
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ diffuse_channel = 0;
}
void LLDrawPoolAvatar::endFootShadow()
@@ -440,7 +442,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
-
+ diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
sVertexProgram->bind();
}
@@ -449,6 +452,7 @@ void LLDrawPoolAvatar::endDeferredImpostor()
sShaderLevel = mVertexShaderLevel;
sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
+ sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
sVertexProgram->unbind();
gGL.getTexUnit(0)->activate();
}
@@ -685,7 +689,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
avatarp->mImpostor.bindTexture(1, specular_channel);
}
}
- avatarp->renderImpostor();
+ avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel);
}
else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred)
{
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 331ba67d36..f581f2c402 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -572,6 +572,8 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
LLViewerTexture* bump = NULL;
U8 bump_code = params.mBump;
+
+ //Note: texture atlas does not support bump texture now.
LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ;
if(!tex)
{
@@ -831,7 +833,7 @@ void LLBumpImageList::updateImages()
if( image )
{
BOOL destroy = TRUE;
- if( image->hasValidGLTexture())
+ if( image->hasGLTexture())
{
if( image->getBoundRecently() )
{
@@ -858,7 +860,7 @@ void LLBumpImageList::updateImages()
if( image )
{
BOOL destroy = TRUE;
- if( image->hasValidGLTexture())
+ if( image->hasGLTexture())
{
if( image->getBoundRecently() )
{
@@ -963,7 +965,7 @@ void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTextu
LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4);
generateNormalMapFromAlpha(src, nrm_image);
src_vi->setExplicitFormat(GL_RGBA, GL_RGBA);
- src_vi->createGLTexture(0, nrm_image);
+ src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image);
}
}
@@ -1147,14 +1149,14 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
if (!LLPipeline::sRenderDeferred)
{
bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
- bump->createGLTexture(0, dst_image);
+ bump->createGLTexture(bump->getDiscardLevel(), dst_image);
}
else
{
LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4);
generateNormalMapFromAlpha(src, nrm_image);
bump->setExplicitFormat(GL_RGBA, GL_RGBA);
- bump->createGLTexture(0, nrm_image);
+ bump->createGLTexture(bump->getDiscardLevel(), nrm_image);
}
@@ -1216,7 +1218,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
if (params.mTexture.notNull())
{
gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
- params.mTexture->addTextureStats(params.mVSize);
+ params.mTexture->addTextureStats(params.mVSize);
}
else
{
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 331536fdca..ca7a1b47c2 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -47,6 +47,9 @@
static LLGLSLShader* simple_shader = NULL;
static LLGLSLShader* fullbright_shader = NULL;
+static LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple");
+static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass");
+
void LLDrawPoolGlow::render(S32 pass)
{
LLFastTimer t(FTM_RENDER_GLOW);
@@ -156,13 +159,13 @@ void LLDrawPoolSimple::render(S32 pass)
void LLDrawPoolSimple::beginDeferredPass(S32 pass)
{
- LLFastTimer t(FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
gDeferredDiffuseProgram.bind();
}
void LLDrawPoolSimple::endDeferredPass(S32 pass)
{
- LLFastTimer t(FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
LLRenderPass::endRenderPass(pass);
gDeferredDiffuseProgram.unbind();
@@ -174,7 +177,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass)
LLGLDisable alpha_test(GL_ALPHA_TEST);
{ //render simple
- LLFastTimer t(FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
}
}
@@ -258,10 +261,10 @@ void LLDrawPoolGrass::endDeferredPass(S32 pass)
void LLDrawPoolGrass::renderDeferred(S32 pass)
{
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
{
- LLFastTimer t(FTM_RENDER_GRASS);
+ LLFastTimer t(FTM_RENDER_GRASS_DEFERRED);
gDeferredTreeProgram.bind();
LLGLEnable test(GL_ALPHA_TEST);
//render grass
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 345dd6bb84..790e75cfaa 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -77,7 +77,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
GL_ALPHA8, GL_ALPHA,
LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb"));
- gGL.getTexUnit(0)->bind(mAlphaRampImagep);
+ //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get());
mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c",
@@ -86,12 +86,12 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
GL_ALPHA8, GL_ALPHA,
LLUUID("38b86f85-2575-52a9-a531-23108d8da837"));
- gGL.getTexUnit(0)->bind(m2DAlphaRampImagep);
+ //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
mTexturep->setBoostLevel(LLViewerTexture::BOOST_TERRAIN);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
LLDrawPoolTerrain::~LLDrawPoolTerrain()
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 5cb1fcb635..8d2cbc583c 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -52,7 +52,6 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) :
LLFacePool(POOL_TREE),
mTexturep(texturep)
{
- gGL.getTexUnit(0)->bind(mTexturep);
mTexturep->setAddressMode(LLTexUnit::TAM_WRAP);
}
@@ -138,7 +137,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass)
void LLDrawPoolTree::beginDeferredPass(S32 pass)
{
LLFastTimer t(FTM_RENDER_TREES);
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
shader = &gDeferredTreeProgram;
shader->bind();
@@ -164,6 +163,9 @@ void LLDrawPoolTree::beginShadowPass(S32 pass)
{
LLFastTimer t(FTM_SHADOW_TREE);
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"),
+ gSavedSettings.getF32("RenderDeferredTreeShadowBias"));
+
gDeferredShadowProgram.bind();
}
@@ -176,7 +178,11 @@ void LLDrawPoolTree::endShadowPass(S32 pass)
{
LLFastTimer t(FTM_SHADOW_TREE);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
- gDeferredShadowProgram.unbind();
+
+ glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"),
+ gSavedSettings.getF32("RenderDeferredSpotShadowBias"));
+
+ //gDeferredShadowProgram.unbind();
}
@@ -247,7 +253,7 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
LLGLState normalize(GL_NORMALIZE, TRUE);
// Bind the texture for this tree.
- gGL.getTexUnit(sDiffTex)->bind(mTexturep);
+ gGL.getTexUnit(sDiffTex)->bind(mTexturep.get());
U32 indices_drawn = 0;
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index fd4dc123d5..f56359afc3 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -136,6 +136,19 @@ void LLDrawPoolWater::endPostDeferredPass(S32 pass)
deferred_render = FALSE;
}
+//===============================
+//DEFERRED IMPLEMENTATION
+//===============================
+void LLDrawPoolWater::renderDeferred(S32 pass)
+{
+ LLFastTimer t(FTM_RENDER_WATER);
+ deferred_render = TRUE;
+ shade();
+ deferred_render = FALSE;
+}
+
+//=========================================
+
void LLDrawPoolWater::render(S32 pass)
{
LLFastTimer ftm(FTM_RENDER_WATER);
@@ -337,7 +350,10 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
void LLDrawPoolWater::shade()
{
- gGL.setColorMask(true, true);
+ if (!deferred_render)
+ {
+ gGL.setColorMask(true, true);
+ }
LLVOSky *voskyp = gSky.mVOSkyp;
@@ -400,6 +416,15 @@ void LLDrawPoolWater::shade()
shader = &gWaterProgram;
}
+ if (deferred_render)
+ {
+ gPipeline.bindDeferredShader(*shader);
+ }
+ else
+ {
+ shader->bind();
+ }
+
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX);
@@ -435,15 +460,6 @@ void LLDrawPoolWater::shade()
S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX);
- if (deferred_render)
- {
- gPipeline.bindDeferredShader(*shader);
- }
- else
- {
- shader->bind();
- }
-
if (screentex > -1)
{
shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
@@ -547,8 +563,15 @@ void LLDrawPoolWater::shade()
{ //smash background faces to far clip plane
if (water->getIsEdgePatch())
{
- LLGLClampToFarClip far_clip(glh_get_current_projection());
- face->renderIndexed();
+ if (deferred_render)
+ {
+ face->renderIndexed();
+ }
+ else
+ {
+ LLGLClampToFarClip far_clip(glh_get_current_projection());
+ face->renderIndexed();
+ }
}
else
{
@@ -577,7 +600,10 @@ void LLDrawPoolWater::shade()
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- gGL.setColorMask(true, false);
+ if (!deferred_render)
+ {
+ gGL.setColorMask(true, false);
+ }
}
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index e28ac1cfab..68a8172dd0 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -71,10 +71,12 @@ public:
/*virtual*/ LLDrawPool *instancePool();
static void restoreGL();
- /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); }
+ /*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); }
/*virtual*/ void beginPostDeferredPass(S32 pass);
/*virtual*/ void endPostDeferredPass(S32 pass);
/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+ /*virtual*/ S32 getNumDeferredPasses() { return 1; }
+ /*virtual*/ void renderDeferred(S32 pass = 0);
/*virtual*/ S32 getNumPasses();
/*virtual*/ void render(S32 pass = 0);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index bef9e40c49..8aea7422fc 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -174,6 +174,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mLastGeomIndex = mGeomIndex;
mLastIndicesCount = mIndicesCount;
mLastIndicesIndex = mIndicesIndex;
+
+ mAtlasInfop = NULL ;
+ mUsingAtlas = FALSE ;
}
@@ -200,12 +203,14 @@ void LLFace::destroy()
if (group)
{
group->dirtyGeom();
+ gPipeline.markRebuild(group, TRUE);
}
}
}
setDrawInfo(NULL);
+ removeAtlas();
mDrawablep = NULL;
mVObjp = NULL;
}
@@ -264,6 +269,7 @@ void LLFace::setTexture(LLViewerTexture* tex)
if(mTexture.notNull())
{
mTexture->removeFace(this) ;
+ removeAtlas() ;
}
mTexture = tex ;
@@ -447,8 +453,15 @@ void LLFace::renderForSelect(U32 data_mask)
void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
{
- if(mDrawablep.isNull() || mVertexBuffer.isNull() || mDrawablep->getSpatialGroup() == NULL ||
- mDrawablep->getSpatialGroup()->isState(LLSpatialGroup::GEOM_DIRTY))
+ if (mDrawablep->getSpatialGroup() == NULL)
+ {
+ return;
+ }
+
+ mDrawablep->getSpatialGroup()->rebuildGeom();
+ mDrawablep->getSpatialGroup()->rebuildMesh();
+
+ if(mDrawablep.isNull() || mVertexBuffer.isNull())
{
return;
}
@@ -467,17 +480,10 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix);
}
- setFaceColor(color);
- renderSetColor();
-
+ glColor4fv(color.mV);
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
-#if !LL_RELEASE_FOR_DOWNLOAD
- LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
-#endif
mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
- unsetFaceColor();
- unsetFaceColor();
gGL.popMatrix();
}
}
@@ -888,6 +894,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
}
+
+ F32 tcoord_xoffset = 0.f ;
+ F32 tcoord_yoffset = 0.f ;
+ F32 tcoord_xscale = 1.f ;
+ F32 tcoord_yscale = 1.f ;
+ BOOL in_atlas = FALSE ;
+
if (rebuild_tcoord)
{
mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
@@ -895,6 +908,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
}
+
+ in_atlas = isAtlasInUse() ;
+ if(in_atlas)
+ {
+ const LLVector2* tmp = getTexCoordOffset() ;
+ tcoord_xoffset = tmp->mV[0] ;
+ tcoord_yoffset = tmp->mV[1] ;
+
+ tmp = getTexCoordScale() ;
+ tcoord_xscale = tmp->mV[0] ;
+ tcoord_yscale = tmp->mV[1] ;
+ }
}
if (rebuild_color)
{
@@ -1021,7 +1046,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
break;
case BE_BRIGHTNESS:
case BE_DARKNESS:
- if( mTexture.notNull() && mTexture->hasValidGLTexture())
+ if( mTexture.notNull() && mTexture->hasGLTexture())
{
// Offset by approximately one texel
S32 cur_discard = mTexture->getDiscardLevel();
@@ -1104,6 +1129,93 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
}
+ if(in_atlas)
+ {
+ //
+ //manually calculate tex-coord per vertex for varying address modes.
+ //should be removed if shader can handle this.
+ //
+
+ S32 int_part = 0 ;
+ switch(mTexture->getAddressMode())
+ {
+ case LLTexUnit::TAM_CLAMP:
+ if(tc.mV[0] < 0.f)
+ {
+ tc.mV[0] = 0.f ;
+ }
+ else if(tc.mV[0] > 1.f)
+ {
+ tc.mV[0] = 1.f;
+ }
+
+ if(tc.mV[1] < 0.f)
+ {
+ tc.mV[1] = 0.f ;
+ }
+ else if(tc.mV[1] > 1.f)
+ {
+ tc.mV[1] = 1.f;
+ }
+ break;
+ case LLTexUnit::TAM_MIRROR:
+ if(tc.mV[0] < 0.f)
+ {
+ tc.mV[0] = -tc.mV[0] ;
+ }
+ int_part = (S32)tc.mV[0] ;
+ if(int_part & 1) //odd number
+ {
+ tc.mV[0] = int_part + 1 - tc.mV[0] ;
+ }
+ else //even number
+ {
+ tc.mV[0] -= int_part ;
+ }
+
+ if(tc.mV[1] < 0.f)
+ {
+ tc.mV[1] = -tc.mV[1] ;
+ }
+ int_part = (S32)tc.mV[1] ;
+ if(int_part & 1) //odd number
+ {
+ tc.mV[1] = int_part + 1 - tc.mV[1] ;
+ }
+ else //even number
+ {
+ tc.mV[1] -= int_part ;
+ }
+ break;
+ case LLTexUnit::TAM_WRAP:
+ if(tc.mV[0] > 1.f)
+ tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ;
+ else if(tc.mV[0] < -1.f)
+ tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ;
+
+ if(tc.mV[1] > 1.f)
+ tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ;
+ else if(tc.mV[1] < -1.f)
+ tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ;
+
+ if(tc.mV[0] < 0.f)
+ {
+ tc.mV[0] = 1.0f + tc.mV[0] ;
+ }
+ if(tc.mV[1] < 0.f)
+ {
+ tc.mV[1] = 1.0f + tc.mV[1] ;
+ }
+ break;
+ default:
+ break;
+ }
+
+ tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ;
+ tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ;
+ }
+
+
*tex_coords++ = tc;
if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
@@ -1358,3 +1470,156 @@ LLVector3 LLFace::getPositionAgent() const
return mCenterLocal * getRenderMatrix();
}
}
+
+//
+//atlas
+//
+void LLFace::removeAtlas()
+{
+ setAtlasInUse(FALSE) ;
+ mAtlasInfop = NULL ;
+}
+
+const LLTextureAtlas* LLFace::getAtlas()const
+{
+ if(mAtlasInfop)
+ {
+ return mAtlasInfop->getAtlas() ;
+ }
+ return NULL ;
+}
+
+const LLVector2* LLFace::getTexCoordOffset()const
+{
+ if(isAtlasInUse())
+ {
+ return mAtlasInfop->getTexCoordOffset() ;
+ }
+ return NULL ;
+}
+const LLVector2* LLFace::getTexCoordScale() const
+{
+ if(isAtlasInUse())
+ {
+ return mAtlasInfop->getTexCoordScale() ;
+ }
+ return NULL ;
+}
+
+BOOL LLFace::isAtlasInUse()const
+{
+ return mUsingAtlas ;
+}
+
+BOOL LLFace::canUseAtlas()const
+{
+ //no drawable or no spatial group, do not use atlas
+ if(!mDrawablep || !mDrawablep->getSpatialGroup())
+ {
+ return FALSE ;
+ }
+
+ //if bump face, do not use atlas
+ if(getTextureEntry() && getTextureEntry()->getBumpmap())
+ {
+ return FALSE ;
+ }
+
+ //if animated texture, do not use atlas
+ if(isState(TEXTURE_ANIM))
+ {
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+void LLFace::setAtlasInUse(BOOL flag)
+{
+ //no valid atlas to use.
+ if(flag && (!mAtlasInfop || !mAtlasInfop->isValid()))
+ {
+ flag = FALSE ;
+ }
+
+ if(!flag && !mUsingAtlas)
+ {
+ return ;
+ }
+
+ //
+ //at this stage (flag || mUsingAtlas) is always true.
+ //
+
+ //rebuild the tex coords
+ if(mDrawablep)
+ {
+ gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_TCOORD);
+ mUsingAtlas = flag ;
+ }
+ else
+ {
+ mUsingAtlas = FALSE ;
+ }
+}
+
+LLTextureAtlasSlot* LLFace::getAtlasInfo()
+{
+ return mAtlasInfop ;
+}
+
+void LLFace::setAtlasInfo(LLTextureAtlasSlot* atlasp)
+{
+ if(mAtlasInfop != atlasp)
+ {
+ if(mAtlasInfop)
+ {
+ //llerrs << "Atlas slot changed!" << llendl ;
+ }
+ mAtlasInfop = atlasp ;
+ }
+}
+
+LLViewerTexture* LLFace::getTexture() const
+{
+ if(isAtlasInUse())
+ {
+ return (LLViewerTexture*)mAtlasInfop->getAtlas() ;
+ }
+
+ return mTexture ;
+}
+
+//switch to atlas or switch back to gl texture
+//return TRUE if using atlas.
+BOOL LLFace::switchTexture()
+{
+ //no valid atlas or texture
+ if(!mAtlasInfop || !mAtlasInfop->isValid() || !mTexture)
+ {
+ return FALSE ;
+ }
+
+ if(mTexture->getTexelsInAtlas() >= (U32)mVSize ||
+ mTexture->getTexelsInAtlas() >= mTexture->getTexelsInGLTexture())
+ {
+ //switch to use atlas
+ //atlas resolution is qualified, use it.
+ if(!mUsingAtlas)
+ {
+ setAtlasInUse(TRUE) ;
+ }
+ }
+ else //if atlas not qualified.
+ {
+ //switch back to GL texture
+ if(mUsingAtlas && mTexture->isGLTextureCreated() &&
+ mTexture->getDiscardLevel() < mTexture->getDiscardLevelInAtlas())
+ {
+ setAtlasInUse(FALSE) ;
+ }
+ }
+
+ return mUsingAtlas ;
+}
+
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index e0728fe15e..cafad5706c 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -47,6 +47,7 @@
#include "llvertexbuffer.h"
#include "llviewertexture.h"
#include "lldrawable.h"
+#include "lltextureatlasmanager.h"
class LLFacePool;
class LLVolume;
@@ -55,6 +56,7 @@ class LLTextureEntry;
class LLVertexProgram;
class LLViewerTexture;
class LLGeometryManager;
+class LLTextureAtlasSlot;
const F32 MIN_ALPHA_SIZE = 1024.f;
const F32 MIN_TEX_ANIM_SIZE = 512.f;
@@ -86,7 +88,6 @@ public:
U16 getGeomCount() const { return mGeomCount; } // vertex count for this face
U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool
U16 getGeomStart() const { return mGeomIndex; } // index into draw pool
- LLViewerTexture* getTexture() const { return mTexture; }
void setTexture(LLViewerTexture* tex) ;
LLXformMatrix* getXform() const { return mXform; }
BOOL hasGeometry() const { return mGeomCount > 0; }
@@ -119,7 +120,7 @@ public:
LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
void setPoolType(U32 type) { mPoolType = type; }
S32 getTEOffset() { return mTEOffset; }
- LLViewerTexture* getTexture() { return mTexture; }
+ LLViewerTexture* getTexture() const;
void setViewerObject(LLViewerObject* object);
void setPool(LLFacePool *pool, LLViewerTexture *texturep);
@@ -185,7 +186,17 @@ public:
void setIndicesIndex(S32 idx) { mIndicesIndex = idx; }
void setDrawInfo(LLDrawInfo* draw_info);
-protected:
+ //for atlas
+ LLTextureAtlasSlot* getAtlasInfo() ;
+ void setAtlasInUse(BOOL flag);
+ void setAtlasInfo(LLTextureAtlasSlot* atlasp);
+ BOOL isAtlasInUse()const;
+ BOOL canUseAtlas() const;
+ const LLVector2* getTexCoordScale() const ;
+ const LLVector2* getTexCoordOffset()const;
+ const LLTextureAtlas* getAtlas()const ;
+ void removeAtlas() ;
+ BOOL switchTexture() ;
public:
@@ -230,6 +241,10 @@ protected:
S32 mReferenceIndex;
F32 mVSize;
F32 mPixelArea;
+
+ //atlas
+ LLPointer<LLTextureAtlasSlot> mAtlasInfop ;
+ BOOL mUsingAtlas ;
protected:
static BOOL sSafeRenderSelect;
@@ -258,7 +273,7 @@ public:
const LLTextureEntry* lte = lhs->getTextureEntry();
const LLTextureEntry* rte = rhs->getTextureEntry();
- if (lhs->getTexture() != rhs->getTexture())
+ if(lhs->getTexture() != rhs->getTexture())
{
return lhs->getTexture() < rhs->getTexture();
}
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index a27070de39..fbc0ff3cf5 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -148,11 +148,11 @@ void LLFloaterPostcard::draw()
F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight();
if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
{
- rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
+ rect.mRight = LLRect::tCoordType((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
}
else
{
- rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
+ rect.mBottom = LLRect::tCoordType((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
}
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp
index 616e9bac35..8979575ef7 100644
--- a/indra/newview/llfloatersettingsdebug.cpp
+++ b/indra/newview/llfloatersettingsdebug.cpp
@@ -111,6 +111,11 @@ void LLFloaterSettingsDebug::onCommitSettings()
LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
+ if (!controlp)
+ {
+ return;
+ }
+
LLVector3 vector;
LLVector3d vectord;
LLRect rect;
diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp
index 18745284cb..02979acdd7 100644
--- a/indra/newview/llfloaterwindlight.cpp
+++ b/indra/newview/llfloaterwindlight.cpp
@@ -59,6 +59,8 @@
#include "llwlparamset.h"
#include "llwlparammanager.h"
#include "llpostprocess.h"
+#include "lltabcontainer.h"
+
#undef max
@@ -434,6 +436,11 @@ void LLFloaterWindLight::syncMenu()
childSetValue("WLGamma", param_mgr->mWLGamma.x);
childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness());
+
+ LLTabContainer* tab = getChild<LLTabContainer>("WindLight Tabs");
+ LLPanel* panel = getChild<LLPanel>("Scattering");
+
+ tab->enableTabButton(tab->getIndexForPanel(panel), gSavedSettings.getBOOL("RenderDeferredGI"));
}
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 8086400493..55019f91f8 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -1063,6 +1063,8 @@ void LLHUDText::renderAllHUD()
LLVertexBuffer::unbind();
+ LLVertexBuffer::unbind();
+
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index 3d1d6cad74..f62d7229a3 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -85,6 +85,7 @@ void LLManip::rebuild(LLViewerObject* vobj)
if (group)
{
group->dirtyGeom();
+ gPipeline.markRebuild(group, TRUE);
}
}
}
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index ce16b95bc0..4ac109bf3d 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -52,6 +52,7 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcolorswatch.h"
+#include "lltexturectrl.h"
#include "llcombobox.h"
#include "llfirstuse.h"
#include "llfocusmgr.h"
@@ -72,6 +73,7 @@
#include "llvovolume.h"
#include "llworld.h"
#include "pipeline.h"
+#include "llviewershadermgr.h"
#include "lldrawpool.h"
#include "lluictrlfactory.h"
@@ -110,12 +112,28 @@ BOOL LLPanelVolume::postBuild()
LightColorSwatch->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectColor, this, _2));
childSetCommitCallback("colorswatch",onCommitLight,this);
}
+
+ LLTextureCtrl* LightTexPicker = getChild<LLTextureCtrl>("light texture control");
+ if (LightTexPicker)
+ {
+ LightTexPicker->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelTexture, this, _2));
+ LightTexPicker->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectTexture, this, _2));
+ childSetCommitCallback("light texture control", onCommitLight, this);
+ }
+
childSetCommitCallback("Light Intensity",onCommitLight,this);
childSetValidate("Light Intensity",precommitValidate);
childSetCommitCallback("Light Radius",onCommitLight,this);
childSetValidate("Light Radius",precommitValidate);
childSetCommitCallback("Light Falloff",onCommitLight,this);
childSetValidate("Light Falloff",precommitValidate);
+
+ childSetCommitCallback("Light FOV", onCommitLight, this);
+ childSetValidate("Light FOV", precommitValidate);
+ childSetCommitCallback("Light Focus", onCommitLight, this);
+ childSetValidate("Light Focus", precommitValidate);
+ childSetCommitCallback("Light Ambiance", onCommitLight, this);
+ childSetValidate("Light Ambiance", precommitValidate);
}
// Start with everyone disabled
@@ -220,14 +238,32 @@ void LLPanelVolume::getState( )
LightColorSwatch->setValid( TRUE );
LightColorSwatch->set(volobjp->getLightBaseColor());
}
+
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if (LightTextureCtrl)
+ {
+ LightTextureCtrl->setEnabled(TRUE);
+ LightTextureCtrl->setValid(TRUE);
+ LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID());
+ }
+
childSetEnabled("Light Intensity",true);
childSetEnabled("Light Radius",true);
childSetEnabled("Light Falloff",true);
+ childSetEnabled("Light FOV", true);
+ childSetEnabled("Light Focus", true);
+ childSetEnabled("Light Ambiance", true);
+
childSetValue("Light Intensity",volobjp->getLightIntensity());
childSetValue("Light Radius",volobjp->getLightRadius());
childSetValue("Light Falloff",volobjp->getLightFalloff());
+ LLVector3 params = volobjp->getSpotLightParams();
+ childSetValue("Light FOV", params.mV[0]);
+ childSetValue("Light Focus", params.mV[1]);
+ childSetValue("Light Ambiance", params.mV[2]);
+
mLightSavedColor = volobjp->getLightColor();
}
else
@@ -243,9 +279,20 @@ void LLPanelVolume::getState( )
LightColorSwatch->setEnabled( FALSE );
LightColorSwatch->setValid( FALSE );
}
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if (LightTextureCtrl)
+ {
+ LightTextureCtrl->setEnabled(FALSE);
+ LightTextureCtrl->setValid(FALSE);
+ }
+
childSetEnabled("Light Intensity",false);
childSetEnabled("Light Radius",false);
childSetEnabled("Light Falloff",false);
+
+ childSetEnabled("Light FOV",false);
+ childSetEnabled("Light Focus",false);
+ childSetEnabled("Light Ambiance",false);
}
// Flexible properties
@@ -335,6 +382,15 @@ void LLPanelVolume::refresh()
{
mRootObject = NULL;
}
+
+ BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
+
+ childSetVisible("label texture", visible);
+ childSetVisible("Light FOV", visible);
+ childSetVisible("Light Focus", visible);
+ childSetVisible("Light Ambiance", visible);
+ childSetVisible("light texture control", visible);
+
}
@@ -361,6 +417,13 @@ void LLPanelVolume::clearCtrls()
LightColorSwatch->setEnabled( FALSE );
LightColorSwatch->setValid( FALSE );
}
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if(LightTextureCtrl)
+ {
+ LightTextureCtrl->setEnabled( FALSE );
+ LightTextureCtrl->setValid( FALSE );
+ }
+
childSetEnabled("Light Intensity",false);
childSetEnabled("Light Radius",false);
childSetEnabled("Light Falloff",false);
@@ -436,6 +499,15 @@ void LLPanelVolume::onLightCancelColor(const LLSD& data)
onLightSelectColor(data);
}
+void LLPanelVolume::onLightCancelTexture(const LLSD& data)
+{
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if (LightTextureCtrl)
+ {
+ LightTextureCtrl->setImageAssetID(mLightSavedTexture);
+ }
+}
+
void LLPanelVolume::onLightSelectColor(const LLSD& data)
{
LLViewerObject* objectp = mObject;
@@ -456,6 +528,24 @@ void LLPanelVolume::onLightSelectColor(const LLSD& data)
}
}
+void LLPanelVolume::onLightSelectTexture(const LLSD& data)
+{
+ if (mObject.isNull() || (mObject->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume *volobjp = (LLVOVolume *) mObject.get();
+
+
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if(LightTextureCtrl)
+ {
+ LLUUID id = LightTextureCtrl->getImageAssetID();
+ volobjp->setLightTextureID(id);
+ mLightSavedTexture = id;
+ }
+}
+
// static
void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
{
@@ -471,12 +561,47 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
volobjp->setLightIntensity((F32)self->childGetValue("Light Intensity").asReal());
volobjp->setLightRadius((F32)self->childGetValue("Light Radius").asReal());
volobjp->setLightFalloff((F32)self->childGetValue("Light Falloff").asReal());
+
LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LLColor4 clr = LightColorSwatch->get();
volobjp->setLightColor(LLColor3(clr));
}
+
+ LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control");
+ if(LightTextureCtrl)
+ {
+ LLUUID id = LightTextureCtrl->getImageAssetID();
+ if (id.notNull())
+ {
+ if (volobjp->getLightTextureID().isNull())
+ { //this commit is making this a spot light, set UI to default params
+ volobjp->setLightTextureID(id);
+ LLVector3 spot_params = volobjp->getSpotLightParams();
+ self->childSetValue("Light FOV", spot_params.mV[0]);
+ self->childSetValue("Light Focus", spot_params.mV[1]);
+ self->childSetValue("Light Ambiance", spot_params.mV[2]);
+ }
+ else
+ { //modifying existing params
+ LLVector3 spot_params;
+ spot_params.mV[0] = (F32) self->childGetValue("Light FOV").asReal();
+ spot_params.mV[1] = (F32) self->childGetValue("Light Focus").asReal();
+ spot_params.mV[2] = (F32) self->childGetValue("Light Ambiance").asReal();
+ volobjp->setSpotLightParams(spot_params);
+ }
+ }
+ else if (volobjp->getLightTextureID().notNull())
+ { //no longer a spot light
+ volobjp->setLightTextureID(id);
+ //self->childDisable("Light FOV");
+ //self->childDisable("Light Focus");
+ //self->childDisable("Light Ambiance");
+ }
+ }
+
+
}
// static
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index f285141bbe..9d197aafa5 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -74,6 +74,10 @@ public:
void onLightCancelColor(const LLSD& data);
void onLightSelectColor(const LLSD& data);
+ void onLightCancelTexture(const LLSD& data);
+ void onLightSelectTexture(const LLSD& data);
+
+
protected:
void getState();
@@ -99,6 +103,7 @@ protected:
*/
LLColor4 mLightSavedColor;
+ LLUUID mLightSavedTexture;
LLPointer<LLViewerObject> mObject;
LLPointer<LLViewerObject> mRootObject;
};
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index dea9af0657..8a052b61db 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -47,6 +47,7 @@
#include "llrender.h"
#include "lloctree.h"
#include "llvoavatar.h"
+#include "lltextureatlas.h"
static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
@@ -88,8 +89,6 @@ protected:
static LLOcclusionQueryPool sQueryPool;
-BOOL LLSpatialPartition::sFreezeState = FALSE;
-
//static counter for frame to switch LOD on
void sg_assert(BOOL expr)
@@ -283,10 +282,10 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3
LLSpatialGroup::~LLSpatialGroup()
{
- if (sNoDelete)
+ /*if (sNoDelete)
{
llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
- }
+ }*/
if (isState(DEAD))
{
@@ -297,13 +296,136 @@ LLSpatialGroup::~LLSpatialGroup()
if (gGLManager.mHasOcclusionQuery && mOcclusionQuery)
{
- sQueryPool.release(mOcclusionQuery);
+ sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
}
delete [] mOcclusionVerts;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
clearDrawMap();
+ clearAtlasList() ;
+}
+
+BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp)
+{
+ S8 type = atlasp->getComponents() - 1 ;
+ for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
+ {
+ if(atlasp == *iter)
+ {
+ return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
+void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level)
+{
+ if(!hasAtlas(atlasp))
+ {
+ mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ;
+ atlasp->addSpatialGroup(this) ;
+ }
+
+ --recursive_level;
+ if(recursive_level)//levels propagating up.
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ parent->addAtlas(atlasp, recursive_level) ;
+ }
+ }
+}
+
+void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level)
+{
+ mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ;
+ if(remove_group)
+ {
+ atlasp->removeSpatialGroup(this) ;
+ }
+
+ --recursive_level;
+ if(recursive_level)//levels propagating up.
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ parent->removeAtlas(atlasp, recursive_level) ;
+ }
+ }
+}
+
+void LLSpatialGroup::clearAtlasList()
+{
+ std::list<LLTextureAtlas*>::iterator iter ;
+ for(S8 i = 0 ; i < 4 ; i++)
+ {
+ if(mAtlasList[i].size() > 0)
+ {
+ for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter)
+ {
+ ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ;
+ }
+ mAtlasList[i].clear() ;
+ }
+ }
+}
+
+LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level)
+{
+ S8 type = ncomponents - 1 ;
+ if(mAtlasList[type].size() > 0)
+ {
+ for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
+ {
+ if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved))
+ {
+ return *iter ;
+ }
+ }
+ }
+
+ --recursive_level;
+ if(recursive_level)
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ;
+ }
+ }
+ return NULL ;
+}
+
+void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp)
+{
+ mCurUpdatingSlotp = slotp;
+
+ //if(!hasAtlas(mCurUpdatingSlotp->getAtlas()))
+ //{
+ // addAtlas(mCurUpdatingSlotp->getAtlas()) ;
+ //}
+}
+
+LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level)
+{
+ if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep)
+ {
+ return mCurUpdatingSlotp ;
+ }
+
+ //--recursive_level ;
+ //if(recursive_level)
+ //{
+ // LLSpatialGroup* parent = getParent() ;
+ // if(parent)
+ // {
+ // return parent->getCurUpdatingSlot(imagep, recursive_level) ;
+ // }
+ //}
+ return NULL ;
}
void LLSpatialGroup::clearDrawMap()
@@ -313,15 +435,12 @@ void LLSpatialGroup::clearDrawMap()
BOOL LLSpatialGroup::isVisible() const
{
- return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
+ return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
}
void LLSpatialGroup::setVisible()
{
- if (!LLSpatialPartition::sFreezeState)
- {
- mVisible = LLDrawable::getCurrentFrame();
- }
+ mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame();
}
void LLSpatialGroup::validate()
@@ -380,63 +499,6 @@ void LLSpatialGroup::validate()
#endif
}
-
-
-class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
-{
-public:
- U32 mInheritedMask;
-
- LLOctreeStateCheck(): mInheritedMask(0) { }
-
- virtual void traverse(const LLSpatialGroup::OctreeNode* node)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
-
- node->accept(this);
-
- U32 temp = mInheritedMask;
- mInheritedMask |= group->getState() &
- (LLSpatialGroup::OCCLUDED);
-
- for (U32 i = 0; i < node->getChildCount(); i++)
- {
- traverse(node->getChild(i));
- }
-
- mInheritedMask = temp;
- }
-
- virtual void visit(const LLOctreeNode<LLDrawable>* state)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
-
- if (mInheritedMask && !group->isState(mInheritedMask))
- {
- llerrs << "Spatial group failed inherited mask test." << llendl;
- }
-
- if (group->isState(LLSpatialGroup::DIRTY))
- {
- assert_parent_state(group, LLSpatialGroup::DIRTY);
- }
- }
-
- void assert_parent_state(LLSpatialGroup* group, U32 state)
- {
- LLSpatialGroup* parent = group->getParent();
- while (parent)
- {
- if (!parent->isState(state))
- {
- llerrs << "Spatial group failed parent state check." << llendl;
- }
- parent = parent->getParent();
- }
- }
-};
-
-
void LLSpatialGroup::checkStates()
{
#if LL_OCTREE_PARANOIA_CHECK
@@ -470,17 +532,17 @@ void validate_draw_info(LLDrawInfo& params)
}
//bad indices
- U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer();
+ U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer();
if (indicesp)
{
for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++)
{
- if (indicesp[i] < params.mStart)
+ if (indicesp[i] < (U16)params.mStart)
{
llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl;
}
- if (indicesp[i] > params.mEnd)
+ if (indicesp[i] > (U16)params.mEnd)
{
llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl;
}
@@ -541,7 +603,9 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc
{
drawablep->setSpatialGroup(this);
validate_drawable(drawablep);
- setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY);
+ setState(OBJECT_DIRTY | GEOM_DIRTY);
+ setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
+ gPipeline.markRebuild(this, TRUE);
if (drawablep->isSpatialBridge())
{
mBridgeList.push_back((LLSpatialBridge*) drawablep);
@@ -576,22 +640,23 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
{
- if (!gPipeline.hasRenderType(mDrawableType))
+ /*if (!gPipeline.hasRenderType(mDrawableType))
{
return;
- }
-
- if (!LLPipeline::sSkipUpdate && group->changeLOD())
- {
- group->mLastUpdateDistance = group->mDistance;
- group->mLastUpdateViewAngle = group->mViewAngle;
- }
+ }*/
if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
+ /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup)
+ {
+ llerrs << "WTF?" << llendl;
+ }*/
return;
}
+ group->mLastUpdateDistance = group->mDistance;
+ group->mLastUpdateViewAngle = group->mViewAngle;
+
LLFastTimer ftm(FTM_REBUILD_VBO);
group->clearDrawMap();
@@ -629,6 +694,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
group->clearState(LLSpatialGroup::GEOM_DIRTY);
}
+
void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
{
@@ -667,8 +733,11 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
drawablep = *i;
minMax = drawablep->getSpatialExtents();
+ update_min_max(newMin, newMax, minMax[0]);
+ update_min_max(newMin, newMax, minMax[1]);
+
//bin up the object
- for (U32 i = 0; i < 3; i++)
+ /*for (U32 i = 0; i < 3; i++)
{
if (minMax[0].mV[i] < newMin.mV[i])
{
@@ -678,7 +747,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
{
newMax.mV[i] = minMax[1].mV[i];
}
- }
+ }*/
}
mObjectBounds[0] = (newMin + newMax) * 0.5f;
@@ -742,6 +811,10 @@ LLSpatialGroup* LLSpatialGroup::getParent()
return NULL;
}
+ if(!mOctreeNode)
+ {
+ return NULL;
+ }
OctreeNode* parent = mOctreeNode->getOctParent();
if (parent)
@@ -767,6 +840,8 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
{
drawablep->setSpatialGroup(NULL);
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
+
if (drawablep->isSpatialBridge())
{
for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i)
@@ -803,6 +878,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
//if (!mSpatialPartition->mRenderByGroup)
{
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
}
if (mOcclusionVerts)
@@ -843,18 +919,21 @@ public:
void LLSpatialGroup::setState(U32 state)
{
- if (!LLSpatialPartition::sFreezeState)
+ mState |= state;
+
+ if (state > LLSpatialGroup::STATE_MASK)
{
- mState |= state;
+ llerrs << "WTF?" << llendl;
}
}
void LLSpatialGroup::setState(U32 state, S32 mode)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (LLSpatialPartition::sFreezeState)
+
+ if (state > LLSpatialGroup::STATE_MASK)
{
- return;
+ llerrs << "WTF?" << llendl;
}
if (mode > STATE_MODE_SINGLE)
@@ -902,20 +981,23 @@ public:
void LLSpatialGroup::clearState(U32 state)
{
- if (!LLSpatialPartition::sFreezeState)
+ if (state > LLSpatialGroup::STATE_MASK)
{
- mState &= ~state;
+ llerrs << "WTF?" << llendl;
}
+
+ mState &= ~state;
}
void LLSpatialGroup::clearState(U32 state, S32 mode)
{
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (LLSpatialPartition::sFreezeState)
+ if (state > LLSpatialGroup::STATE_MASK)
{
- return;
+ llerrs << "WTF?" << llendl;
}
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
if (mode > STATE_MODE_SINGLE)
{
if (mode == STATE_MODE_DIFF)
@@ -935,6 +1017,128 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
}
}
+BOOL LLSpatialGroup::isState(U32 state) const
+{
+ if (state > LLSpatialGroup::STATE_MASK)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ return mState & state ? TRUE : FALSE;
+}
+
+//=====================================
+// Occlusion State Set/Clear
+//=====================================
+class LLSpatialSetOcclusionState : public LLSpatialGroup::OctreeTraveler
+{
+public:
+ U32 mState;
+ LLSpatialSetOcclusionState(U32 state) : mState(state) { }
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); }
+};
+
+class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState
+{
+public:
+ LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (!group->isOcclusionState(mState))
+ {
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ }
+};
+
+
+void LLSpatialGroup::setOcclusionState(U32 state, S32 mode)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (mode > STATE_MODE_SINGLE)
+ {
+ if (mode == STATE_MODE_DIFF)
+ {
+ LLSpatialSetOcclusionStateDiff setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ else if (mode == STATE_MODE_BRANCH)
+ {
+ LLSpatialSetOcclusionState setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ else
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] |= state;
+ }
+ }
+ }
+ else
+ {
+ mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
+ }
+}
+
+class LLSpatialClearOcclusionState : public LLSpatialGroup::OctreeTraveler
+{
+public:
+ U32 mState;
+
+ LLSpatialClearOcclusionState(U32 state) : mState(state) { }
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); }
+};
+
+class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState
+{
+public:
+ LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (group->isOcclusionState(mState))
+ {
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ }
+};
+
+void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (mode > STATE_MODE_SINGLE)
+ {
+ if (mode == STATE_MODE_DIFF)
+ {
+ LLSpatialClearOcclusionStateDiff clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ else if (mode == STATE_MODE_BRANCH)
+ {
+ LLSpatialClearOcclusionState clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ else
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] &= ~state;
+ }
+ }
+ }
+ else
+ {
+ mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
+ }
+}
//======================================
// Octree Listener Implementation
//======================================
@@ -946,13 +1150,16 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
mSpatialPartition(part),
mVertexBuffer(NULL),
mBufferUsage(GL_STATIC_DRAW_ARB),
- mVisible(0),
mDistance(0.f),
mDepth(0.f),
mLastUpdateDistance(-1.f),
mLastUpdateTime(gFrameTimeSeconds),
mViewAngle(0.f),
- mLastUpdateViewAngle(-1.f)
+ mLastUpdateViewAngle(-1.f),
+ mAtlasList(4),
+ mCurUpdatingTime(0),
+ mCurUpdatingSlotp(NULL),
+ mCurUpdatingTexture (NULL)
{
sNodeCount++;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -960,14 +1167,25 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
sg_assert(mOctreeNode->getListenerCount() == 0);
mOctreeNode->addListener(this);
setState(SG_INITIAL_STATE_MASK);
+ gPipeline.markRebuild(this, TRUE);
mBounds[0] = LLVector3(node->getCenter());
mBounds[1] = LLVector3(node->getSize());
part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
mLODHash = part->mLODSeed;
-
- mOcclusionQuery = 0;
+
+ OctreeNode* oct_parent = node->getOctParent();
+
+ LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL;
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionQuery[i] = 0;
+ mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
+ mVisible[i] = 0;
+ }
+
mOcclusionVerts = NULL;
mRadius = 1;
@@ -976,13 +1194,18 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
void LLSpatialGroup::updateDistance(LLCamera &camera)
{
+ if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
#if !LL_RELEASE_FOR_DOWNLOAD
if (isState(LLSpatialGroup::OBJECT_DIRTY))
{
llerrs << "Spatial group dirty on distance update." << llendl;
}
#endif
- if (!getData().empty() && !LLSpatialPartition::sFreezeState)
+ if (!getData().empty())
{
mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
(F32) mOctreeNode->getSize().magVec();
@@ -1018,6 +1241,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
//NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
//not setting this node to dirty would be a very good thing
group->setState(LLSpatialGroup::ALPHA_DIRTY);
+ gPipeline.markRebuild(group, FALSE);
}
}
}
@@ -1054,6 +1278,18 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
}
+F32 LLSpatialGroup::getUpdateUrgency() const
+{
+ if (!isVisible())
+ {
+ return 0.f;
+ }
+ else
+ {
+ return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance;
+ }
+}
+
BOOL LLSpatialGroup::needsUpdate()
{
return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
@@ -1140,8 +1376,7 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
if (child->getListenerCount() == 0)
{
- LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition);
- group->setState(mState & SG_STATE_INHERIT_MASK);
+ new LLSpatialGroup(child, mSpatialPartition);
}
else
{
@@ -1161,16 +1396,21 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo
void LLSpatialGroup::destroyGL()
{
setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
+
mLastUpdateTime = gFrameTimeSeconds;
mVertexBuffer = NULL;
mBufferMap.clear();
clearDrawMap();
- if (mOcclusionQuery)
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
{
- sQueryPool.release(mOcclusionQuery);
- mOcclusionQuery = 0;
+ if (mOcclusionQuery[i])
+ {
+ sQueryPool.release(mOcclusionQuery[i]);
+ mOcclusionQuery[i] = 0;
+ }
}
delete [] mOcclusionVerts;
@@ -1266,38 +1506,43 @@ void LLSpatialGroup::checkOcclusion()
if (LLPipeline::sUseOcclusion > 1)
{
LLSpatialGroup* parent = getParent();
- if (parent && parent->isState(LLSpatialGroup::OCCLUDED))
+ if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //if the parent has been marked as occluded, the child is implicitly occluded
- clearState(QUERY_PENDING | DISCARD_QUERY);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
}
- else if (isState(QUERY_PENDING))
+ else if (isOcclusionState(QUERY_PENDING))
{ //otherwise, if a query is pending, read it back
LLFastTimer t(FTM_OCCLUSION_READBACK);
GLuint res = 1;
- if (!isState(DISCARD_QUERY) && mOcclusionQuery)
+ if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res);
+ glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
+ }
+
+ if (isOcclusionState(DISCARD_QUERY))
+ {
+ res = 2;
}
if (res > 0)
{
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
else
{
assert_states_valid(this);
- setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
- clearState(QUERY_PENDING | DISCARD_QUERY);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
}
- else if (mSpatialPartition->isOcclusionEnabled() && isState(LLSpatialGroup::OCCLUDED))
+ else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //check occlusion has been issued for occluded node that has not had a query issued
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
}
@@ -1309,9 +1554,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
if (earlyFail(camera, this))
{
- setState(LLSpatialGroup::DISCARD_QUERY);
+ setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
else
@@ -1319,9 +1564,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
LLFastTimer t(FTM_RENDER_OCCLUSION);
- if (!mOcclusionQuery)
+ if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- mOcclusionQuery = sQueryPool.allocate();
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
}
if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
@@ -1329,22 +1574,33 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
buildOcclusion();
}
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery);
+ glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ if (camera->getOrigin().isExactlyZero())
+ { //origin is invalid, draw entire box
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8);
+ }
+ else
+ {
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ }
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
}
- setState(LLSpatialGroup::QUERY_PENDING);
- clearState(LLSpatialGroup::DISCARD_QUERY);
+ setOcclusionState(LLSpatialGroup::QUERY_PENDING);
+ clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
}
}
}
//==============================================
-LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
+LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
+: mRenderByGroup(render_by_group)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
mOcclusionEnabled = TRUE;
@@ -1356,7 +1612,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
mBufferUsage = buffer_usage;
mDepthMask = FALSE;
mSlopRatio = 0.25f;
- mRenderByGroup = TRUE;
mInfiniteFarClip = FALSE;
LLGLNamePool::registerPool(&sQueryPool);
@@ -1393,9 +1648,9 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
LLSpatialGroup* group = drawablep->getSpatialGroup();
- if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING))
+ if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
{
- group->setState(LLSpatialGroup::DISCARD_QUERY);
+ group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
}
return group;
@@ -1494,7 +1749,7 @@ public:
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
gPipeline.markOccluder(group);
return true;
@@ -1576,7 +1831,7 @@ public:
virtual void processGroup(LLSpatialGroup* group)
{
if (group->needsUpdate() ||
- group->mVisible < LLDrawable::getCurrentFrame() - 1)
+ group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
{
group->doOcclusion(mCamera);
}
@@ -1644,7 +1899,7 @@ public:
{
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
return true;
}
@@ -1652,13 +1907,57 @@ public:
return false;
}
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (earlyFail(group))
+ {
+ return;
+ }
+
+ if (mRes == 2)
+ {
+ //fully in, don't traverse further (won't effect extents
+ }
+ else if (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK))
+ { //don't need to do frustum check
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ else
+ {
+ mRes = frustumCheck(group);
+
+ if (mRes)
+ { //at least partially in, run on down
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+
+ mRes = 0;
+ }
+ }
+
virtual void processGroup(LLSpatialGroup* group)
{
- if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f)
- { //megaprims and water edge patches be damned!
+ if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty())
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ if (mRes < 2)
+ {
+ if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0)
+ {
+ mEmpty = FALSE;
+ update_min_max(mMin, mMax, group->mObjectExtents[0]);
+ update_min_max(mMin, mMax, group->mObjectExtents[1]);
+ }
+ }
+ else
+ {
mEmpty = FALSE;
- update_min_max(mMin, mMax, group->mObjectExtents[0]);
- update_min_max(mMin, mMax, group->mObjectExtents[1]);
+ update_min_max(mMin, mMax, group->mExtents[0]);
+ update_min_max(mMin, mMax, group->mExtents[1]);
}
}
@@ -1678,7 +1977,7 @@ public:
if (mResult || //already found a node, don't check any more
group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
return true;
}
@@ -1857,6 +2156,12 @@ BOOL LLSpatialPartition::isOcclusionEnabled()
BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax)
{
+ {
+ LLFastTimer ftm(FTM_CULL_REBOUND);
+ LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
+ group->rebound();
+ }
+
LLOctreeCullVisExtents vis(&camera, visMin, visMax);
vis.traverse(mOctree);
return vis.mEmpty;
@@ -1876,12 +2181,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
#endif
{
- BOOL temp = sFreezeState;
- sFreezeState = FALSE;
LLFastTimer ftm(FTM_CULL_REBOUND);
LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
group->rebound();
- sFreezeState = temp;
}
#if LL_OCTREE_PARANOIA_CHECK
@@ -1918,6 +2220,11 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
{
+ if (camera->getOrigin().isExactlyZero())
+ {
+ return FALSE;
+ }
+
const F32 vel = SG_OCCLUSION_FUDGE*2.f;
LLVector3 c = group->mBounds[0];
LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel);
@@ -2195,7 +2502,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
LLGLEnable cull(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
+ BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
!group->getData().empty();
if (render_objects)
{
@@ -2436,6 +2743,39 @@ void renderBatchSize(LLDrawInfo* params)
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
}
+void renderShadowFrusta(LLDrawInfo* params)
+{
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+
+ LLVector3 center = (params->mExtents[1]+params->mExtents[0])*0.5f;
+ LLVector3 size = (params->mExtents[1]-params->mExtents[0])*0.5f;
+
+ if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size))
+ {
+ glColor3f(1,0,0);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size))
+ {
+ glColor3f(0,1,0);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size))
+ {
+ glColor3f(0,0,1);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size))
+ {
+ glColor3f(1,0,1);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+}
+
+
void renderLights(LLDrawable* drawablep)
{
if (!drawablep->isLight())
@@ -2571,6 +2911,9 @@ public:
//draw tight fit bounding boxes for spatial group
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
renderOctree(group);
stop_glerror();
}
@@ -2578,6 +2921,9 @@ public:
//render visibility wireframe
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
gGL.flush();
glPushMatrix();
gGLLastMatrix = NULL;
@@ -2603,6 +2949,19 @@ public:
LLVector3 nodeCenter = group->mBounds[0];
LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter());
+ group->rebuildGeom();
+ group->rebuildMesh();
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
+ {
+ if (!group->getData().empty())
+ {
+ gGL.color3f(0,0,1);
+ drawBoxOutline(group->mObjectBounds[0],
+ group->mObjectBounds[1]);
+ }
+ }
+
for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
{
LLDrawable* drawable = *i;
@@ -2612,6 +2971,16 @@ public:
renderBoundingBox(drawable);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE))
+ {
+ if (drawable->isState(LLDrawable::IN_REBUILD_Q2))
+ {
+ gGL.color4f(0.6f, 0.6f, 0.1f, 1.f);
+ const LLVector3* ext = drawable->getSpatialExtents();
+ drawBoxOutline((ext[0]+ext[1])*0.5f, (ext[1]-ext[0])*0.5f);
+ }
+ }
+
if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
renderTexturePriority(drawable);
@@ -2660,6 +3029,10 @@ public:
{
renderBatchSize(draw_info);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ renderShadowFrusta(draw_info);
+ }
}
}
}
@@ -2710,6 +3083,79 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera)
pusher.traverse(mOctree);
}
+class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS];
+
+ LLOctreeStateCheck()
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mInheritedMask[i] = 0;
+ }
+ }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+ node->accept(this);
+
+
+ U32 temp[LLViewerCamera::NUM_CAMERAS];
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ temp[i] = mInheritedMask[i];
+ mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED;
+ }
+
+ for (U32 i = 0; i < node->getChildCount(); i++)
+ {
+ traverse(node->getChild(i));
+ }
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mInheritedMask[i] = temp[i];
+ }
+ }
+
+
+ virtual void visit(const LLOctreeNode<LLDrawable>* state)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i]))
+ {
+ llerrs << "Spatial group failed inherited mask test." << llendl;
+ }
+ }
+
+ if (group->isState(LLSpatialGroup::DIRTY))
+ {
+ assert_parent_state(group, LLSpatialGroup::DIRTY);
+ }
+ }
+
+ void assert_parent_state(LLSpatialGroup* group, U32 state)
+ {
+ LLSpatialGroup* parent = group->getParent();
+ while (parent)
+ {
+ if (!parent->isState(state))
+ {
+ llerrs << "Spatial group failed parent state check." << llendl;
+ }
+ parent = parent->getParent();
+ }
+ }
+};
+
+
void LLSpatialPartition::renderDebug()
{
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE |
@@ -2722,7 +3168,9 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
LLPipeline::RENDER_DEBUG_RAYCAST |
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
- LLPipeline::RENDER_DEBUG_AGENT_TARGET))
+ LLPipeline::RENDER_DEBUG_AGENT_TARGET |
+ LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
+ LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
return;
}
@@ -2757,6 +3205,12 @@ void LLSpatialPartition::renderDebug()
render_debug.traverse(mOctree);
}
+void LLSpatialGroup::drawObjectBox(LLColor4 col)
+{
+ gGL.color4fv(col.mV);
+ drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
+}
+
BOOL LLSpatialPartition::isVisible(const LLVector3& v)
{
@@ -2937,10 +3391,10 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
LLDrawInfo::~LLDrawInfo()
{
- if (LLSpatialGroup::sNoDelete)
+ /*if (LLSpatialGroup::sNoDelete)
{
llerrs << "LLDrawInfo deleted illegally!" << llendl;
- }
+ }*/
if (mFace)
{
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 13ab35402c..16e8782a8e 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -44,6 +44,7 @@
#include "llcubemap.h"
#include "lldrawpool.h"
#include "llface.h"
+#include "llviewercamera.h"
#include <queue>
@@ -53,6 +54,8 @@
class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
+class LLTextureAtlas;
+class LLTextureAtlasSlot;
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared);
@@ -72,7 +75,7 @@ public:
LLPointer<LLVertexBuffer> mVertexBuffer;
- LLPointer<LLViewerTexture> mTexture;
+ LLPointer<LLViewerTexture> mTexture;
LLColor4U mGlowColor;
S32 mDebugColor;
const LLMatrix4* mTextureMatrix;
@@ -154,12 +157,14 @@ public:
class LLSpatialGroup : public LLOctreeListener<LLDrawable>
{
friend class LLSpatialPartition;
+ friend class LLOctreeStateCheck;
public:
static U32 sNodeCount;
static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE
typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t;
typedef std::set<LLPointer<LLSpatialGroup> > sg_set_t;
+ typedef std::list<LLPointer<LLSpatialGroup> > sg_list_t;
typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t;
typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t;
typedef std::map<U32, drawmap_elem_t > draw_map_t;
@@ -184,6 +189,14 @@ public:
}
};
+ struct CompareUpdateUrgency
+ {
+ bool operator()(const LLPointer<LLSpatialGroup> lhs, const LLPointer<LLSpatialGroup> rhs)
+ {
+ return lhs->getUpdateUrgency() > rhs->getUpdateUrgency();
+ }
+ };
+
struct CompareDepthGreater
{
bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs)
@@ -194,35 +207,44 @@ public:
typedef enum
{
- OCCLUDED = 0x00000001,
- IN_QUEUE = 0x00000002,
- QUERY_PENDING = 0x00000004,
- ACTIVE_OCCLUSION = 0x00000008,
- DISCARD_QUERY = 0x00000010,
- DEAD = 0x00000020,
- EARLY_FAIL = 0x00000040,
- DIRTY = 0x00000080,
- OBJECT_DIRTY = 0x00000100,
- GEOM_DIRTY = 0x00000200,
- ALPHA_DIRTY = 0x00000800,
- SKIP_FRUSTUM_CHECK = 0x00001000,
- IN_IMAGE_QUEUE = 0x00002000,
- IMAGE_DIRTY = 0x00004000,
- OCCLUSION_DIRTY = 0x00008000,
- MESH_DIRTY = 0x00010000,
+ OCCLUDED = 0x00010000,
+ QUERY_PENDING = 0x00020000,
+ ACTIVE_OCCLUSION = 0x00040000,
+ DISCARD_QUERY = 0x00080000,
+ EARLY_FAIL = 0x00100000,
+ } eOcclusionState;
+
+ typedef enum
+ {
+ DEAD = 0x00000001,
+ DIRTY = 0x00000002,
+ OBJECT_DIRTY = 0x00000004,
+ GEOM_DIRTY = 0x00000008,
+ ALPHA_DIRTY = 0x00000010,
+ SKIP_FRUSTUM_CHECK = 0x00000020,
+ IN_IMAGE_QUEUE = 0x00000040,
+ IMAGE_DIRTY = 0x00000080,
+ OCCLUSION_DIRTY = 0x00000100,
+ MESH_DIRTY = 0x00000200,
+ NEW_DRAWINFO = 0x00000400,
+ IN_BUILD_Q1 = 0x00000800,
+ IN_BUILD_Q2 = 0x00001000,
+ STATE_MASK = 0x0000FFFF,
} eSpatialState;
typedef enum
{
STATE_MODE_SINGLE = 0, //set one node
STATE_MODE_BRANCH, //set entire branch
- STATE_MODE_DIFF //set entire branch as long as current state is different
+ STATE_MODE_DIFF, //set entire branch as long as current state is different
+ STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras
} eSetStateMode;
LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
BOOL isDead() { return isState(DEAD); }
- BOOL isState(U32 state) const { return mState & state ? TRUE : FALSE; }
+ BOOL isState(U32 state) const;
+ BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
U32 getState() { return mState; }
void setState(U32 state);
void clearState(U32 state);
@@ -233,10 +255,14 @@ public:
void validateDrawMap();
void setState(U32 state, S32 mode);
+ void clearState(U32 state, S32 mode);
+
+ void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
+ void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
LLSpatialGroup* getParent();
- void clearState(U32 state, S32 mode);
+
BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE);
BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE);
BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group
@@ -253,6 +279,7 @@ public:
void updateDistance(LLCamera& camera);
BOOL needsUpdate();
+ F32 getUpdateUrgency() const;
BOOL changeLOD();
void rebuildGeom();
void rebuildMesh();
@@ -262,6 +289,8 @@ public:
element_list& getData() { return mOctreeNode->getData(); }
U32 getElementCount() const { return mOctreeNode->getElementCount(); }
+ void drawObjectBox(LLColor4 col);
+
//LISTENER FUNCTIONS
virtual void handleInsertion(const TreeNode* node, LLDrawable* face);
virtual void handleRemoval(const TreeNode* node, LLDrawable* face);
@@ -270,10 +299,41 @@ public:
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child);
+//-------------------
+//for atlas use
+//-------------------
+ //atlas
+ void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;}
+ U32 getCurUpdatingTime() const { return mCurUpdatingTime ;}
+
+ void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ;
+ LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level = 3) ;
+
+ void setCurUpdatingTexture(LLViewerTexture* tex){ mCurUpdatingTexture = tex ;}
+ LLViewerTexture* getCurUpdatingTexture() const { return mCurUpdatingTexture ;}
+
+ BOOL hasAtlas(LLTextureAtlas* atlasp) ;
+ LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ;
+ void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ;
+ void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ;
+ void clearAtlasList() ;
+private:
+ U32 mCurUpdatingTime ;
+ //do not make the below two to use LLPointer
+ //because mCurUpdatingTime invalidates them automatically.
+ LLTextureAtlasSlot* mCurUpdatingSlotp ;
+ LLViewerTexture* mCurUpdatingTexture ;
+
+ std::vector< std::list<LLTextureAtlas*> > mAtlasList ;
+//-------------------
+//end for atlas use
+//-------------------
+
protected:
virtual ~LLSpatialGroup();
U32 mState;
+ U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
S32 mLODHash;
static S32 sLODSeed;
@@ -292,12 +352,12 @@ public:
LLPointer<LLVertexBuffer> mVertexBuffer;
F32* mOcclusionVerts;
- GLuint mOcclusionQuery;
+ GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
U32 mBufferUsage;
draw_map_t mDrawMap;
- S32 mVisible;
+ S32 mVisible[LLViewerCamera::NUM_CAMERAS];
F32 mDistance;
F32 mDepth;
F32 mLastUpdateDistance;
@@ -326,9 +386,7 @@ public:
class LLSpatialPartition: public LLGeometryManager
{
public:
- static BOOL sFreezeState; //if true, no spatialgroup state updates will be made
-
- LLSpatialPartition(U32 data_mask, U32 mBufferUsage = GL_STATIC_DRAW_ARB);
+ LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage);
virtual ~LLSpatialPartition();
LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE);
@@ -374,7 +432,7 @@ public:
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
U32 mBufferUsage;
- BOOL mRenderByGroup;
+ const BOOL mRenderByGroup;
U32 mLODSeed;
U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed)
U32 mVertexDataMask;
@@ -393,7 +451,7 @@ protected:
public:
typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t;
- LLSpatialBridge(LLDrawable* root, U32 data_mask);
+ LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask);
virtual BOOL isSpatialBridge() const { return TRUE; }
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 44e76a0bc1..dbb3062323 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -436,8 +436,8 @@ bool idle_startup()
}
else
{
- // Update images?
- gTextureList.updateImages(0.01f);
+ //note: Removing this line will cause incorrect button size in the login screen. -- bao.
+ gTextureList.updateImages(0.01f) ;
}
if ( STATE_FIRST == LLStartUp::getStartupState() )
diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index de3d80f044..39f6a6c396 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -214,7 +214,7 @@ void LLSurface::create(const S32 grids_per_edge,
LLViewerTexture* LLSurface::getSTexture()
{
- if (mSTexturep.notNull() && !mSTexturep->hasValidGLTexture())
+ if (mSTexturep.notNull() && !mSTexturep->hasGLTexture())
{
createSTexture();
}
@@ -223,7 +223,7 @@ LLViewerTexture* LLSurface::getSTexture()
LLViewerTexture* LLSurface::getWaterTexture()
{
- if (mWaterTexturep.notNull() && !mWaterTexturep->hasValidGLTexture())
+ if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture())
{
createWaterTexture();
}
@@ -235,8 +235,13 @@ void LLSurface::createSTexture()
if (!mSTexturep)
{
// Fill with dummy gray data.
- LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
- U8 *default_texture = raw->getData();
+
+ mSTexturep = LLViewerTextureManager::getLocalTexture(sTextureSize, sTextureSize, 3, FALSE);
+ mSTexturep->dontDiscard();
+ mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ // GL NOT ACTIVE HERE
+ /*U8 *default_texture = raw->getData();
for (S32 i = 0; i < sTextureSize; i++)
{
for (S32 j = 0; j < sTextureSize; j++)
@@ -250,7 +255,8 @@ void LLSurface::createSTexture()
mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
mSTexturep->dontDiscard();
gGL.getTexUnit(0)->bind(mSTexturep);
- mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);*/
+
}
}
@@ -259,7 +265,7 @@ void LLSurface::createWaterTexture()
if (!mWaterTexturep)
{
// Create the water texture
- LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
+ /*LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
U8 *default_texture = raw->getData();
for (S32 i = 0; i < sTextureSize/2; i++)
{
@@ -270,10 +276,11 @@ void LLSurface::createWaterTexture()
*(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
*(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
}
- }
- mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
+ }*/
+
+
+ mWaterTexturep = LLViewerTextureManager::getLocalTexture(sTextureSize/2, sTextureSize/2, 4, FALSE);
mWaterTexturep->dontDiscard();
- gGL.getTexUnit(0)->bind(mWaterTexturep);
mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
}
}
@@ -1189,7 +1196,7 @@ F32 LLSurface::getWaterHeight() const
BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
const F32 width, const F32 height)
{
- if (!getWaterTexture() || !mWaterTexturep->hasGLTexture())
+ if (!getWaterTexture())
{
return FALSE;
}
@@ -1273,6 +1280,11 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
}
}
+ if (!mWaterTexturep->hasGLTexture())
+ {
+ mWaterTexturep->createGLTexture(0, raw);
+ }
+
mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
return TRUE;
}
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 5fac5fd1e4..0ce794addb 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -712,17 +712,7 @@ BOOL LLSurfacePatch::updateTexture()
if (mVObjp)
{
mVObjp->dirtyGeom();
- }
- updateCompositionStats();
- F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
- if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
- tex_patch_size, tex_patch_size))
- {
- mSTexUpdate = FALSE;
-
- // Also generate the water texture
- mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
- tex_patch_size, tex_patch_size);
+ gPipeline.markGLRebuild(mVObjp);
return TRUE;
}
}
@@ -735,6 +725,28 @@ BOOL LLSurfacePatch::updateTexture()
}
}
+void LLSurfacePatch::updateGL()
+{
+ F32 meters_per_grid = getSurface()->getMetersPerGrid();
+ F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge();
+
+ LLViewerRegion *regionp = getSurface()->getRegion();
+ LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal();
+
+ LLVLComposition* comp = regionp->getComposition();
+
+ updateCompositionStats();
+ F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
+ if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
+ tex_patch_size, tex_patch_size))
+ {
+ mSTexUpdate = FALSE;
+
+ // Also generate the water texture
+ mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
+ tex_patch_size, tex_patch_size);
+ }
+}
void LLSurfacePatch::dirtyZ()
{
diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h
index 4cac977305..ebfb64c1d8 100644
--- a/indra/newview/llsurfacepatch.h
+++ b/indra/newview/llsurfacepatch.h
@@ -90,6 +90,7 @@ public:
void updateCameraDistanceRegion( const LLVector3 &pos_region);
void updateVisibility();
+ void updateGL();
void dirtyZ(); // Dirty the z values of this patch
void setHasReceivedData();
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index b0ac13913e..6922eae0e1 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -193,7 +193,7 @@ public:
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
void renderAlphaMaskTextures(S32 width, S32 height, bool forceClear = false);
LLTexLayer* findLayerByName(std::string name);
-
+
LLVOAvatarSelf* getAvatar() const { return mAvatar; }
const std::string getBodyRegion() const;
BOOL hasComposite() const { return (mComposite.notNull()); }
diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp
index c9117a84a5..7a1ee95a65 100644
--- a/indra/newview/lltexlayerparams.cpp
+++ b/indra/newview/lltexlayerparams.cpp
@@ -94,7 +94,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
{
S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents();
- if (tex->hasValidGLTexture())
+ if (tex->hasGLTexture())
{
*gl_bytes += bytes;
}
diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp
new file mode 100644
index 0000000000..79b3686386
--- /dev/null
+++ b/indra/newview/lltextureatlas.cpp
@@ -0,0 +1,422 @@
+/**
+ * @file lltextureatlas.cpp
+ * @brief LLTextureAtlas class implementation.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+#include "llerror.h"
+#include "llimage.h"
+#include "llmath.h"
+#include "llgl.h"
+#include "llrender.h"
+#include "lltextureatlas.h"
+
+//-------------------
+S16 LLTextureAtlas::sMaxSubTextureSize = 64 ;
+S16 LLTextureAtlas::sSlotSize = 32 ;
+
+#ifndef DEBUG_ATLAS
+#define DEBUG_ATLAS 0
+#endif
+
+#ifndef DEBUG_USAGE_BITS
+#define DEBUG_USAGE_BITS 0
+#endif
+//**************************************************************************************************************
+LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) :
+ LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE),
+ mAtlasDim(atlas_dim),
+ mNumSlotsReserved(0),
+ mMaxSlotsInAtlas(atlas_dim * atlas_dim)
+{
+ generateEmptyUsageBits() ;
+
+ //generate an empty texture
+ generateGLTexture() ;
+ LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
+ createGLTexture(0, image_raw, 0);
+ image_raw = NULL;
+}
+
+LLTextureAtlas::~LLTextureAtlas()
+{
+ if(mSpatialGroupList.size() > 0)
+ {
+ llerrs << "Not clean up the spatial groups!" << llendl ;
+ }
+ releaseUsageBits() ;
+}
+
+//virtual
+S8 LLTextureAtlas::getType() const
+{
+ return LLViewerTexture::ATLAS_TEXTURE ;
+}
+
+void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset)
+{
+ xoffset = (F32)col / mAtlasDim ;
+ yoffset = (F32)row / mAtlasDim ;
+}
+
+void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale)
+{
+ xscale = (F32)w / (mAtlasDim * sSlotSize) ;
+ yscale = (F32)h / (mAtlasDim * sSlotSize) ;
+}
+
+//insert a texture piece into the atlas
+LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row)
+{
+ if(!getTexName())
+ {
+ return 0 ;
+ }
+
+ S32 w = raw_image->getWidth() ;
+ S32 h = raw_image->getHeight() ;
+ if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize)
+ {
+ //size overflow
+ return 0 ;
+ }
+
+ BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName());
+ if (!res)
+ {
+ llerrs << "bindTexture failed" << llendl;
+ }
+
+ GLint xoffset = sSlotSize * slot_col ;
+ GLint yoffset = sSlotSize * slot_row ;
+
+ if(!source_gl_tex->preAddToAtlas(discard_level, raw_image))
+ {
+ return 0 ;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,
+ mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData());
+
+ source_gl_tex->postAddToAtlas() ;
+ return getTexName();
+}
+
+//release a sub-texture slot from the atlas
+void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width)
+{
+ unmarkUsageBits(slot_width, slot_col, slot_row) ;
+ mNumSlotsReserved -= slot_width * slot_width ;
+}
+
+BOOL LLTextureAtlas::isEmpty() const
+{
+ return !mNumSlotsReserved ;
+}
+
+BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const
+{
+ return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ;
+}
+F32 LLTextureAtlas::getFullness() const
+{
+ return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ;
+}
+
+void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp)
+{
+ if(groupp && !hasSpatialGroup(groupp))
+ {
+ mSpatialGroupList.push_back(groupp);
+ }
+}
+
+void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp)
+{
+ if(groupp)
+ {
+ mSpatialGroupList.remove(groupp);
+ }
+}
+
+void LLTextureAtlas::clearSpatialGroup()
+{
+ mSpatialGroupList.clear();
+}
+void LLTextureAtlas::removeLastSpatialGroup()
+{
+ mSpatialGroupList.pop_back() ;
+}
+
+LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup()
+{
+ if(mSpatialGroupList.size() > 0)
+ {
+ return mSpatialGroupList.back() ;
+ }
+ return NULL ;
+}
+
+BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp)
+{
+ for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter)
+ {
+ if(*iter == groupp)
+ {
+ return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
+//--------------------------------------------------------------------------------------
+//private
+void LLTextureAtlas::generateEmptyUsageBits()
+{
+ S32 col_len = (mAtlasDim + 7) >> 3 ;
+ mUsageBits = new U8*[mAtlasDim] ;
+ *mUsageBits = new U8[mAtlasDim * col_len] ;
+
+ mUsageBits[0] = *mUsageBits ;
+ for(S32 i = 1 ; i < mAtlasDim ; i++)
+ {
+ mUsageBits[i] = mUsageBits[i-1] + col_len ;
+
+ for(S32 j = 0 ; j < col_len ; j++)
+ {
+ //init by 0 for all bits.
+ mUsageBits[i][j] = 0 ;
+ }
+ }
+
+ //do not forget mUsageBits[0]!
+ for(S32 j = 0 ; j < col_len ; j++)
+ {
+ //init by 0 for all bits.
+ mUsageBits[0][j] = 0 ;
+ }
+
+ mTestBits = NULL ;
+#if DEBUG_USAGE_BITS
+ //------------
+ //test
+ mTestBits = new U8*[mAtlasDim] ;
+ *mTestBits = new U8[mAtlasDim * mAtlasDim] ;
+ mTestBits[0] = *mTestBits ;
+ for(S32 i = 1 ; i < mAtlasDim ; i++)
+ {
+ mTestBits[i] = mTestBits[i-1] + mAtlasDim ;
+
+ for(S32 j = 0 ; j < mAtlasDim ; j++)
+ {
+ //init by 0 for all bits.
+ mTestBits[i][j] = 0 ;
+ }
+ }
+
+ for(S32 j = 0 ; j < mAtlasDim ; j++)
+ {
+ //init by 0 for all bits.
+ mTestBits[0][j] = 0 ;
+ }
+#endif
+}
+
+void LLTextureAtlas::releaseUsageBits()
+{
+ if(mUsageBits)
+ {
+ delete[] *mUsageBits ;
+ delete[] mUsageBits ;
+ }
+ mUsageBits = NULL ;
+
+ //test
+ if( mTestBits)
+ {
+ delete[] *mTestBits;
+ delete[] mTestBits;
+ }
+ mTestBits = NULL ;
+}
+
+void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row)
+{
+ S16 x = col >> 3 ;
+
+ for(S8 i = 0 ; i < bits_len ; i++)
+ {
+ mUsageBits[row + i][x] |= mask ;
+ }
+
+#if DEBUG_USAGE_BITS
+ //test
+ for(S8 i = row ; i < row + bits_len ; i++)
+ {
+ for(S8 j = col ; j < col + bits_len ; j++)
+ {
+ mTestBits[i][j] = 1 ;
+ }
+ }
+#endif
+}
+
+void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row)
+{
+ S16 x = col >> 3 ;
+ U8 mask = 1 ;
+ for(S8 i = 1 ; i < bits_len ; i++)
+ {
+ mask |= (1 << i) ;
+ }
+ mask <<= (col & 7) ;
+ mask = ~mask ;
+
+ for(S8 i = 0 ; i < bits_len ; i++)
+ {
+ mUsageBits[row + i][x] &= mask ;
+ }
+
+#if DEBUG_USAGE_BITS
+ //test
+ for(S8 i = row ; i < row + bits_len ; i++)
+ {
+ for(S8 j = col ; j < col + bits_len ; j++)
+ {
+ mTestBits[i][j] = 0 ;
+ }
+ }
+#endif
+}
+
+//return true if any of bits in the range marked.
+BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row)
+{
+ BOOL ret = FALSE ;
+ S16 x = col >> 3 ;
+
+ for(S8 i = 0 ; i < bits_len ; i++)
+ {
+ if(mUsageBits[row + i][x] & mask)
+ {
+ ret = TRUE ;
+ break ;
+ //return TRUE ;
+ }
+ }
+
+#if DEBUG_USAGE_BITS
+ //test
+ BOOL ret2 = FALSE ;
+ for(S8 i = row ; i < row + bits_len ; i++)
+ {
+ for(S8 j = col ; j < col + bits_len ; j++)
+ {
+ if(mTestBits[i][j])
+ {
+ ret2 = TRUE ;
+ }
+ }
+ }
+
+ if(ret != ret2)
+ {
+ llerrs << "bits map corrupted." << llendl ;
+ }
+#endif
+ return ret ;//FALSE ;
+}
+
+//----------------------------------------------------------------------
+//
+//index order: Z order, i.e.:
+// |-----|-----|-----|-----|
+// | 10 | 11 | 14 | 15 |
+// |-----|-----|-----|-----|
+// | 8 | 9 | 12 | 13 |
+// |-----|-----|-----|-----|
+// | 2 | 3 | 6 | 7 |
+// |-----|-----|-----|-----|
+// | 0 | 1 | 4 | 5 |
+// |-----|-----|-----|-----|
+void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row)
+{
+ col = 0 ;
+ row = 0 ;
+
+ S16 index_copy = index ;
+ for(S16 i = 0 ; index_copy && i < 16 ; i += 2)
+ {
+ col |= ((index & (1 << i)) >> i) << (i >> 1) ;
+ row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ;
+ index_copy >>= 2 ;
+ }
+}
+void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index)
+{
+ index = 0 ;
+ S16 col_copy = col ;
+ S16 row_copy = row ;
+ for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++)
+ {
+ index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ;
+ col_copy >>= 1 ;
+ row_copy >>= 1 ;
+ }
+}
+//----------------------------------------------------------------------
+//return TRUE if succeeds.
+BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row)
+{
+ S16 index_step = bits_len * bits_len ;
+
+ U8 mask = 1 ;
+ for(S8 i = 1 ; i < bits_len ; i++)
+ {
+ mask |= (1 << i) ;
+ }
+
+ U8 cur_mask ;
+ for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step)
+ {
+ getPositionFromIndex(index, col, row) ;
+
+ cur_mask = mask << (col & 7) ;
+ if(!areUsageBitsMarked(bits_len, cur_mask, col, row))
+ {
+ markUsageBits(bits_len, cur_mask, col, row) ;
+ mNumSlotsReserved += bits_len * bits_len ;
+
+ return TRUE ;
+ }
+ }
+
+ return FALSE ;
+}
diff --git a/indra/newview/lltextureatlas.h b/indra/newview/lltextureatlas.h
new file mode 100644
index 0000000000..1f756ccf1a
--- /dev/null
+++ b/indra/newview/lltextureatlas.h
@@ -0,0 +1,95 @@
+/**
+ * @file lltextureatlas.h
+ * @brief LLTextureAtlas base class.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_TEXTUREATLAS_H
+#define LL_TEXTUREATLAS_H
+
+#include "llviewertexture.h"
+class LLSpatialGroup ;
+
+class LLTextureAtlas : public LLViewerTexture
+{
+protected:
+ /*virtual*/ ~LLTextureAtlas() ;
+
+public:
+ LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ;
+
+ /*virtual*/ S8 getType() const;
+
+ LLGLuint insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ;
+ void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width);
+
+ BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ;
+ void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ;
+ void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ;
+
+ BOOL isEmpty() const ;
+ BOOL isFull(S8 to_be_reserved = 1) const ;
+ F32 getFullness() const ;
+
+ void addSpatialGroup(LLSpatialGroup* groupp) ;
+ void removeSpatialGroup(LLSpatialGroup* groupp) ;
+ LLSpatialGroup* getLastSpatialGroup() ;
+ void removeLastSpatialGroup() ;
+ BOOL hasSpatialGroup(LLSpatialGroup* groupp) ;
+ void clearSpatialGroup() ;
+ std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;}
+private:
+ void generateEmptyUsageBits() ;
+ void releaseUsageBits() ;
+
+ void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ;
+ void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ;
+
+ void getPositionFromIndex(S16 index, S16& col, S16& row) ;
+ void getIndexFromPosition(S16 col, S16 row, S16& index) ;
+ BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ;
+
+private:
+ S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas.
+ S16 mNumSlotsReserved ;
+ S16 mMaxSlotsInAtlas ;
+ U8 **mUsageBits ;
+ std::list<LLSpatialGroup*> mSpatialGroupList ;
+
+public:
+ //debug use only
+ U8 **mTestBits ;
+
+public:
+ static S16 sMaxSubTextureSize ;
+ static S16 sSlotSize ;
+};
+
+#endif
+
diff --git a/indra/newview/lltextureatlasmanager.cpp b/indra/newview/lltextureatlasmanager.cpp
new file mode 100644
index 0000000000..8f026787ca
--- /dev/null
+++ b/indra/newview/lltextureatlasmanager.cpp
@@ -0,0 +1,273 @@
+/**
+ * @file lltextureatlasmanager.cpp
+ * @brief LLTextureAtlasManager class implementation.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+#include "llerror.h"
+#include "llmath.h"
+#include "lltextureatlas.h"
+#include "lltextureatlasmanager.h"
+#include "llspatialpartition.h"
+
+const S8 MAX_NUM_EMPTY_ATLAS = 2 ;
+const F32 MIN_ATLAS_FULLNESS = 0.6f ;
+
+//*********************************************************************************************
+//implementation of class LLTextureAtlasInfo
+//*********************************************************************************************
+LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) :
+ mAtlasp(atlasp),
+ mGroupp(groupp),
+ mCol(col),
+ mRow(row),
+ mReservedSlotWidth(slot_width),
+ mValid(FALSE),
+ mUpdatedTime(0),
+ mTexCoordOffset(xoffset, yoffset),
+ mTexCoordScale(1.f, 1.f)
+{
+ llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ;
+}
+
+LLTextureAtlasSlot::~LLTextureAtlasSlot()
+{
+ if(mAtlasp)
+ {
+ mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ;
+ if(mAtlasp->isEmpty())
+ {
+ LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ;
+ }
+ mAtlasp = NULL ;
+ }
+}
+
+//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp)
+//{
+// mAtlasp = atlasp ;
+//}
+//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row)
+//{
+// mCol = col ;
+// mRow = row ;
+//}
+//void LLTextureAtlasSlot::setSlotWidth(S8 width)
+//{
+// //slot is a square with each edge length a power-of-two number
+// mReservedSlotWidth = width ;
+//}
+//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset)
+//{
+// mTexCoordOffset.mV[0] = xoffset ;
+// mTexCoordOffset.mV[1] = yoffset ;
+//}
+
+void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp)
+{
+ mGroupp = groupp ;
+}
+void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale)
+{
+ mTexCoordScale.mV[0] = xscale ;
+ mTexCoordScale.mV[1] = yscale ;
+}
+//*********************************************************************************************
+//END of implementation of class LLTextureAtlasInfo
+//*********************************************************************************************
+
+//*********************************************************************************************
+//implementation of class LLTextureAtlasManager
+//*********************************************************************************************
+LLTextureAtlasManager::LLTextureAtlasManager() :
+ mAtlasMap(4),
+ mEmptyAtlasMap(4)
+{
+}
+
+LLTextureAtlasManager::~LLTextureAtlasManager()
+{
+ for(S32 i = 0 ; i < 4 ; i++)
+ {
+ for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j)
+ {
+ *j = NULL ;
+ }
+ for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j)
+ {
+ *j = NULL ;
+ }
+
+ mAtlasMap[i].clear() ;
+ mEmptyAtlasMap[i].clear() ;
+ }
+ mAtlasMap.clear() ;
+ mEmptyAtlasMap.clear() ;
+}
+
+//return TRUE if qualified
+BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target)
+{
+ if(ncomponents < 1 || ncomponents > 4)
+ {
+ return FALSE ;
+ }
+ //only support GL_TEXTURE_2D
+ if(GL_TEXTURE_2D != target)
+ {
+ return FALSE ;
+ }
+ //real image size overflows
+ if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize)
+ {
+ return FALSE ;
+ }
+
+ //if non-power-of-two number
+ if((w & (w - 1)) || (h & (h - 1)))
+ {
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp)
+{
+ LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ;
+ while(groupp)
+ {
+ groupp->removeAtlas(atlasp, FALSE) ;
+ atlasp->removeLastSpatialGroup() ;
+
+ groupp = atlasp->getLastSpatialGroup() ;
+ }
+
+ S8 type = atlasp->getComponents() - 1 ;
+ //insert to the empty list
+ if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS)
+ {
+ mEmptyAtlasMap[type].push_back(atlasp) ;
+ }
+
+ //delete the atlasp
+ mAtlasMap[type].remove(atlasp) ;
+}
+
+//
+//this function reserves an appropriate slot from atlas pool for an image.
+//return non-NULL if succeeds.
+//Note:
+//1, this function does not check if the image this slot assigned for qualifies for atlas or not,
+// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function.
+//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway.
+//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching.
+//
+LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
+ LLSpatialGroup* groupp, LLViewerTexture* imagep)
+{
+ if(!groupp)
+ {
+ //do not insert to atlas if does not have a group.
+ return NULL ;
+ }
+
+ //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8.
+ if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize)
+ {
+ sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ;
+ }
+ S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ;
+ if(bits_len < 1)
+ {
+ bits_len = 1 ;
+ }
+
+ S16 col = -1, row = -1;
+ S8 total_bits = bits_len * bits_len ;
+
+ //insert to the atlas reserved by the same spatial group
+ LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ;
+ if(atlasp.notNull())
+ {
+ if(!atlasp->getNextAvailableSlot(bits_len, col, row))
+ {
+ //failed
+ atlasp = NULL ;
+ }
+ }
+
+ //search an atlas to fit for 'size'
+ if(!atlasp)
+ {
+ S8 atlas_index = ncomponents - 1 ;
+ ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ;
+ for(; iter != mAtlasMap[atlas_index].end(); ++iter)
+ {
+ LLTextureAtlas* cur = (LLTextureAtlas*)*iter ;
+ if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary.
+ {
+ if(cur->getNextAvailableSlot(bits_len, col, row))
+ {
+ atlasp = cur ;
+ groupp->addAtlas(atlasp) ;
+ break ;
+ }
+ }
+ }
+ }
+
+ //create a new atlas if necessary
+ if(!atlasp)
+ {
+ if(mEmptyAtlasMap[ncomponents - 1].size() > 0)
+ {
+ //there is an empty one
+ atlasp = mEmptyAtlasMap[ncomponents - 1].back() ;
+ mEmptyAtlasMap[ncomponents - 1].pop_back() ;
+ }
+ else
+ {
+ atlasp = new LLTextureAtlas(ncomponents, 16) ;
+ }
+ mAtlasMap[ncomponents - 1].push_back(atlasp) ;
+ atlasp->getNextAvailableSlot(bits_len, col, row) ;
+ groupp->addAtlas(atlasp) ;
+ }
+
+ F32 xoffset, yoffset ;
+ atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ;
+ LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ;
+
+ return slot_infop ;
+}
+
+//*********************************************************************************************
+//END of implementation of class LLTextureAtlasManager
+//*********************************************************************************************
diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h
new file mode 100644
index 0000000000..4dba0759f9
--- /dev/null
+++ b/indra/newview/lltextureatlasmanager.h
@@ -0,0 +1,111 @@
+/**
+ * @file lltextureatlasmanager.h
+ * @brief LLTextureAtlasManager base class.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_TEXTUREATLASMANAGER_H
+#define LL_TEXTUREATLASMANAGER_H
+
+#include "llmemory.h"
+
+class LLSpatialGroup ;
+class LLViewerTexture ;
+
+//just use it as a structure.
+class LLTextureAtlasSlot : public LLRefCount
+{
+public:
+ LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ;
+
+protected:
+ virtual ~LLTextureAtlasSlot();
+
+public:
+
+ //
+ //do not allow to change those values
+ //
+ //void setAtlas(LLTextureAtlas* atlasp) ;
+ //void setSlotPos(S16 col, S16 row) ;
+ //void setSlotWidth(S8 width) ;
+ //void setTexCoordOffset(F32 xoffser, F32 yoffset) ;
+ //
+
+ void setSpatialGroup(LLSpatialGroup* groupp) ;
+ void setTexCoordScale(F32 xscale, F32 yscale) ;
+ void setValid() {mValid = TRUE ;}
+
+ LLTextureAtlas* getAtlas()const {return mAtlasp;}
+ LLSpatialGroup* getSpatialGroup() const {return mGroupp ;}
+ S16 getSlotCol()const {return mCol;}
+ S16 getSlotRow()const {return mRow;}
+ S8 getSlotWidth()const{return mReservedSlotWidth;}
+ BOOL isValid()const { return mValid;}
+ const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;}
+ const LLVector2* getTexCoordScale() const {return &mTexCoordScale;}
+
+ void setUpdatedTime(U32 t) {mUpdatedTime = t;}
+ U32 getUpdatedTime()const {return mUpdatedTime;}
+
+private:
+ LLTextureAtlas* mAtlasp;
+ S16 mCol ;//col of the slot
+ S16 mRow ;//row of the slot
+ S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number
+ LLSpatialGroup* mGroupp ;
+ BOOL mValid ;
+
+ LLVector2 mTexCoordOffset ;
+ LLVector2 mTexCoordScale ;
+
+ U32 mUpdatedTime ;
+} ;
+
+class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager>
+{
+private:
+ typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ;
+
+public:
+ LLTextureAtlasManager();
+ ~LLTextureAtlasManager();
+
+ LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
+ LLSpatialGroup* groupp, LLViewerTexture* imagep) ;
+ void releaseAtlas(LLTextureAtlas* atlasp);
+
+ BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ;
+
+private:
+ std::vector<ll_texture_atlas_list_t> mAtlasMap ;
+ std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately.
+};
+
+#endif
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 9da2446354..ea675c5a6e 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -56,6 +56,7 @@
extern F32 texmem_lower_bound_scale;
LLTextureView *gTextureView = NULL;
+LLTextureSizeView *gTextureSizeView = NULL;
//static
std::set<LLViewerFetchedTexture*> LLTextureView::sDebugImages;
@@ -315,7 +316,7 @@ void LLTextureBar::draw()
pip_x += pip_width + pip_space;
// we don't want to show bind/resident pips for textures using the default texture
- if (mImagep->hasValidGLTexture())
+ if (mImagep->hasGLTexture())
{
// Draw the bound pip
last_event = mImagep->getTimePassedSinceLastBound();
@@ -536,6 +537,73 @@ LLRect LLGLTexMemBar::getRequiredRect()
}
////////////////////////////////////////////////////////////////////////////
+class LLGLTexSizeBar
+{
+public:
+ LLGLTexSizeBar(S32 index, S32 left, S32 bottom, S32 right, S32 line_height)
+ {
+ mIndex = index ;
+ mLeft = left ;
+ mBottom = bottom ;
+ mRight = right ;
+ mLineHeight = line_height ;
+ mTopLoaded = 0 ;
+ mTopBound = 0 ;
+ mScale = 1.0f ;
+ }
+
+ void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;}
+
+ void draw();
+ BOOL handleHover(S32 x, S32 y, MASK mask) ;
+
+private:
+ S32 mIndex ;
+ S32 mLeft ;
+ S32 mBottom ;
+ S32 mRight ;
+ S32 mTopLoaded ;
+ S32 mTopBound ;
+ S32 mLineHeight ;
+ F32 mScale ;
+};
+
+BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask)
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale)))
+ {
+ LLImageGL::setCurTexSizebar(mIndex);
+ }
+#endif
+ return TRUE ;
+}
+void LLGLTexSizeBar::draw()
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLSUIDefault gls_ui;
+
+ if(LLImageGL::sCurTexSizeBar == mIndex)
+ {
+ F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+ std::string text;
+
+ text = llformat("%d", mTopLoaded) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, mLeft, mBottom + (S32)(mTopLoaded * mScale) + mLineHeight,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ text = llformat("%d", mTopBound) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, (mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale) + mLineHeight,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
+ F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
+ gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ;
+ gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ;
+#endif
+}
+////////////////////////////////////////////////////////////////////////////
LLTextureView::LLTextureView(const LLTextureView::Params& p)
: LLContainerView(p),
@@ -820,4 +888,163 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return FALSE;
}
+//-----------------------------------------------------------------
+LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p)
+ : LLView(p)
+{
+ setVisible(FALSE) ;
+
+ mTextureSizeBarWidth = 30 ;
+}
+
+LLTextureSizeView::~LLTextureSizeView()
+{
+ if(mTextureSizeBar.size())
+ {
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ delete mTextureSizeBar[i] ;
+ }
+ mTextureSizeBar.clear() ;
+ }
+}
+void LLTextureSizeView::draw()
+{
+#if !LL_RELEASE_FOR_DOWNLOAD
+ if(mTextureSizeBar.size() == 0)
+ {
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;
+ mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
+
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth ,
+ line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;
+ }
+ }
+
+ F32 size_bar_scale = drawTextureSizeDistributionGraph() ;
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ;
+ mTextureSizeBar[i]->draw() ;
+ }
+ LLImageGL::resetCurTexSizebar();
+
+ LLView::draw();
+#endif
+}
+
+BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask)
+{
+ if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight)
+ {
+ mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask) ;
+ }
+
+ return TRUE ;
+}
+
+//draw background of texture size bar graph
+F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
+{
+ F32 scale = 1.0f ;
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLGLSUIDefault gls_ui;
+
+ //scale
+ {
+ S32 count = 0 ;
+ for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++)
+ {
+ if(LLImageGL::sTextureLoadedCounter[i] > count)
+ {
+ count = LLImageGL::sTextureLoadedCounter[i] ;
+ }
+ }
+ if(count > mTextureSizeBarRect.getHeight())
+ {
+ scale = (F32)mTextureSizeBarRect.getHeight() / count ;
+ }
+ }
+
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 left = mTextureSizeBarRect.mLeft ;
+ S32 bottom = mTextureSizeBarRect.mBottom ;
+ S32 right = mTextureSizeBarRect.mRight ;
+ S32 top = mTextureSizeBarRect.mTop ;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ //background rect
+ gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
+
+ //--------------------------------------------------
+ gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
+ gl_line_2d(left, bottom, right, bottom) ; //x axis
+ gl_line_2d(left, bottom, left, top) ; //y axis
+
+ //ruler
+ //--------------------------------------------------
+ gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
+ for(S32 i = bottom + 50 ; i <= top ; i += 50)
+ {
+ gl_line_2d(left, i, right, i) ;
+ }
+
+ //texts
+ //--------------------------------------------------
+ F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+ std::string text;
+
+ //-------
+ //x axis: size label
+ text = llformat("%d", 0) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
+ {
+ text = llformat("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+ text = llformat("(w + h)/2") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ //-------
+
+ //y axis: number label
+ for(S32 i = bottom + 50 ; i <= top ; i += 50)
+ {
+ text = llformat("%d", (S32)((i - bottom) / scale)) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ //--------------------------------------------------
+ F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
+ gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
+ text = llformat("Loaded") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
+ loaded_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
+ gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
+ text = llformat("Bound") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
+ bound_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ //--------------------------------------------------
+
+ //title
+ text = llformat("Texture Size Distribution") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+#endif
+ return scale ;
+}
diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h
index 20be17aef4..e917c0235e 100644
--- a/indra/newview/lltextureview.h
+++ b/indra/newview/lltextureview.h
@@ -78,5 +78,25 @@ public:
static std::set<LLViewerFetchedTexture*> sDebugImages;
};
+class LLGLTexSizeBar;
+
+class LLTextureSizeView : public LLView
+{
+public:
+ LLTextureSizeView(const Params&);
+ ~LLTextureSizeView();
+
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) ;
+
+private:
+ F32 drawTextureSizeDistributionGraph() ;
+
+private:
+ std::vector<LLGLTexSizeBar*> mTextureSizeBar ;
+ LLRect mTextureSizeBarRect ;
+ S32 mTextureSizeBarWidth ;
+};
extern LLTextureView *gTextureView;
+extern LLTextureSizeView *gTextureSizeView;
#endif // LL_TEXTURE_VIEW_H
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index be6e539ffd..328653d2b8 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -74,13 +74,12 @@ public:
static void selectionPropertiesReceived();
static void showAvatarInspector(const LLUUID& id);
-
private:
BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y);
BOOL pickLeftMouseDownCallback();
BOOL pickRightMouseDownCallback();
BOOL useClickAction (MASK mask, LLViewerObject* object,LLViewerObject* parent);
-
+
void showVisualContextMenuEffect();
private:
BOOL mGrabMouseButtonDown;
@@ -90,6 +89,7 @@ private:
LLPointer<LLViewerObject> mClickActionObject;
U8 mClickAction;
LLSafeHandle<LLObjectSelection> mLeftClickSelection;
+
};
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 3f3c10a7c7..1c2894dc37 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -56,6 +56,8 @@
// System includes
#include <iomanip> // for setprecision
+U32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
//glu pick matrix implementation borrowed from Mesa3D
glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport)
{
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index b99dd39584..90b77f771f 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -55,6 +55,24 @@ const BOOL NOT_FOR_SELECTION = FALSE;
class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera>
{
public:
+
+ typedef enum
+ {
+ CAMERA_WORLD = 0,
+ CAMERA_SHADOW0,
+ CAMERA_SHADOW1,
+ CAMERA_SHADOW2,
+ CAMERA_SHADOW3,
+ CAMERA_SHADOW4,
+ CAMERA_SHADOW5,
+ CAMERA_WATER0,
+ CAMERA_WATER1,
+ CAMERA_GI_SOURCE,
+ NUM_CAMERAS
+ } eCameraID;
+
+ static U32 sCurCameraID;
+
LLViewerCamera();
void updateCameraLocation(const LLVector3 &center,
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index be832ebe32..b888560fc7 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -493,6 +493,8 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("EnableRippleWater")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
@@ -523,6 +525,8 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2));
gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2));
gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));
gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2));
gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 6d2482d3f0..a6a72e9666 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -125,6 +125,11 @@ void display_startup()
return;
}
+ gPipeline.updateGL();
+
+ // Update images?
+ //gImageList.updateImages(0.01f);
+
LLGLSDefault gls_default;
// Required for HTML update in login screen
@@ -558,6 +563,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
stop_glerror();
}
+ gPipeline.updateGL();
+ stop_glerror();
+
S32 water_clip = 0;
if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))
@@ -606,6 +614,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLGLState::checkClientArrays();
static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
stop_glerror();
@@ -647,6 +656,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
}
+ LLVertexBuffer::unbind();
+
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
@@ -678,6 +689,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
+ gPipeline.generateHighlight(*LLViewerCamera::getInstance());
}
//////////////////////////////////////
@@ -702,6 +714,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame)
gTextureList.updateImages(max_image_decode_time);
+
+ //remove dead textures from GL
+ LLImageGL::deleteDeadTextures();
stop_glerror();
}
llpushcallstacks ;
@@ -715,6 +730,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
//
LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
{
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
stop_glerror();
@@ -797,6 +813,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
gPipeline.mDeferredScreen.bindTarget();
+ glClearColor(0,0,0,0);
gPipeline.mDeferredScreen.clear();
}
else
@@ -813,6 +830,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
&& !gRestoreGL)
{
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM);
gGL.setColorMask(true, false);
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
@@ -831,6 +849,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
for (U32 i = 0; i < 16; i++)
{
gGLLastModelView[i] = gGLModelView[i];
+ gGLLastProjection[i] = gGLProjection[i];
}
stop_glerror();
}
@@ -870,6 +889,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
render_ui();
}
+ gPipeline.rebuildGroups();
+
LLSpatialGroup::sNoDelete = FALSE;
}
@@ -944,6 +965,7 @@ void render_hud_attachments()
static LLCullResult result;
LLSpatialGroup::sNoDelete = TRUE;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
gPipeline.updateCull(hud_cam, result);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
@@ -951,6 +973,15 @@ void render_hud_attachments()
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
gPipeline.stateSort(hud_cam, result);
@@ -1259,7 +1290,73 @@ void render_ui_2d()
glPopMatrix();
stop_glerror();
}
- gViewerWindow->draw();
+
+
+ if (gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ if (LLUI::sDirty)
+ {
+ LLUI::sDirty = FALSE;
+ LLRect t_rect;
+
+ gPipeline.mUIScreen.bindTarget();
+ gGL.setColorMask(true, true);
+ {
+ static const S32 pad = 8;
+
+ LLUI::sDirtyRect.mLeft -= pad;
+ LLUI::sDirtyRect.mRight += pad;
+ LLUI::sDirtyRect.mBottom -= pad;
+ LLUI::sDirtyRect.mTop += pad;
+
+ LLGLEnable scissor(GL_SCISSOR_TEST);
+ static LLRect last_rect = LLUI::sDirtyRect;
+
+ //union with last rect to avoid mouse poop
+ last_rect.unionWith(LLUI::sDirtyRect);
+
+ t_rect = LLUI::sDirtyRect;
+ LLUI::sDirtyRect = last_rect;
+ last_rect = t_rect;
+
+ last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
+ last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
+
+ LLRect clip_rect(last_rect);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ gViewerWindow->draw();
+ }
+
+ gPipeline.mUIScreen.flush();
+ gGL.setColorMask(true, false);
+
+ LLUI::sDirtyRect = t_rect;
+
+ }
+
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+ S32 width = gViewerWindow->getWindowWidth();
+ S32 height = gViewerWindow->getWindowHeight();
+ gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.color4f(1,1,1,1);
+ gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
+ gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0);
+ gGL.texCoord2f(0, height); gGL.vertex2i(0, height);
+ gGL.texCoord2f(width, height); gGL.vertex2i(width, height);
+ gGL.end();
+ }
+ else
+ {
+ gViewerWindow->draw();
+ }
+
+
// reset current origin for font rendering, in case of tiling render
LLFontGL::sCurOrigin.set(0, 0);
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 28f883312a..cd60a8d560 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -564,7 +564,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
// Ignore the warning if that's the case.
if (!gSavedSettings.getBOOL("RenderUnloadedAvatar"))
{
- llwarns << "Layerset without composite" << llendl;
+ //llwarns << "Layerset without composite" << llendl;
}
gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
@@ -576,6 +576,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
{
old_mode = mTexture->getAddressMode();
}
+ gGL.getTexUnit(0)->bind(mTexture.get());
gGL.getTexUnit(0)->bind(mTexture);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 12d5687877..70f2331efa 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -979,6 +979,10 @@ U32 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME;
}
+ else if ("raycast" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_RAYCAST;
+ }
else if ("agent target" == info_display)
{
return LLPipeline::RENDER_DEBUG_AGENT_TARGET;
@@ -1172,6 +1176,29 @@ class LLAdvancedCheckDisableTextures : public view_listener_t
}
};
+//////////////////////
+// TEXTURE ATLAS //
+//////////////////////
+
+class LLAdvancedToggleTextureAtlas : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerTexture::sUseTextureAtlas = !LLViewerTexture::sUseTextureAtlas;
+ gSavedSettings.setBOOL("EnableTextureAtlas", LLViewerTexture::sUseTextureAtlas) ;
+ return true;
+ }
+};
+
+class LLAdvancedCheckTextureAtlas : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLViewerTexture::sUseTextureAtlas; // <-- make this using LLCacheControl
+ return new_value;
+ }
+};
+
//////////////////////////
// DUMP SCRIPTED CAMERA //
//////////////////////////
@@ -2145,11 +2172,48 @@ class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t
bool handleEvent(const LLSD& userdata)
{
- bool new_value = gGLManager.mHasOcclusionQuery && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
+ bool new_value = gGLManager.mHasOcclusionQuery; // && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
return new_value;
}
};
+/////////////////////////////////////
+// Enable Framebuffer Objects ///
+/////////////////////////////////////
+class LLAdvancedEnableRenderFBO: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gGLManager.mHasFramebufferObject;
+ return new_value;
+ }
+};
+
+/////////////////////////////////////
+// Enable Deferred Rendering ///
+/////////////////////////////////////
+class LLAdvancedEnableRenderDeferred: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT > 0) &&
+ LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
+ return new_value;
+ }
+};
+
+/////////////////////////////////////
+// Enable Global Illumination ///
+/////////////////////////////////////
+class LLAdvancedEnableRenderDeferredGI: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && gSavedSettings.getBOOL("RenderDeferred");
+ return new_value;
+ }
+};
+
//////////////////
@@ -7792,7 +7856,12 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
view_listener_t::addMenu(new LLAdvancedToggleDisableTextures(), "Advanced.ToggleDisableTextures");
view_listener_t::addMenu(new LLAdvancedCheckDisableTextures(), "Advanced.CheckDisableTextures");
+ view_listener_t::addMenu(new LLAdvancedToggleTextureAtlas(), "Advanced.ToggleTextureAtlas");
+ view_listener_t::addMenu(new LLAdvancedCheckTextureAtlas(), "Advanced.CheckTextureAtlas");
view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion");
+ view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO");
+ view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred");
+ view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredGI(), "Advanced.EnableRenderDeferredGI");
view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 7e2183f1f3..e37bad6b0e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3267,7 +3267,6 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data)
// Update the object...
gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL);
- stop_glerror();
}
void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data)
@@ -3285,7 +3284,6 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
// Update the object...
gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED);
- stop_glerror();
}
void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
@@ -3303,7 +3301,6 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
// Update the object...
gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED);
- stop_glerror();
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index cf77f7e2b6..8c223557bf 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2803,6 +2803,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable)
return TRUE;
}
+void LLViewerObject::updateGL()
+{
+
+}
+
void LLViewerObject::updateFaceSize(S32 idx)
{
@@ -4188,6 +4193,11 @@ void LLViewerObject::updateText()
}
}
+LLVOAvatar* LLViewerObject::asAvatar()
+{
+ return NULL;
+}
+
BOOL LLViewerObject::isParticleSource() const
{
return !mPartSourcep.isNull() && !mPartSourcep->isDead();
@@ -4494,7 +4504,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
new_block = new LLSculptParams();
break;
}
-
+ case LLNetworkData::PARAMS_LIGHT_IMAGE:
+ {
+ new_block = new LLLightImageParams();
+ break;
+ }
default:
{
llinfos << "Unknown param type." << llendl;
@@ -4585,7 +4599,7 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_
bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin)
{
ExtraParameter* param = getExtraParameterEntryCreate(param_type);
- if (param->in_use != in_use)
+ if (param && param->in_use != in_use)
{
param->in_use = in_use;
parameterChanged(param_type, param->data, in_use, local_origin);
@@ -4998,7 +5012,7 @@ U32 LLViewerObject::getPartitionType() const
return LLViewerRegion::PARTITION_NONE;
}
-void LLViewerObject::dirtySpatialGroup() const
+void LLViewerObject::dirtySpatialGroup(BOOL priority) const
{
if (mDrawable)
{
@@ -5006,6 +5020,7 @@ void LLViewerObject::dirtySpatialGroup() const
if (group)
{
group->dirtyGeom();
+ gPipeline.markRebuild(group, priority);
}
}
}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 836e05728f..08e2ec47cd 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -75,6 +75,7 @@ class LLViewerPartSourceScript;
class LLViewerRegion;
class LLViewerObjectMedia;
class LLVOInventoryListener;
+class LLVOAvatar;
typedef enum e_object_update_type
{
@@ -117,7 +118,7 @@ public:
//============================================================================
-class LLViewerObject : public LLPrimitive, public LLRefCount
+class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate
{
protected:
~LLViewerObject(); // use unref()
@@ -144,6 +145,8 @@ public:
BOOL isOrphaned() const { return mOrphaned; }
BOOL isParticleSource() const;
+ virtual LLVOAvatar* asAvatar();
+
static void initVOClasses();
static void cleanupVOClasses();
@@ -195,6 +198,7 @@ public:
virtual LLDrawable* createDrawable(LLPipeline *pipeline);
virtual BOOL updateGeometry(LLDrawable *drawable);
+ virtual void updateGL();
virtual void updateFaceSize(S32 idx);
virtual BOOL updateLOD();
virtual BOOL setDrawableParent(LLDrawable* parentp);
@@ -219,6 +223,7 @@ public:
virtual BOOL isFlexible() const { return FALSE; }
virtual BOOL isSculpted() const { return FALSE; }
+ virtual BOOL hasLightTexture() const { return FALSE; }
// This method returns true if the object is over land owned by
// the agent.
@@ -470,7 +475,7 @@ public:
virtual S32 getLOD() const { return 3; }
virtual U32 getPartitionType() const;
- virtual void dirtySpatialGroup() const;
+ virtual void dirtySpatialGroup(BOOL priority = FALSE) const;
virtual void dirtyMesh();
virtual LLNetworkData* getParameterEntry(U16 param_type) const;
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index 1a91240abb..9896adad97 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -53,6 +53,8 @@
#include "llselectmgr.h"
#include "llfloatertools.h"
#include "llglheaders.h"
+#include "pipeline.h"
+
const U8 OVERLAY_IMG_COMPONENTS = 4;
@@ -72,8 +74,6 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
// Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges
mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS);
mTexture = LLViewerTextureManager::getLocalTexture(mImageRaw.get(), FALSE);
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->bind(mTexture);
mTexture->setAddressMode(LLTexUnit::TAM_CLAMP);
mTexture->setFilteringOption(LLTexUnit::TFO_POINT);
@@ -87,7 +87,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
{
raw[i] = 0;
}
- mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
+ //mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
// Create storage for ownership information from simulator
// and initialize it.
@@ -97,8 +97,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
mOwnership[i] = PARCEL_PUBLIC;
}
- // Make sure the texture matches the ownership information.
- updateOverlayTexture();
+ gPipeline.markGLRebuild(this);
}
@@ -283,6 +282,10 @@ void LLViewerParcelOverlay::updateOverlayTexture()
// Copy data into GL texture from raw data
if (i >= COUNT)
{
+ if (!mTexture->hasGLTexture())
+ {
+ mTexture->createGLTexture(0, mImageRaw);
+ }
mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
mOverlayTextureIdx = -1;
}
@@ -709,6 +712,11 @@ void LLViewerParcelOverlay::setDirty()
mDirty = TRUE;
}
+void LLViewerParcelOverlay::updateGL()
+{
+ updateOverlayTexture();
+}
+
void LLViewerParcelOverlay::idleUpdate(bool force_update)
{
LLMemType mt_iup(LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY);
@@ -719,7 +727,7 @@ void LLViewerParcelOverlay::idleUpdate(bool force_update)
if (mOverlayTextureIdx >= 0 && (!(mDirty && force_update)))
{
// We are in the middle of updating the overlay texture
- updateOverlayTexture();
+ gPipeline.markGLRebuild(this);
return;
}
// Only if we're dirty and it's been a while since the last update.
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index e673b811ed..161b7a386b 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -40,13 +40,14 @@
#include "llframetimer.h"
#include "lluuid.h"
#include "llviewertexture.h"
+#include "llgl.h"
class LLViewerRegion;
class LLVector3;
class LLColor4U;
class LLVector2;
-class LLViewerParcelOverlay
+class LLViewerParcelOverlay : public LLGLUpdate
{
public:
LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters);
@@ -76,6 +77,7 @@ public:
void setDirty();
void idleUpdate(bool update_now = false);
+ void updateGL();
private:
// This is in parcel rows and columns, not grid rows and columns
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index a8cbcd86c6..4752bf1a85 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -101,7 +101,7 @@ LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp)
mSourceObjectp = source_objp;
mPosAgent = mSourceObjectp->getPositionAgent();
mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
- gGL.getTexUnit(0)->bind(mImagep);
+
mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
}
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index b5bd2f93af..6dc9f5c465 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -104,6 +104,7 @@ LLGLSLShader gPostNightVisionProgram;
// Deferred rendering shaders
LLGLSLShader gDeferredImpostorProgram;
+LLGLSLShader gDeferredEdgeProgram;
LLGLSLShader gDeferredWaterProgram;
LLGLSLShader gDeferredDiffuseProgram;
LLGLSLShader gDeferredBumpProgram;
@@ -113,6 +114,8 @@ LLGLSLShader gDeferredAvatarProgram;
LLGLSLShader gDeferredAvatarAlphaProgram;
LLGLSLShader gDeferredLightProgram;
LLGLSLShader gDeferredMultiLightProgram;
+LLGLSLShader gDeferredSpotLightProgram;
+LLGLSLShader gDeferredMultiSpotLightProgram;
LLGLSLShader gDeferredSunProgram;
LLGLSLShader gDeferredBlurLightProgram;
LLGLSLShader gDeferredSoftenProgram;
@@ -120,6 +123,13 @@ LLGLSLShader gDeferredShadowProgram;
LLGLSLShader gDeferredAvatarShadowProgram;
LLGLSLShader gDeferredAlphaProgram;
LLGLSLShader gDeferredFullbrightProgram;
+LLGLSLShader gDeferredGIProgram;
+LLGLSLShader gDeferredGIFinalProgram;
+LLGLSLShader gDeferredPostGIProgram;
+LLGLSLShader gDeferredPostProgram;
+
+LLGLSLShader gLuminanceGatherProgram;
+
//current avatar shader parameter pointer
GLint gAvatarMatrixParam;
@@ -151,6 +161,11 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredMultiLightProgram);
mShaderList.push_back(&gDeferredAlphaProgram);
mShaderList.push_back(&gDeferredFullbrightProgram);
+ mShaderList.push_back(&gDeferredPostGIProgram);
+ mShaderList.push_back(&gDeferredEdgeProgram);
+ mShaderList.push_back(&gDeferredPostProgram);
+ mShaderList.push_back(&gDeferredGIProgram);
+ mShaderList.push_back(&gDeferredGIFinalProgram);
mShaderList.push_back(&gDeferredWaterProgram);
mShaderList.push_back(&gDeferredAvatarAlphaProgram);
}
@@ -220,13 +235,35 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)
mReservedUniforms.push_back("shadowMap1");
mReservedUniforms.push_back("shadowMap2");
mReservedUniforms.push_back("shadowMap3");
+ mReservedUniforms.push_back("shadowMap4");
+ mReservedUniforms.push_back("shadowMap5");
+
mReservedUniforms.push_back("normalMap");
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
mReservedUniforms.push_back("noiseMap");
+ mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
-
+ mReservedUniforms.push_back("luminanceMap");
+ mReservedUniforms.push_back("giLightMap");
+ mReservedUniforms.push_back("giMip");
+ mReservedUniforms.push_back("edgeMap");
+ mReservedUniforms.push_back("bloomMap");
+ mReservedUniforms.push_back("sunLightMap");
+ mReservedUniforms.push_back("localLightMap");
+ mReservedUniforms.push_back("projectionMap");
+ mReservedUniforms.push_back("diffuseGIMap");
+ mReservedUniforms.push_back("specularGIMap");
+ mReservedUniforms.push_back("normalGIMap");
+ mReservedUniforms.push_back("minpGIMap");
+ mReservedUniforms.push_back("maxpGIMap");
+ mReservedUniforms.push_back("depthGIMap");
+ mReservedUniforms.push_back("lastDiffuseGIMap");
+ mReservedUniforms.push_back("lastNormalGIMap");
+ mReservedUniforms.push_back("lastMinpGIMap");
+ mReservedUniforms.push_back("lastMaxpGIMap");
+
mWLUniforms.push_back("camPosLocal");
mTerrainUniforms.reserve(5);
@@ -340,7 +377,21 @@ void LLViewerShaderMgr::setShaders()
if (LLPipeline::sRenderDeferred)
{
- deferred_class = 1;
+ if (gSavedSettings.getBOOL("RenderDeferredShadow"))
+ {
+ if (gSavedSettings.getBOOL("RenderDeferredGI"))
+ { //shadows + gi
+ deferred_class = 3;
+ }
+ else
+ { //shadows
+ deferred_class = 2;
+ }
+ }
+ else
+ { //no shadows
+ deferred_class = 1;
+ }
}
if(!gSavedSettings.getBOOL("EnableRippleWater"))
@@ -814,6 +865,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTerrainProgram.unload();
gDeferredLightProgram.unload();
gDeferredMultiLightProgram.unload();
+ gDeferredSpotLightProgram.unload();
+ gDeferredMultiSpotLightProgram.unload();
gDeferredSunProgram.unload();
gDeferredBlurLightProgram.unload();
gDeferredSoftenProgram.unload();
@@ -823,6 +876,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaProgram.unload();
gDeferredAlphaProgram.unload();
gDeferredFullbrightProgram.unload();
+ gDeferredPostGIProgram.unload();
+ gDeferredEdgeProgram.unload();
+ gDeferredPostProgram.unload();
+ gLuminanceGatherProgram.unload();
+ gDeferredGIProgram.unload();
+ gDeferredGIFinalProgram.unload();
gDeferredWaterProgram.unload();
return FALSE;
}
@@ -893,6 +952,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader";
+ gDeferredSpotLightProgram.mShaderFiles.clear();
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredSpotLightProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";
+ gDeferredMultiSpotLightProgram.mShaderFiles.clear();
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
gDeferredSunProgram.mName = "Deferred Sun Shader";
gDeferredSunProgram.mShaderFiles.clear();
gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1022,6 +1101,72 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
}
+ if (mVertexShaderLevel[SHADER_DEFERRED] > 1)
+ {
+ if (success)
+ {
+ gDeferredEdgeProgram.mName = "Deferred Edge Shader";
+ gDeferredEdgeProgram.mShaderFiles.clear();
+ gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredEdgeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredEdgeProgram.createShader(NULL, NULL);
+ }
+ }
+
+ if (mVertexShaderLevel[SHADER_DEFERRED] > 2)
+ {
+ if (success)
+ {
+ gDeferredPostProgram.mName = "Deferred Post Shader";
+ gDeferredPostProgram.mShaderFiles.clear();
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredPostProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredPostGIProgram.mName = "Deferred Post GI Shader";
+ gDeferredPostGIProgram.mShaderFiles.clear();
+ gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredPostGIProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredGIProgram.mName = "Deferred GI Shader";
+ gDeferredGIProgram.mShaderFiles.clear();
+ gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredGIProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredGIFinalProgram.mName = "Deferred GI Final Shader";
+ gDeferredGIFinalProgram.mShaderFiles.clear();
+ gDeferredGIFinalProgram.mShaderFiles.push_back(make_pair("deferred/giFinalV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredGIFinalProgram.mShaderFiles.push_back(make_pair("deferred/giFinalF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredGIFinalProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredGIFinalProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gLuminanceGatherProgram.mName = "Luminance Gather Shader";
+ gLuminanceGatherProgram.mShaderFiles.clear();
+ gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceV.glsl", GL_VERTEX_SHADER_ARB));
+ gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gLuminanceGatherProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gLuminanceGatherProgram.createShader(NULL, NULL);
+ }
+ }
+
return success;
}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index a743966d93..ac2b4624e0 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -116,12 +116,33 @@ public:
DEFERRED_SHADOW1,
DEFERRED_SHADOW2,
DEFERRED_SHADOW3,
+ DEFERRED_SHADOW4,
+ DEFERRED_SHADOW5,
DEFERRED_NORMAL,
DEFERRED_POSITION,
DEFERRED_DIFFUSE,
DEFERRED_SPECULAR,
DEFERRED_NOISE,
+ DEFERRED_LIGHTFUNC,
DEFERRED_LIGHT,
+ DEFERRED_LUMINANCE,
+ DEFERRED_GI_LIGHT,
+ DEFERRED_GI_MIP,
+ DEFERRED_EDGE,
+ DEFERRED_BLOOM,
+ DEFERRED_SUN_LIGHT,
+ DEFERRED_LOCAL_LIGHT,
+ DEFERRED_PROJECTION,
+ DEFERRED_GI_DIFFUSE,
+ DEFERRED_GI_SPECULAR,
+ DEFERRED_GI_NORMAL,
+ DEFERRED_GI_MIN_POS,
+ DEFERRED_GI_MAX_POS,
+ DEFERRED_GI_DEPTH,
+ DEFERRED_GI_LAST_DIFFUSE,
+ DEFERRED_GI_LAST_NORMAL,
+ DEFERRED_GI_LAST_MIN_POS,
+ DEFERRED_GI_LAST_MAX_POS,
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
@@ -319,6 +340,7 @@ extern LLGLSLShader gPostNightVisionProgram;
// Deferred rendering shaders
extern LLGLSLShader gDeferredImpostorProgram;
+extern LLGLSLShader gDeferredEdgeProgram;
extern LLGLSLShader gDeferredWaterProgram;
extern LLGLSLShader gDeferredDiffuseProgram;
extern LLGLSLShader gDeferredBumpProgram;
@@ -326,16 +348,24 @@ extern LLGLSLShader gDeferredTerrainProgram;
extern LLGLSLShader gDeferredTreeProgram;
extern LLGLSLShader gDeferredLightProgram;
extern LLGLSLShader gDeferredMultiLightProgram;
+extern LLGLSLShader gDeferredSpotLightProgram;
+extern LLGLSLShader gDeferredMultiSpotLightProgram;
extern LLGLSLShader gDeferredSunProgram;
+extern LLGLSLShader gDeferredGIProgram;
+extern LLGLSLShader gDeferredGIFinalProgram;
extern LLGLSLShader gDeferredBlurLightProgram;
extern LLGLSLShader gDeferredAvatarProgram;
extern LLGLSLShader gDeferredSoftenProgram;
extern LLGLSLShader gDeferredShadowProgram;
+extern LLGLSLShader gDeferredPostGIProgram;
+extern LLGLSLShader gDeferredPostProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredFullbrightProgram;
extern LLGLSLShader gDeferredAvatarAlphaProgram;
+extern LLGLSLShader gLuminanceGatherProgram;
+
//current avatar shader parameter pointer
extern GLint gAvatarMatrixParam;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index c479a232c5..e3d657068f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -60,6 +60,8 @@
#include "llviewercontrol.h"
#include "pipeline.h"
#include "llappviewer.h"
+#include "lltextureatlas.h"
+#include "lltextureatlasmanager.h"
///////////////////////////////////////////////////////////////////////////////
// statics
@@ -83,6 +85,7 @@ S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
BOOL LLViewerTexture::sDontLoadVolumeTextures = FALSE;
+BOOL LLViewerTexture::sUseTextureAtlas = FALSE ;
const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by
@@ -368,6 +371,7 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
}
}
sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max);
+ LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ;
}
//end of static functions
@@ -667,7 +671,7 @@ LLGLuint LLViewerTexture::getTexName() const
return mGLTexturep->getTexName() ;
}
-BOOL LLViewerTexture::hasValidGLTexture() const
+BOOL LLViewerTexture::hasGLTexture() const
{
if(mGLTexturep.notNull())
{
@@ -676,11 +680,6 @@ BOOL LLViewerTexture::hasValidGLTexture() const
return FALSE ;
}
-BOOL LLViewerTexture::hasGLTexture() const
-{
- return mGLTexturep.notNull() ;
-}
-
BOOL LLViewerTexture::getBoundRecently() const
{
if(mGLTexturep.notNull())
@@ -779,6 +778,34 @@ BOOL LLViewerTexture::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool
return mGLTexturep->readBackRaw(discard_level, imageraw, compressed_ok) ;
}
+U32 LLViewerTexture::getTexelsInAtlas() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInAtlas() ;
+}
+
+U32 LLViewerTexture::getTexelsInGLTexture() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInGLTexture() ;
+}
+
+BOOL LLViewerTexture::isGLTextureCreated() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->isGLTextureCreated() ;
+}
+
+S32 LLViewerTexture::getDiscardLevelInAtlas() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getDiscardLevelInAtlas() ;
+}
+
void LLViewerTexture::destroyGLTexture()
{
if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
@@ -796,6 +823,7 @@ void LLViewerTexture::updateBindStatsForTester()
LLViewerTextureManager::sTesterp->updateTextureBindingStats(this) ;
}
}
+
//----------------------------------------------------------------------------------------------
//end of LLViewerTexture
//----------------------------------------------------------------------------------------------
@@ -1044,7 +1072,11 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
return FALSE;
}
- res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename);
+ if(!(res = insertToAtlas()))
+ {
+ res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename);
+ resetFaceAtlas() ;
+ }
setActive() ;
}
@@ -1741,6 +1773,197 @@ void LLViewerFetchedTexture::destroyRawImage()
mIsRawImageValid = FALSE;
mRawDiscardLevel = INVALID_DISCARD_LEVEL;
}
+
+//----------------------------------------------------------------------------------------------
+//atlasing
+//----------------------------------------------------------------------------------------------
+void LLViewerFetchedTexture::resetFaceAtlas()
+{
+ //Nothing should be done here.
+}
+
+//invalidate all atlas slots for this image.
+void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom)
+{
+ for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
+ {
+ if(*iter)
+ {
+ LLFace* facep = (LLFace*)*iter ;
+ facep->removeAtlas() ;
+ if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup())
+ {
+ facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY);
+ }
+ }
+ }
+}
+
+BOOL LLViewerFetchedTexture::insertToAtlas()
+{
+ if(!LLViewerTexture::sUseTextureAtlas)
+ {
+ return FALSE ;
+ }
+ if(mFaceList.size() < 1)
+ {
+ return FALSE ;
+ }
+ if(mGLTexturep->getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= mGLTexturep->getDiscardLevelInAtlas())
+ {
+ return FALSE ;
+ }
+ if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), mGLTexturep->getTexTarget()))
+ {
+ return FALSE ;
+ }
+
+ BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image.
+ S32 raw_w = mRawImage->getWidth() ;
+ S32 raw_h = mRawImage->getHeight() ;
+ F32 xscale = 1.0f, yscale = 1.0f ;
+ LLPointer<LLTextureAtlasSlot> slot_infop;
+ LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer.
+ LLSpatialGroup* groupp ;
+ LLFace* facep;
+
+ //if the atlas slot pointers for some faces are null, process them later.
+ ll_face_list_t waiting_list ;
+
+ for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter)
+ {
+ if(*iter)
+ {
+ facep = (LLFace*)*iter ;
+
+ //face can not use atlas.
+ if(!facep->canUseAtlas())
+ {
+ if(facep->getAtlasInfo())
+ {
+ facep->removeAtlas() ;
+ }
+ ret = FALSE ;
+ continue ;
+ }
+
+ //the atlas slot is updated
+ slot_infop = facep->getAtlasInfo() ;
+ groupp = facep->getDrawable()->getSpatialGroup() ;
+
+ if(slot_infop)
+ {
+ if(slot_infop->getSpatialGroup() != groupp)
+ {
+ if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot
+ {
+ facep->setAtlasInfo(cur_slotp) ;
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+ else //do not forget to update slot_infop->getSpatialGroup().
+ {
+ LLSpatialGroup* gp = slot_infop->getSpatialGroup() ;
+ gp->setCurUpdatingTime(gFrameCount) ;
+ gp->setCurUpdatingTexture(this) ;
+ gp->setCurUpdatingSlot(slot_infop) ;
+ }
+ }
+ else //same group
+ {
+ if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated
+ {
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+ }
+ }
+ else
+ {
+ //if the slot is null, wait to process them later.
+ waiting_list.push_back(facep) ;
+ continue ;
+ }
+
+ //----------
+ //insert to atlas
+ if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
+ {
+
+ //the texture does not qualify to add to atlas, do not bother to try for other faces.
+ //invalidateAtlas();
+ return FALSE ;
+ }
+
+ //update texture scale
+ slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
+ slot_infop->setTexCoordScale(xscale, yscale) ;
+ slot_infop->setValid() ;
+ slot_infop->setUpdatedTime(gFrameCount) ;
+
+ //update spatial group atlas info
+ groupp->setCurUpdatingTime(gFrameCount) ;
+ groupp->setCurUpdatingTexture(this) ;
+ groupp->setCurUpdatingSlot(slot_infop) ;
+
+ //make the face to switch to the atlas.
+ facep->setAtlasInUse(TRUE) ;
+ }
+ }
+
+ //process the waiting_list
+ for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter)
+ {
+ facep = (LLFace*)*iter ;
+ groupp = facep->getDrawable()->getSpatialGroup() ;
+
+ //check if this texture already inserted to atlas for this group
+ if((cur_slotp = groupp->getCurUpdatingSlot(this)))
+ {
+ facep->setAtlasInfo(cur_slotp) ;
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+
+ //need to reserve a slot from atlas
+ slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ;
+
+ facep->setAtlasInfo(slot_infop) ;
+
+ groupp->setCurUpdatingTime(gFrameCount) ;
+ groupp->setCurUpdatingTexture(this) ;
+ groupp->setCurUpdatingSlot(slot_infop) ;
+
+ //slot allocation failed.
+ if(!slot_infop || !slot_infop->getAtlas())
+ {
+ ret = FALSE ;
+ facep->setAtlasInUse(FALSE) ;
+ continue ;
+ }
+
+ //insert to atlas
+ if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
+ {
+ //the texture does not qualify to add to atlas, do not bother to try for other faces.
+ ret = FALSE ;
+ //invalidateAtlas();
+ break ;
+ }
+
+ //update texture scale
+ slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
+ slot_infop->setTexCoordScale(xscale, yscale) ;
+ slot_infop->setValid() ;
+ slot_infop->setUpdatedTime(gFrameCount) ;
+
+ //make the face to switch to the atlas.
+ facep->setAtlasInUse(TRUE) ;
+ }
+
+ return ret ;
+}
+
//----------------------------------------------------------------------------------------------
//end of LLViewerFetchedTexture
//----------------------------------------------------------------------------------------------
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 142c212435..0be1bf81de 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -98,6 +98,7 @@ public:
DYNAMIC_TEXTURE,
FETCHED_TEXTURE,
LOD_TEXTURE,
+ ATLAS_TEXTURE,
INVALID_TEXTURE_TYPE
};
@@ -171,7 +172,6 @@ public:
/*virtual*/S32 getHeight(S32 discard_level = -1) const;
BOOL hasGLTexture() const ;
- BOOL hasValidGLTexture() const ;
LLGLuint getTexName() const ;
BOOL createGLTexture() ;
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0);
@@ -197,6 +197,11 @@ public:
BOOL getMissed() const ;
BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ;
BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
+
+ U32 getTexelsInAtlas() const ;
+ U32 getTexelsInGLTexture() const ;
+ BOOL isGLTextureCreated() const ;
+ S32 getDiscardLevelInAtlas() const ;
//---------------------------------------------------------------------------------------------
//end of functions to access LLImageGL
//---------------------------------------------------------------------------------------------
@@ -263,6 +268,7 @@ public:
static S32 sMaxTotalTextureMemInMegaBytes;
static S32 sMaxDesiredTextureMemInBytes ;
static BOOL sDontLoadVolumeTextures;
+ static BOOL sUseTextureAtlas ;
static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
};
@@ -388,6 +394,11 @@ private:
F32 calcDecodePriorityForUnknownTexture(F32 pixel_priority) ;
+ //for atlas
+ void resetFaceAtlas() ;
+ void invalidateAtlas(BOOL rebuild_geom) ;
+ BOOL insertToAtlas() ;
+
private:
BOOL mFullyLoaded;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index f7fbe96aa7..fd6ffbe07a 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1898,6 +1898,11 @@ void LLViewerWindow::draw()
//S32 screen_x, screen_y;
+ if (!gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ LLUI::sDirtyRect = this->getWindowRect();
+ }
+
// HACK for timecode debugging
if (gSavedSettings.getBOOL("DisplayTimecode"))
{
@@ -3874,7 +3879,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
if(image_width > window_width || image_height > window_height) //need to enlarge the scene
{
- if (gGLManager.mHasFramebufferObject && !show_ui)
+ if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui)
{
GLint max_size = 0;
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
@@ -3962,9 +3967,17 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
else
{
const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
- display(do_rebuild, scale_factor, subfield, TRUE);
- // Required for showing the GUI in snapshots? See DEV-16350 for details. JC
- render_ui(scale_factor, subfield);
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ display(do_rebuild, scale_factor, subfield, FALSE);
+ }
+ else
+ {
+ display(do_rebuild, scale_factor, subfield, TRUE);
+ // Required for showing the GUI in snapshots? See DEV-16350 for details. JC
+ render_ui(scale_factor, subfield);
+ }
}
S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index f26ba6f46e..d124cbcdce 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -448,6 +448,10 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
}
}
+ if (!texturep->hasGLTexture())
+ {
+ texturep->createGLTexture(0, raw);
+ }
texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32();
LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 018cce4b49..1d9ca12af8 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -680,6 +680,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
}
mDirtyMesh = TRUE; // Dirty geometry, need to regenerate.
+ mMeshTexturesDirty = FALSE;
mShadow0Facep = NULL;
mShadow1Facep = NULL;
mHeadp = NULL;
@@ -718,8 +719,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRippleTimeLast = 0.f;
mShadowImagep = LLViewerTextureManager::getFetchedTextureFromFile("foot_shadow.j2c");
- gGL.getTexUnit(0)->bind(mShadowImagep);
- mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ // GL NOT ACTIVE HERE
+ //gGL.getTexUnit(0)->bind(mShadowImagep.get());
+ //mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
mInAir = FALSE;
@@ -1612,6 +1615,11 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
return TRUE;
}
+LLVOAvatar* LLVOAvatar::asAvatar()
+{
+ return this;
+}
+
//-----------------------------------------------------------------------------
// LLVOAvatar::startDefaultMotions()
//-----------------------------------------------------------------------------
@@ -2176,10 +2184,14 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
idleUpdateVoiceVisualizer( voice_enabled );
idleUpdateMisc( detailed_update );
idleUpdateAppearanceAnimation();
- idleUpdateLipSync( voice_enabled );
- idleUpdateLoadingEffect();
- idleUpdateBelowWater(); // wind effect uses this
- idleUpdateWindEffect();
+ if (detailed_update)
+ {
+ idleUpdateLipSync( voice_enabled );
+ idleUpdateLoadingEffect();
+ idleUpdateBelowWater(); // wind effect uses this
+ idleUpdateWindEffect();
+ }
+
idleUpdateNameTag( root_pos_last );
idleUpdateRenderCost();
idleUpdateTractorBeam();
@@ -3032,7 +3044,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
if (!visible)
{
- updateMotions(LLCharacter::HIDDEN_UPDATE);
+ //updateMotions(LLCharacter::HIDDEN_UPDATE);
return FALSE;
}
@@ -3702,7 +3714,8 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
if (pass == AVATAR_RENDER_PASS_SINGLE)
{
- const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha; // Don't alpha mask if "Highlight Transparent" checked
+ const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
+ && !LLDrawPoolAvatar::sSkipTransparent;
LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
@@ -3817,20 +3830,8 @@ U32 LLVOAvatar::renderRigid()
if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
{
- // If the meshes need to be drawn, enable alpha masking but not blending
- bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha;
-
- LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
-
- if (should_alpha_mask)
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
- }
-
num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
-
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
return num_indices;
@@ -3875,7 +3876,7 @@ U32 LLVOAvatar::renderFootShadows()
LLGLDepthTest test(GL_TRUE, GL_FALSE);
//render foot shadows
LLGLEnable blend(GL_BLEND);
- gGL.getTexUnit(0)->bind(mShadowImagep);
+ gGL.getTexUnit(0)->bind(mShadowImagep.get());
glColor4fv(mShadow0Facep->getRenderColor().mV);
mShadow0Facep->renderIndexed(foot_mask);
glColor4fv(mShadow1Facep->getRenderColor().mV);
@@ -3884,7 +3885,7 @@ U32 LLVOAvatar::renderFootShadows()
return num_indices;
}
-U32 LLVOAvatar::renderImpostor(LLColor4U color)
+U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
{
if (!mImpostor.isComplete())
{
@@ -3904,7 +3905,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color)
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
gGL.color4ubv(color.mV);
- gGL.getTexUnit(0)->bind(&mImpostor);
+ gGL.getTexUnit(diffuse_channel)->bind(&mImpostor);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0,0);
gGL.vertex3fv((pos+left-up).mV);
@@ -3942,6 +3943,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
}
std::vector<BOOL> layer_baked;
+ // GL NOT ACTIVE HERE - *TODO
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex));
@@ -5171,6 +5173,15 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
}
+void LLVOAvatar::updateGL()
+{
+ if (mMeshTexturesDirty)
+ {
+ updateMeshTextures();
+ mMeshTexturesDirty = FALSE;
+ }
+}
+
//-----------------------------------------------------------------------------
// updateGeometry()
//-----------------------------------------------------------------------------
@@ -5222,7 +5233,7 @@ void LLVOAvatar::updateShadowFaces()
sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f);
LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f);
- if (mShadowImagep->hasValidGLTexture())
+ if (mShadowImagep->hasGLTexture())
{
LLVector3 normal;
LLVector3d shadow_pos;
@@ -6354,7 +6365,8 @@ void LLVOAvatar::onFirstTEMessageReceived()
}
}
- updateMeshTextures();
+ mMeshTexturesDirty = TRUE;
+ gPipeline.markGLRebuild(this);
}
}
@@ -6417,6 +6429,8 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
}
setCompositeUpdatesEnabled( FALSE );
+ mMeshTexturesDirty = TRUE;
+ gPipeline.markGLRebuild(this);
// ! BACKWARDS COMPATIBILITY !
// Non-self avatars will no longer have component textures
@@ -6425,8 +6439,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
releaseComponentTextures();
}
- updateMeshTextures(); // enables updates for laysets without baked textures.
-
+
// parse visual params
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
if( num_blocks > 1 )
@@ -7436,6 +7449,11 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)
BOOL LLVOAvatar::updateLOD()
{
+ if (isImpostor())
+ {
+ return TRUE;
+ }
+
BOOL res = updateJointLODs();
LLFace* facep = mDrawable->getFace(0);
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 4dc70511ce..ef5358198d 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -114,6 +114,8 @@ protected:
// LLViewerObject interface and related
//--------------------------------------------------------------------
public:
+ virtual void updateGL();
+ virtual LLVOAvatar* asAvatar();
virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num,
@@ -329,7 +331,7 @@ private:
public:
U32 renderFootShadows();
- U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255));
+ U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
U32 renderRigid();
U32 renderSkinned(EAvatarRenderPass pass);
U32 renderTransparent(BOOL first_pass);
@@ -560,6 +562,7 @@ protected:
/*virtual*/ void restoreMeshData();
private:
BOOL mDirtyMesh;
+ BOOL mMeshTexturesDirty;
typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t;
polymesh_map_t mMeshes;
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index a7b5b60842..dfc82ea8d5 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1331,7 +1331,7 @@ void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const
{
S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
- if (image_gl->hasValidGLTexture())
+ if (image_gl->hasGLTexture())
{
*gl_bytes += bytes;
}
@@ -1539,7 +1539,7 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
// Check for the case that texture is defined but not sufficiently loaded to display anything.
LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex );
- if (!baked_img || !baked_img->hasValidGLTexture())
+ if (!baked_img || !baked_img->hasGLTexture())
{
loading = TRUE;
}
diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp
index 130e1fd749..8d3c8b6f1a 100644
--- a/indra/newview/llvoclouds.cpp
+++ b/indra/newview/llvoclouds.cpp
@@ -125,7 +125,10 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
return TRUE;
}
- dirtySpatialGroup();
+ if (drawable->isVisible())
+ {
+ dirtySpatialGroup(TRUE);
+ }
LLFace *facep;
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 38c9ce28c4..7585842623 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -155,6 +155,11 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
group = drawable->getSpatialGroup();
}
+ if (group && group->isVisible())
+ {
+ dirtySpatialGroup(TRUE);
+ }
+
if (!num_parts)
{
if (group && drawable->getNumFaces())
@@ -353,12 +358,11 @@ U32 LLVOPartGroup::getPartitionType() const
}
LLParticlePartition::LLParticlePartition()
-: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK)
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB)
{
mRenderPass = LLRenderPass::PASS_ALPHA;
mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
mPartitionType = LLViewerRegion::PARTITION_PARTICLE;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
mSlopRatio = 0.f;
mLODPeriod = 1;
}
@@ -485,7 +489,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
U32 end = start + facep->getGeomCount()-1;
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
- LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright);
+ LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),
+ //facep->getTexture(),
+ buffer, fullbright);
info->mExtents[0] = group->mObjectExtents[0];
info->mExtents[1] = group->mObjectExtents[1];
info->mVSize = vsize;
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index 157d719fcc..164f0f0cad 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -178,11 +178,19 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline)
static LLFastTimer::DeclareTimer FTM_UPDATE_TERRAIN("Update Terrain");
+void LLVOSurfacePatch::updateGL()
+{
+ if (mPatchp)
+ {
+ mPatchp->updateGL();
+ }
+}
+
BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
{
LLFastTimer ftm(FTM_UPDATE_TERRAIN);
- dirtySpatialGroup();
+ dirtySpatialGroup(TRUE);
S32 min_comp, max_comp, range;
min_comp = lltrunc(mPatchp->getMinComposition());
@@ -1014,12 +1022,10 @@ U32 LLVOSurfacePatch::getPartitionType() const
}
LLTerrainPartition::LLTerrainPartition()
-: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK)
+: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB)
{
mOcclusionEnabled = FALSE;
- mRenderByGroup = FALSE;
mInfiniteFarClip = TRUE;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN;
mPartitionType = LLViewerRegion::PARTITION_TERRAIN;
}
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index 2dd8651899..aaf4d41fa1 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -64,6 +64,7 @@ public:
virtual U32 getPartitionType() const;
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
+ /*virtual*/ void updateGL();
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ BOOL updateLOD();
/*virtual*/ void updateFaceSize(S32 idx);
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 86d9f31d07..615ae13bc2 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -312,10 +312,6 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,
// Load Species-Specific data
//
mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
- if (mTreeImagep)
- {
- gGL.getTexUnit(0)->bind(mTreeImagep);
- }
mBranchLength = sSpeciesTable[mSpecies]->mBranchLength;
mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength;
mLeafScale = sSpeciesTable[mSpecies]->mLeafScale;
@@ -1305,9 +1301,8 @@ U32 LLVOTree::getPartitionType() const
}
LLTreePartition::LLTreePartition()
-: LLSpatialPartition(0)
+: LLSpatialPartition(0, FALSE, 0)
{
- mRenderByGroup = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_TREE;
mPartitionType = LLViewerRegion::PARTITION_TREE;
mSlopRatio = 0.f;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 940accdd06..0217324808 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -69,8 +69,10 @@
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
+const F32 MAX_LOD_DISTANCE = 24.f;
const S32 MAX_SCULPT_REZ = 128;
+
BOOL gAnimateTextures = TRUE;
//extern BOOL gHideSelectedObjects;
@@ -97,6 +99,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mNumFaces = 0;
mLODChanged = FALSE;
mSculptChanged = FALSE;
+ mSpotLightPriority = 0.f;
}
LLVOVolume::~LLVOVolume()
@@ -320,11 +323,6 @@ void LLVOVolume::animateTextures()
te->getScale(&scale_s, &scale_t);
}
- LLVector3 scale(scale_s, scale_t, 1.f);
- LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f);
- LLQuaternion quat;
- quat.setQuat(rot, 0, 0, -1.f);
-
if (!facep->mTextureMatrix)
{
facep->mTextureMatrix = new LLMatrix4();
@@ -332,7 +330,43 @@ void LLVOVolume::animateTextures()
LLMatrix4& tex_mat = *facep->mTextureMatrix;
tex_mat.setIdentity();
- tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
+ LLVector3 trans ;
+
+ if(facep->isAtlasInUse())
+ {
+ //
+ //if use atlas for animated texture
+ //apply the following transform to the animation matrix.
+ //
+
+ F32 tcoord_xoffset = 0.f ;
+ F32 tcoord_yoffset = 0.f ;
+ F32 tcoord_xscale = 1.f ;
+ F32 tcoord_yscale = 1.f ;
+ if(facep->isAtlasInUse())
+ {
+ const LLVector2* tmp = facep->getTexCoordOffset() ;
+ tcoord_xoffset = tmp->mV[0] ;
+ tcoord_yoffset = tmp->mV[1] ;
+
+ tmp = facep->getTexCoordScale() ;
+ tcoord_xscale = tmp->mV[0] ;
+ tcoord_yscale = tmp->mV[1] ;
+ }
+ trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f));
+
+ tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f));
+ }
+ else //non atlas
+ {
+ trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
+ tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
+ }
+
+ LLVector3 scale(scale_s, scale_t, 1.f);
+ LLQuaternion quat;
+ quat.setQuat(rot, 0, 0, -1.f);
+
tex_mat.rotate(quat);
LLMatrix4 mat;
@@ -541,6 +575,19 @@ void LLVOVolume::updateTextures()
}
}
+ if (getLightTextureID().notNull())
+ {
+ LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ LLUUID id = params->getLightTexture();
+ mLightTexture = LLViewerTextureManager::getFetchedTexture(id);
+ if (mLightTexture.notNull())
+ {
+ F32 rad = getLightRadius();
+ mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(),
+ LLVector3(rad,rad,rad),
+ *LLViewerCamera::getInstance()));
+ }
+ }
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
{
@@ -711,7 +758,17 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
if (mSculptTexture.notNull())
{
- sculpt();
+ //ignore sculpt GL usage since bao fixed this in a separate branch
+ if (!gGLActive)
+ {
+ gGLActive = TRUE;
+ sculpt();
+ gGLActive = FALSE;
+ }
+ else
+ {
+ sculpt();
+ }
mSculptLevel = getVolume()->getSculptLevel();
}
}
@@ -836,12 +893,15 @@ BOOL LLVOVolume::calcLOD()
}
//update face texture sizes on lod calculation
- updateTextures();
+ //if (mDrawable->isVisible())
+ //{
+ // updateTextures();
+ //}
S32 cur_detail = 0;
F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
- F32 distance = mDrawable->mDistanceWRTCamera;
+ F32 distance = llmin(mDrawable->mDistanceWRTCamera, MAX_LOD_DISTANCE);
distance *= sDistanceFactor;
F32 rampDist = LLVOVolume::sLODFactor * 2;
@@ -1452,6 +1512,41 @@ void LLVOVolume::updateTEData()
//----------------------------------------------------------------------------
+void LLVOVolume::setLightTextureID(LLUUID id)
+{
+ if (id.notNull())
+ {
+ if (!hasLightTexture())
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true);
+ }
+ LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block && param_block->getLightTexture() != id)
+ {
+ param_block->setLightTexture(id);
+ parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);
+ }
+ }
+ else
+ {
+ if (hasLightTexture())
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true);
+ mLightTexture = NULL;
+ }
+ }
+}
+
+void LLVOVolume::setSpotLightParams(LLVector3 params)
+{
+ LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block && param_block->getParams() != params)
+ {
+ param_block->setParams(params);
+ parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);
+ }
+}
+
void LLVOVolume::setIsLight(BOOL is_light)
{
if (is_light != getIsLight())
@@ -1578,6 +1673,83 @@ LLColor3 LLVOVolume::getLightColor() const
}
}
+LLUUID LLVOVolume::getLightTextureID() const
+{
+ if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ {
+ const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block)
+ {
+ return param_block->getLightTexture();
+ }
+ }
+
+ return LLUUID::null;
+}
+
+
+LLVector3 LLVOVolume::getSpotLightParams() const
+{
+ if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ {
+ const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block)
+ {
+ return param_block->getParams();
+ }
+ }
+
+ return LLVector3();
+}
+
+F32 LLVOVolume::getSpotLightPriority() const
+{
+ return mSpotLightPriority;
+}
+
+void LLVOVolume::updateSpotLightPriority()
+{
+ LLVector3 pos = mDrawable->getPositionAgent();
+ LLVector3 at(0,0,-1);
+ at *= getRenderRotation();
+
+ F32 r = getLightRadius()*0.5f;
+
+ pos += at * r;
+
+ at = LLViewerCamera::getInstance()->getAtAxis();
+
+ pos -= at * r;
+
+ mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance());
+
+ if (mLightTexture.notNull())
+ {
+ mLightTexture->addTextureStats(mSpotLightPriority);
+ mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS);
+ }
+}
+
+
+LLViewerTexture* LLVOVolume::getLightTexture()
+{
+ LLUUID id = getLightTextureID();
+
+ if (id.notNull())
+ {
+ if (mLightTexture.isNull() || id != mLightTexture->getID())
+ {
+ mLightTexture = LLViewerTextureManager::getFetchedTexture(id);
+ }
+ }
+ else
+ {
+ mLightTexture = NULL;
+ }
+
+ return mLightTexture;
+}
+
F32 LLVOVolume::getLightIntensity() const
{
const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
@@ -1669,6 +1841,16 @@ BOOL LLVOVolume::isSculpted() const
return FALSE;
}
+BOOL LLVOVolume::hasLightTexture() const
+{
+ if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
BOOL LLVOVolume::isVolumeGlobal() const
{
if (mVolumeImpl)
@@ -2116,9 +2298,9 @@ U32 LLVOVolume::getPartitionType() const
}
LLVolumePartition::LLVolumePartition()
-: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE)
+: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB)
{
- mLODPeriod = 16;
+ mLODPeriod = 32;
mDepthMask = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_VOLUME;
@@ -2127,10 +2309,10 @@ LLVolumePartition::LLVolumePartition()
}
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
-: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK)
+: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK)
{
mDepthMask = FALSE;
- mLODPeriod = 16;
+ mLODPeriod = 32;
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
@@ -2154,8 +2336,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
S32 idx = draw_vec.size()-1;
- BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT ||
- type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE;
+ BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) ||
+ (type == LLRenderPass::PASS_ALPHA ? facep->isState(LLFace::FULLBRIGHT) : FALSE);
+
+ if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
+ {
+ llwarns << "Non fullbright face has no normals!" << llendl;
+ return;
+ }
const LLMatrix4* tex_mat = NULL;
if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
@@ -2218,7 +2406,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
U32 end = start + facep->getGeomCount()-1;
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
- LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset,tex,
+ LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
facep->mVertexBuffer, fullbright, bump);
draw_info->mGroup = group;
draw_info->mVSize = facep->getVirtualSize();
@@ -2246,11 +2434,6 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
- if (LLPipeline::sSkipUpdate)
- {
- return;
- }
-
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
@@ -2312,6 +2495,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
vobj->updateTextures();
vobj->preRebuild();
+ drawablep->clearState(LLDrawable::HAS_ALPHA);
+
//for each face
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
{
@@ -2373,13 +2558,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (type == LLDrawPool::POOL_ALPHA)
{
if (LLPipeline::sFastAlpha &&
- (te->getColor().mV[VW] == 1.0f) &&
- facep->getTexture()->getIsAlphaMask())
+ (te->getColor().mV[VW] == 1.0f) &&
+ (!te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible, need to figure out why - for now, avoid
+ facep->getTexture()->getIsAlphaMask())
{ //can be treated as alpha mask
simple_faces.push_back(facep);
}
else
{
+ drawablep->setState(LLDrawable::HAS_ALPHA);
alpha_faces.push_back(facep);
}
}
@@ -2468,16 +2655,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (LLPipeline::sDelayVBUpdate)
{
- group->setState(LLSpatialGroup::MESH_DIRTY);
+ group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
}
mFaceList.clear();
}
+static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
{
- if (group->isState(LLSpatialGroup::MESH_DIRTY))
+ if (group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
+ LLFastTimer tm(FTM_VOLUME_GEOM);
S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ;
group->mBuilt = 1.f;
@@ -2554,7 +2743,12 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
}
}
- group->clearState(LLSpatialGroup::MESH_DIRTY);
+ group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
+ }
+
+ if (group->isState(LLSpatialGroup::NEW_DRAWINFO))
+ {
+ llerrs << "WTF?" << llendl;
}
}
@@ -2699,6 +2893,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA;
BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
+ if ((mask & LLVertexBuffer::MAP_NORMAL) == 0)
+ { //paranoia check to make sure GL doesn't try to read non-existant normals
+ fullbright = TRUE;
+ }
+
const LLTextureEntry* te = facep->getTextureEntry();
BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE;
@@ -2708,6 +2907,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
// can we safely treat this as an alpha mask?
if (LLPipeline::sFastAlpha &&
(te->getColor().mV[VW] == 1.0f) &&
+ (!te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible, need to figure out why - for now, avoid
facep->getTexture()->getIsAlphaMask())
{
if (te->getFullbright())
@@ -2730,6 +2930,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
}
else if (gPipeline.canUseVertexShaders()
+ && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD
&& LLPipeline::sRenderBump
&& te->getShiny())
{
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index d343d4db74..1b90219836 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -198,9 +198,18 @@ public:
void setLightRadius(F32 radius);
void setLightFalloff(F32 falloff);
void setLightCutoff(F32 cutoff);
+ void setLightTextureID(LLUUID id);
+ void setSpotLightParams(LLVector3 params);
+
BOOL getIsLight() const;
LLColor3 getLightBaseColor() const; // not scaled by intensity
LLColor3 getLightColor() const; // scaled by intensity
+ LLUUID getLightTextureID() const;
+ LLVector3 getSpotLightParams() const;
+ void updateSpotLightPriority();
+ F32 getSpotLightPriority() const;
+
+ LLViewerTexture* getLightTexture();
F32 getLightIntensity() const;
F32 getLightRadius() const;
F32 getLightFalloff() const;
@@ -210,6 +219,8 @@ public:
U32 getVolumeInterfaceID() const;
virtual BOOL isFlexible() const;
virtual BOOL isSculpted() const;
+ virtual BOOL hasLightTexture() const;
+
BOOL isVolumeGlobal() const;
BOOL canBeFlexible() const;
BOOL setIsFlexible(BOOL is_flexible);
@@ -232,12 +243,14 @@ private:
BOOL mLODChanged;
S32 mSculptLevel;
BOOL mSculptChanged;
+ F32 mSpotLightPriority;
LLMatrix4 mRelativeXform;
LLMatrix3 mRelativeXformInvTrans;
BOOL mVolumeChanged;
F32 mVObjRadius;
LLVolumeInterface *mVolumeImpl;
LLPointer<LLViewerFetchedTexture> mSculptTexture;
+ LLPointer<LLViewerFetchedTexture> mLightTexture;
// statics
public:
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index e2357957ab..0c967f9020 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -277,9 +277,8 @@ U32 LLVOWater::getPartitionType() const
}
LLWaterPartition::LLWaterPartition()
-: LLSpatialPartition(0)
+: LLSpatialPartition(0, FALSE, 0)
{
- mRenderByGroup = FALSE;
mInfiniteFarClip = TRUE;
mDrawableType = LLPipeline::RENDER_TYPE_WATER;
mPartitionType = LLViewerRegion::PARTITION_WATER;
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 3661be500b..136ffe607d 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -154,7 +154,7 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate)
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
llinfos << "Loading water settings from " << pathName << llendl;
- std::ifstream presetsXML;
+ llifstream presetsXML;
presetsXML.open(pathName.c_str());
// That failed, try loading from the users area instead.
@@ -162,7 +162,8 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate)
{
pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", escaped_filename);
llinfos << "Loading User water setting from " << pathName << llendl;
- presetsXML.open(pathName.c_str());
+ presetsXML.clear();
+ presetsXML.open(pathName.c_str());
}
if (presetsXML)
@@ -279,8 +280,6 @@ void LLWaterParamManager::update(LLViewerCamera * cam)
waterfloater->syncMenu();
}
- stop_glerror();
-
// only do this if we're dealing with shaders
if(gPipeline.canUseVertexShaders())
{
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index 7d9d0a6191..4bf64816c7 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -206,7 +206,8 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate)
{
pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", escaped_filename);
llinfos << "Loading User WindLight sky setting from " << pathName << llendl;
- presetsXML.open(pathName.c_str());
+ presetsXML.clear();
+ presetsXML.open(pathName.c_str());
}
if (presetsXML)
@@ -396,8 +397,6 @@ void LLWLParamManager::update(LLViewerCamera * cam)
F32 camYaw = cam->getYaw();
- stop_glerror();
-
// *TODO: potential optimization - this block may only need to be
// executed some of the time. For example for water shaders only.
{
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index 700971dcc4..b8ecd9556f 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -635,7 +635,6 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
#ifdef IMMEDIATE_IMAGE_LOAD
siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
- gGL.getTexUnit(0)->bind(siminfo->mCurrentImage);
siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
#endif
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 4d7423eaae..79308f7e16 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -372,7 +372,7 @@ void LLWorldMapView::draw()
current_image->setBoostLevel(LLViewerTexture::BOOST_MAP_LAYER);
current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
- if (!current_image->hasValidGLTexture())
+ if (!current_image->hasGLTexture())
{
continue; // better to draw nothing than the default image
}
@@ -474,7 +474,7 @@ void LLWorldMapView::draw()
bool sim_visible =
(gMapScale >= map_scale_cutoff) &&
(simimage != NULL) &&
- (simimage->hasValidGLTexture());
+ (simimage->hasGLTexture());
if (sim_visible)
{
@@ -583,7 +583,7 @@ void LLWorldMapView::draw()
gGL.vertex3f(right, top, 0.f);
gGL.end();
- if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->hasValidGLTexture())
+ if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->hasGLTexture())
{
gGL.getTexUnit(0)->bind(overlayimage);
gGL.color4f(1.f, 1.f, 1.f, alpha);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index b0c3e8d711..38052abfa3 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -102,6 +102,8 @@
#include "llwaterparammanager.h"
#include "llspatialpartition.h"
#include "llmutelist.h"
+#include "lltoolpie.h"
+
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -161,6 +163,8 @@ LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
+LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
+
static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
@@ -186,6 +190,8 @@ std::string gPoolNames[] =
"POOL_ALPHA",
};
+void drawBox(const LLVector3& c, const LLVector3& r);
+
U32 nhpo2(U32 v)
{
U32 r = 1;
@@ -267,7 +273,6 @@ BOOL LLPipeline::sDisableShaders = FALSE;
BOOL LLPipeline::sRenderBump = TRUE;
BOOL LLPipeline::sUseFarClip = TRUE;
BOOL LLPipeline::sShadowRender = FALSE;
-BOOL LLPipeline::sSkipUpdate = FALSE;
BOOL LLPipeline::sWaterReflections = FALSE;
BOOL LLPipeline::sRenderGlow = FALSE;
BOOL LLPipeline::sReflectionRender = FALSE;
@@ -279,6 +284,8 @@ BOOL LLPipeline::sRenderAttachedLights = TRUE;
BOOL LLPipeline::sRenderAttachedParticles = TRUE;
BOOL LLPipeline::sRenderDeferred = FALSE;
S32 LLPipeline::sVisibleLightCount = 0;
+F32 LLPipeline::sMinRenderSize = 0.f;
+
static LLCullResult* sCull = NULL;
@@ -294,11 +301,11 @@ static const U32 gl_cube_face[] =
void validate_framebuffer_object();
+
void addDeferredAttachments(LLRenderTarget& target)
{
- target.addColorAttachment(GL_RGBA16F_ARB); //specular
- target.addColorAttachment(GL_RGBA16F_ARB); //normal+z
- target.addColorAttachment(GL_RGBA16F_ARB); //position
+ target.addColorAttachment(GL_RGBA); //specular
+ target.addColorAttachment(GL_RGBA); //normal+z
}
LLPipeline::LLPipeline() :
@@ -340,6 +347,8 @@ LLPipeline::LLPipeline() :
mLightingDetail(0)
{
mNoiseMap = 0;
+ mTrueNoiseMap = 0;
+ mLightFunc = 0;
}
void LLPipeline::init()
@@ -389,6 +398,11 @@ void LLPipeline::init()
LLViewerShaderMgr::instance()->setShaders();
stop_glerror();
+
+ for (U32 i = 0; i < 2; ++i)
+ {
+ mSpotLightFade[i] = 1.f;
+ }
}
LLPipeline::~LLPipeline()
@@ -496,13 +510,6 @@ void LLPipeline::resizeScreenTexture()
GLuint resX = gViewerWindow->getWorldViewWidth();
GLuint resY = gViewerWindow->getWorldViewHeight();
- U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
- if (res_mod > 1 && res_mod < resX && res_mod < resY)
- {
- resX /= res_mod;
- resY /= res_mod;
- }
-
allocateScreenBuffer(resX,resY);
llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl;
@@ -512,17 +519,59 @@ void LLPipeline::resizeScreenTexture()
void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
{
U32 samples = gSavedSettings.getU32("RenderFSAASamples");
+
+ U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
+ if (res_mod > 1 && res_mod < resX && res_mod < resY)
+ {
+ resX /= res_mod;
+ resY /= res_mod;
+ }
+
+ if (gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ }
+
if (LLPipeline::sRenderDeferred)
{
//allocate deferred rendering color buffers
- mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
addDeferredAttachments(mDeferredScreen);
- mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-
+ mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+
+ for (U32 i = 0; i < 3; i++)
+ {
+ mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ }
+
for (U32 i = 0; i < 2; i++)
{
- mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ }
+
+ F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
}
+
+
+ U32 width = nhpo2(U32(resX*scale))/2;
+ U32 height = width;
+
+ for (U32 i = 4; i < 6; i++)
+ {
+ mShadow[i].allocate(width, height, 0, TRUE, FALSE);
+ }
+
+
+
+ width = nhpo2(resX)/2;
+ height = nhpo2(resY)/2;
+ mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE);
}
else
{
@@ -532,25 +581,23 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
if (gGLManager.mHasFramebufferMultisample && samples > 1)
{
+ mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
+ mScreen.setSampleBuffer(&mSampleBuffer);
+
if (LLPipeline::sRenderDeferred)
{
- mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
addDeferredAttachments(mSampleBuffer);
mDeferredScreen.setSampleBuffer(&mSampleBuffer);
}
- else
- {
- mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
- }
- mScreen.setSampleBuffer(&mSampleBuffer);
stop_glerror();
}
- else if (LLPipeline::sRenderDeferred)
+
+ if (LLPipeline::sRenderDeferred)
{ //share depth buffer between deferred targets
mDeferredScreen.shareDepthBuffer(mScreen);
- for (U32 i = 0; i < 2; i++)
- {
+ for (U32 i = 0; i < 3; i++)
+ { //share stencil buffer with screen space lightmap to stencil out sky
mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
}
}
@@ -583,17 +630,42 @@ void LLPipeline::releaseGLBuffers()
mNoiseMap = 0;
}
+ if (mTrueNoiseMap)
+ {
+ LLImageGL::deleteTextures(1, &mTrueNoiseMap);
+ mTrueNoiseMap = 0;
+ }
+
+ if (mLightFunc)
+ {
+ LLImageGL::deleteTextures(1, &mLightFunc);
+ mLightFunc = 0;
+ }
+
mWaterRef.release();
mWaterDis.release();
mScreen.release();
+ mUIScreen.release();
mSampleBuffer.releaseSampleBuffer();
mDeferredScreen.release();
+ mDeferredDepth.release();
+ for (U32 i = 0; i < 3; i++)
+ {
+ mDeferredLight[i].release();
+ }
+
+ mEdgeMap.release();
+ mGIMap.release();
+ mGIMapPost[0].release();
+ mGIMapPost[1].release();
+ mHighlight.release();
+ mLuminanceMap.release();
-
- for (U32 i = 0; i < 4; i++)
+ for (U32 i = 0; i < 6; i++)
{
- mSunShadow[i].release();
+ mShadow[i].release();
}
+
for (U32 i = 0; i < 3; i++)
{
mGlow[i].release();
@@ -617,6 +689,7 @@ void LLPipeline::createGLBuffers()
mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
}
+ mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
stop_glerror();
@@ -638,11 +711,6 @@ void LLPipeline::createGLBuffers()
if (sRenderDeferred)
{
- mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE);
- mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE);
- mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE);
- mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE);
-
if (!mNoiseMap)
{
const U32 noiseRes = 128;
@@ -662,6 +730,66 @@ void LLPipeline::createGLBuffers()
LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+
+ if (!mTrueNoiseMap)
+ {
+ const U32 noiseRes = 128;
+ F32 noise[noiseRes*noiseRes*3];
+ for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
+ {
+ noise[i] = ll_frand()*2.0-1.0;
+ }
+
+ LLImageGL::generateTextures(1, &mTrueNoiseMap);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ if (!mLightFunc)
+ {
+ U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
+ U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
+ U8* lg = new U8[lightResX*lightResY];
+
+ for (U32 y = 0; y < lightResY; ++y)
+ {
+ for (U32 x = 0; x < lightResX; ++x)
+ {
+ //spec func
+ F32 sa = (F32) x/(lightResX-1);
+ F32 spec = (F32) y/(lightResY-1);
+ //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
+
+ //F32 sp = acosf(sa)/(1.f-spec);
+
+ sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
+ F32 a = acosf(sa*0.25f+0.75f);
+ F32 m = llmax(0.5f-spec*0.5f, 0.001f);
+ F32 t2 = tanf(a)/m;
+ t2 *= t2;
+
+ F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
+ F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
+
+ lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+ }
+ }
+
+ LLImageGL::generateTextures(1, &mLightFunc);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+
+ delete [] lg;
+ }
+
+ if (gSavedSettings.getBOOL("RenderDeferredGI"))
+ {
+ mGIMap.allocate(512,512,GL_RGBA, TRUE, FALSE);
+ addDeferredAttachments(mGIMap);
+ }
}
}
@@ -1038,6 +1166,31 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable)
break;
}
}
+
+ {
+ HighlightItem item(drawablep);
+ mHighlightSet.erase(item);
+
+ if (mHighlightObject == drawablep)
+ {
+ mHighlightObject = NULL;
+ }
+ }
+
+ for (U32 i = 0; i < 2; ++i)
+ {
+ if (mShadowSpotLight[i] == drawablep)
+ {
+ mShadowSpotLight[i] = NULL;
+ }
+
+ if (mTargetShadowSpotLight[i] == drawablep)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
+ }
+
+
}
U32 LLPipeline::addObject(LLViewerObject *vobj)
@@ -1357,6 +1510,8 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
min = LLVector3(F32_MAX, F32_MAX, F32_MAX);
max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX);
+ U32 saved_camera_id = LLViewerCamera::sCurCameraID;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
BOOL res = TRUE;
@@ -1381,6 +1536,8 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
}
}
+ LLViewerCamera::sCurCameraID = saved_camera_id;
+
return res;
}
@@ -1397,8 +1554,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
BOOL to_texture = LLPipeline::sUseOcclusion > 1 &&
!hasRenderType(LLPipeline::RENDER_TYPE_HUD) &&
- !sReflectionRender &&
- !sShadowRender &&
+ LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
gPipeline.canUseVertexShaders() &&
sRenderGlow;
@@ -1407,11 +1563,15 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
mScreen.bindTarget();
}
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixd(gGLLastProjection);
+ glMatrixMode(GL_MODELVIEW);
glPushMatrix();
gGLLastMatrix = NULL;
- //glLoadMatrixd(gGLModelView);
glLoadMatrixd(gGLLastModelView);
+
LLVertexBuffer::unbind();
LLGLDisable blend(GL_BLEND);
LLGLDisable test(GL_ALPHA_TEST);
@@ -1480,6 +1640,9 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
}
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
glPopMatrix();
if (sUseOcclusion > 1)
@@ -1491,10 +1654,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
{
mScreen.flush();
}
- else if (LLPipeline::sUseOcclusion > 1)
- {
- glFlush();
- }
}
void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
@@ -1506,7 +1665,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
group->setVisible();
- if (!sSkipUpdate)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
group->updateDistance(camera);
}
@@ -1518,6 +1677,12 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
return;
}
+ if (sMinRenderSize > 0.f &&
+ llmax(llmax(group->mBounds[1].mV[0], group->mBounds[1].mV[1]), group->mBounds[1].mV[2]) < sMinRenderSize)
+ {
+ return;
+ }
+
assertInitialized();
if (!group->mSpatialPartition->mRenderByGroup)
@@ -1534,22 +1699,22 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
void LLPipeline::markOccluder(LLSpatialGroup* group)
{
- if (sUseOcclusion > 1 && group && !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION))
+ if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
{
LLSpatialGroup* parent = group->getParent();
- if (!parent || !parent->isState(LLSpatialGroup::OCCLUDED))
+ if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //only mark top most occluders as active occlusion
sCull->pushOcclusionGroup(group);
- group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
if (parent &&
- !parent->isState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
+ !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
parent->getElementCount() == 0 &&
parent->needsUpdate())
{
sCull->pushOcclusionGroup(group);
- parent->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
}
}
}
@@ -1572,18 +1737,18 @@ void LLPipeline::doOcclusion(LLCamera& camera)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
if (LLPipeline::sUseOcclusion > 1)
{
for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
{
LLSpatialGroup* group = *iter;
group->doOcclusion(&camera);
- group->clearState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
}
}
gGL.setColorMask(true, false);
- glFlush();
}
BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
@@ -1597,6 +1762,78 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
return update_complete;
}
+void LLPipeline::updateGL()
+{
+ while (!LLGLUpdate::sGLQ.empty())
+ {
+ LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
+ glu->updateGL();
+ glu->mInQ = FALSE;
+ LLGLUpdate::sGLQ.pop_front();
+ }
+}
+
+void LLPipeline::rebuildPriorityGroups()
+{
+ LLTimer update_timer;
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ assertInitialized();
+
+ // Iterate through all drawables on the priority build queue,
+ for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin();
+ iter != mGroupQ1.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->rebuildGeom();
+ group->clearState(LLSpatialGroup::IN_BUILD_Q1);
+ }
+
+ mGroupQ1.clear();
+}
+
+void LLPipeline::rebuildGroups()
+{
+ // Iterate through some drawables on the non-priority build queue
+ S32 size = (S32) mGroupQ2.size();
+ S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
+
+ S32 count = 0;
+
+ std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
+
+ LLSpatialGroup::sg_vector_t::iterator iter;
+ for (iter = mGroupQ2.begin();
+ iter != mGroupQ2.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ group->rebuildGeom();
+
+ if (group->mSpatialPartition->mRenderByGroup)
+ {
+ count++;
+ }
+
+ group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+
+ if (count > min_count)
+ {
+ ++iter;
+ break;
+ }
+ }
+
+ mGroupQ2.erase(mGroupQ2.begin(), iter);
+
+ updateMovedList(mMovedBridge);
+}
+
void LLPipeline::updateGeom(F32 max_dtime)
{
LLTimer update_timer;
@@ -1711,6 +1948,16 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
if (drawablep->isSpatialBridge())
{
+ LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
+
+ if (root && root->getParent() && root->getVObj() && root->getVObj()->isAttachment())
+ {
+ LLVOAvatar* av = root->getParent()->getVObj()->asAvatar();
+ if (av->isImpostor())
+ {
+ return;
+ }
+ }
sCull->pushBridge((LLSpatialBridge*) drawablep);
}
else
@@ -1840,6 +2087,59 @@ void LLPipeline::markTextured(LLDrawable *drawablep)
}
}
+void LLPipeline::markGLRebuild(LLGLUpdate* glu)
+{
+ if (glu && !glu->mInQ)
+ {
+ LLGLUpdate::sGLQ.push_back(glu);
+ glu->mInQ = TRUE;
+ }
+}
+
+void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ //assert_main_thread();
+
+ if (group && !group->isDead() && group->mSpatialPartition)
+ {
+ if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
+ {
+ priority = TRUE;
+ }
+
+ if (priority)
+ {
+ if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
+ {
+ mGroupQ1.push_back(group);
+ group->setState(LLSpatialGroup::IN_BUILD_Q1);
+
+ if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
+ {
+ LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
+ if (iter != mGroupQ2.end())
+ {
+ mGroupQ2.erase(iter);
+ }
+ group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+ }
+ }
+ }
+ else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
+ {
+ //llerrs << "Non-priority updates not yet supported!" << llendl;
+ if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end())
+ {
+ llerrs << "WTF?" << llendl;
+ }
+ mGroupQ2.push_back(group);
+ group->setState(LLSpatialGroup::IN_BUILD_Q2);
+
+ }
+ }
+}
+
void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
@@ -1896,48 +2196,48 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
grabReferences(result);
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
{
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ LLSpatialGroup* group = *iter;
+ group->checkOcclusion();
+ if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
- LLSpatialGroup* group = *iter;
- group->checkOcclusion();
- if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED))
- {
- markOccluder(group);
- }
- else
+ markOccluder(group);
+ }
+ else
+ {
+ group->setVisible();
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- group->setVisible();
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- markVisible(*i, camera);
- }
+ markVisible(*i, camera);
}
}
+ }
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->checkOcclusion();
+ if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
- LLSpatialGroup* group = *iter;
- group->checkOcclusion();
- if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED))
- {
- markOccluder(group);
- }
- else
- {
- group->setVisible();
- stateSort(group, camera);
- }
+ markOccluder(group);
+ }
+ else
+ {
+ group->setVisible();
+ stateSort(group, camera);
}
}
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
{
LLCullResult::bridge_list_t::iterator cur_iter = i;
LLSpatialBridge* bridge = *cur_iter;
LLSpatialGroup* group = bridge->getSpatialGroup();
- if (!bridge->isDead() && group && !group->isState(LLSpatialGroup::OCCLUDED))
+ if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
stateSort(bridge, camera);
}
@@ -1968,7 +2268,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
- if (!sSkipUpdate && group->changeLOD())
+ if (group->changeLOD())
{
for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
@@ -1982,7 +2282,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
- if (!sSkipUpdate && bridge->getSpatialGroup()->changeLOD())
+ if (!sShadowRender && bridge->getSpatialGroup()->changeLOD())
{
bool force_update = false;
bridge->updateDistance(camera, force_update);
@@ -2039,41 +2339,48 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
}
}
- LLSpatialGroup* group = drawablep->getSpatialGroup();
- if (!group || group->changeLOD())
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
- if (drawablep->isVisible() && !sSkipUpdate)
+ LLSpatialGroup* group = drawablep->getSpatialGroup();
+ if (!group || group->changeLOD())
{
- if (!drawablep->isActive())
+ if (drawablep->isVisible())
{
- bool force_update = false;
- drawablep->updateDistance(camera, force_update);
+ if (!drawablep->isActive())
+ {
+ bool force_update = false;
+ drawablep->updateDistance(camera, force_update);
+ }
+ else if (drawablep->isAvatar())
+ {
+ bool force_update = false;
+ drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
+ }
}
- else if (drawablep->isAvatar())
- {
- bool force_update = false;
- drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
- }
}
}
- for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
- iter != drawablep->mFaces.end(); iter++)
+ if (!drawablep->getVOVolume())
{
- LLFace* facep = *iter;
-
- if (facep->hasGeometry())
+ for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
+ iter != drawablep->mFaces.end(); iter++)
{
- if (facep->getPool())
- {
- facep->getPool()->enqueue(facep);
- }
- else
+ LLFace* facep = *iter;
+
+ if (facep->hasGeometry())
{
- break;
+ if (facep->getPool())
+ {
+ facep->getPool()->enqueue(facep);
+ }
+ else
+ {
+ break;
+ }
}
}
}
+
mNumVisibleFaces += drawablep->getNumFaces();
}
@@ -2230,7 +2537,7 @@ void LLPipeline::postSort(LLCamera& camera)
{
LLSpatialGroup* group = *i;
if (!sUseOcclusion ||
- !group->isState(LLSpatialGroup::OCCLUDED))
+ !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
group->rebuildGeom();
}
@@ -2239,7 +2546,7 @@ void LLPipeline::postSort(LLCamera& camera)
//rebuild groups
sCull->assertDrawMapsEmpty();
- LLSpatialGroup::sNoDelete = FALSE;
+ /*LLSpatialGroup::sNoDelete = FALSE;
for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
{
LLSpatialGroup* group = *i;
@@ -2251,8 +2558,10 @@ void LLPipeline::postSort(LLCamera& camera)
group->rebuildGeom();
}
- LLSpatialGroup::sNoDelete = TRUE;
+ LLSpatialGroup::sNoDelete = TRUE;*/
+
+ rebuildPriorityGroups();
const S32 bin_count = 1024*8;
@@ -2274,42 +2583,65 @@ void LLPipeline::postSort(LLCamera& camera)
{
LLSpatialGroup* group = *i;
if (sUseOcclusion &&
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
continue;
}
-
+
+ if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
+ { //no way this group is going to be drawable without a rebuild
+ group->rebuildGeom();
+ }
+
for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
{
LLSpatialGroup::drawmap_elem_t& src_vec = j->second;
-
- for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
+ if (!hasRenderType(j->first))
{
- sCull->pushDrawInfo(j->first, *k);
+ continue;
}
- }
-
- LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
-
- if (alpha != group->mDrawMap.end())
- { //store alpha groups for sorting
- LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
- if (!sSkipUpdate)
+
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
{
- if (bridge)
+ if (sMinRenderSize > 0.f)
{
- LLCamera trans_camera = bridge->transformCamera(camera);
- group->updateDistance(trans_camera);
+ LLVector3 bounds = (*k)->mExtents[1]-(*k)->mExtents[0];
+ if (llmax(llmax(bounds.mV[0], bounds.mV[1]), bounds.mV[2]) > sMinRenderSize)
+ {
+ sCull->pushDrawInfo(j->first, *k);
+ }
}
else
{
- group->updateDistance(camera);
+ sCull->pushDrawInfo(j->first, *k);
}
}
+ }
+
+ if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
+ {
+ LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
- if (hasRenderType(LLDrawPool::POOL_ALPHA))
- {
- sCull->pushAlphaGroup(group);
+ if (alpha != group->mDrawMap.end())
+ { //store alpha groups for sorting
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ if (bridge)
+ {
+ LLCamera trans_camera = bridge->transformCamera(camera);
+ group->updateDistance(trans_camera);
+ }
+ else
+ {
+ group->updateDistance(camera);
+ }
+ }
+
+ if (hasRenderType(LLDrawPool::POOL_ALPHA))
+ {
+ sCull->pushAlphaGroup(group);
+ }
}
}
}
@@ -2408,7 +2740,7 @@ void LLPipeline::postSort(LLCamera& camera)
}
}
- LLSpatialGroup::sNoDelete = FALSE;
+ //LLSpatialGroup::sNoDelete = FALSE;
}
@@ -2470,6 +2802,103 @@ void LLPipeline::renderHighlights()
LLGLEnable color_mat(GL_COLOR_MATERIAL);
disableLights();
+ if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
+ { //draw blurry highlight image over screen
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ gGL.flush();
+ glStencilMask(0xFFFFFFFF);
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ gGL.setColorMask(false, false);
+ for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
+ {
+ renderHighlight(iter->mItem->getVObj(), 1.f);
+ }
+ gGL.setColorMask(true, false);
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+
+ //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+
+ gGL.pushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ gGL.pushMatrix();
+ glLoadIdentity();
+
+ gGL.getTexUnit(0)->bind(&mHighlight);
+
+ LLVector2 tc1;
+ LLVector2 tc2;
+
+ tc1.setVec(0,0);
+ tc2.setVec(2,2);
+
+ gGL.begin(LLRender::TRIANGLES);
+
+ F32 scale = gSavedSettings.getF32("RenderHighlightBrightness");
+ LLColor4 color = gSavedSettings.getColor4("RenderHighlightColor");
+ F32 thickness = gSavedSettings.getF32("RenderHighlightThickness");
+
+ for (S32 pass = 0; pass < 2; ++pass)
+ {
+ if (pass == 0)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+ }
+ else
+ {
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
+ for (S32 i = 0; i < 8; ++i)
+ {
+ for (S32 j = 0; j < 8; ++j)
+ {
+ LLVector2 tc(i-4+0.5f, j-4+0.5f);
+
+ F32 dist = 1.f-(tc.length()/sqrtf(32.f));
+ dist *= scale/64.f;
+
+ tc *= thickness;
+ tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
+ tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
+
+ gGL.color4f(color.mV[0],
+ color.mV[1],
+ color.mV[2],
+ color.mV[3]*dist);
+
+ gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+ }
+ }
+ }
+
+ gGL.end();
+
+ gGL.popMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ gGL.popMatrix();
+
+ //gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
gHighlightProgram.bind();
@@ -2611,6 +3040,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
stop_glerror();
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
+
for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
{
LLDrawPool *poolp = *iter;
@@ -2859,15 +3289,18 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
poolp->endDeferredPass(i);
LLVertexBuffer::unbind();
- GLint depth;
- glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
- if (depth > 3)
+ if (gDebugGL || gDebugPipeline)
{
- llerrs << "GL matrix stack corrupted!" << llendl;
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
}
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
}
}
else
@@ -2950,15 +3383,18 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
poolp->endPostDeferredPass(i);
LLVertexBuffer::unbind();
- GLint depth;
- glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
- if (depth > 3)
+ if (gDebugGL || gDebugPipeline)
{
- llerrs << "GL matrix stack corrupted!" << llendl;
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
}
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
}
}
else
@@ -3118,7 +3554,7 @@ void LLPipeline::renderDebug()
for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
{
LLSpatialBridge* bridge = *i;
- if (!bridge->isDead() && !bridge->isState(LLSpatialGroup::OCCLUDED) && hasRenderType(bridge->mDrawableType))
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
{
glPushMatrix();
glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
@@ -3129,79 +3565,91 @@ void LLPipeline::renderDebug()
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(TRUE, FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+
gGL.color4f(1,1,1,1);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ F32 a = 0.1f;
+
F32 col[] =
{
- 1,1,0,
- 0,1,1,
- 1,0,1,
- 1,1,1,
- 1,0,0,
- 0,1,0,
- 0,0,1,
- 0,0,0
+ 1,0,0,a,
+ 0,1,0,a,
+ 0,0,1,a,
+ 1,0,1,a,
+
+ 1,1,0,a,
+ 0,1,1,a,
+ 1,1,1,a,
+ 1,0,1,a,
};
for (U32 i = 0; i < 8; i++)
{
- gGL.color3fv(col+i*3);
-
- gGL.begin(LLRender::LINES);
-
- LLVector3* frust = mShadowCamera[i].mAgentFrustum;
-
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
-
- gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
- gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
-
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+ if (i > 3)
+ {
+ gGL.color4fv(col+(i-4)*4);
+ LLVector3* frust = mShadowCamera[i].mAgentFrustum;
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.end();
+
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[0].mV);
+ gGL.vertex3fv(frust[1].mV);
+ gGL.vertex3fv(frust[3].mV);
+ gGL.vertex3fv(frust[2].mV);
+ gGL.end();
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[6].mV);
+ gGL.end();
+ }
+
+
if (i < 4)
{
- LLVector3* ext = mShadowExtents[i];
+ gGL.begin(LLRender::LINES);
- LLVector3 box[] =
+ F32* c = col+i*4;
+ for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
{
- LLVector3(ext[0][0], ext[0][1], ext[0][2]),
- LLVector3(ext[1][0], ext[0][1], ext[0][2]),
- LLVector3(ext[1][0], ext[1][1], ext[0][2]),
- LLVector3(ext[0][0], ext[1][1], ext[0][2]),
- LLVector3(ext[0][0], ext[0][1], ext[1][2]),
- LLVector3(ext[1][0], ext[0][1], ext[1][2]),
- LLVector3(ext[1][0], ext[1][1], ext[1][2]),
- LLVector3(ext[0][0], ext[1][1], ext[1][2]),
- };
- gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV);
- gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV);
- gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV);
- gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV);
-
- gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV);
- gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV);
- gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV);
- gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV);
-
- gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV);
- gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV);
- gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV);
- gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV);
+ gGL.color3fv(c);
+
+ for (U32 k = 0; k < mShadowFrustPoints[i].size(); ++k)
+ {
+ if (j != k)
+ {
+ gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+ gGL.vertex3fv(mShadowFrustPoints[i][k].mV);
+ }
+ }
+
+ if (!mShadowFrustOrigin[i].isExactlyZero())
+ {
+ gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+ gGL.color4f(1,1,1,1);
+ gGL.vertex3fv(mShadowFrustOrigin[i].mV);
+ }
+ }
+ gGL.end();
}
- gGL.end();
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ /*for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
LLViewerRegion* region = *iter;
@@ -3216,7 +3664,7 @@ void LLPipeline::renderDebug()
}
}
}
- }
+ }*/
}
}
@@ -3253,6 +3701,55 @@ void LLPipeline::renderDebug()
}
}
+ if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
+ {
+ U32 count = 0;
+ U32 size = mBuildQ2.size();
+ LLColor4 col;
+
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+
+ if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
+ {
+ continue;
+ }
+
+ if (bridge)
+ {
+ gGL.pushMatrix();
+ glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ }
+
+ F32 alpha = (F32) (size-count)/size;
+
+
+ LLVector2 c(1.f-alpha, alpha);
+ c.normVec();
+
+
+ ++count;
+ col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f);
+ group->drawObjectBox(col);
+
+ if (bridge)
+ {
+ gGL.popMatrix();
+ }
+ }
+ }
+
gGL.flush();
}
@@ -3871,37 +4368,34 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
// UPDATE THE EXISTING NEARBY LIGHTS
- if (!LLPipeline::sSkipUpdate)
+ light_set_t cur_nearby_lights;
+ for (light_set_t::iterator iter = mNearbyLights.begin();
+ iter != mNearbyLights.end(); iter++)
{
- light_set_t cur_nearby_lights;
- for (light_set_t::iterator iter = mNearbyLights.begin();
- iter != mNearbyLights.end(); iter++)
+ const Light* light = &(*iter);
+ LLDrawable* drawable = light->drawable;
+ LLVOVolume* volight = drawable->getVOVolume();
+ if (!volight || !drawable->isState(LLDrawable::LIGHT))
{
- const Light* light = &(*iter);
- LLDrawable* drawable = light->drawable;
- LLVOVolume* volight = drawable->getVOVolume();
- if (!volight || !drawable->isState(LLDrawable::LIGHT))
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
- if (light->fade <= -LIGHT_FADE_TIME)
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
- if (!sRenderAttachedLights && volight && volight->isAttachment())
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
-
- F32 dist = calc_light_dist(volight, cam_pos, max_dist);
- cur_nearby_lights.insert(Light(drawable, dist, light->fade));
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+ if (light->fade <= -LIGHT_FADE_TIME)
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
}
- mNearbyLights = cur_nearby_lights;
+ if (!sRenderAttachedLights && volight && volight->isAttachment())
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+
+ F32 dist = calc_light_dist(volight, cam_pos, max_dist);
+ cur_nearby_lights.insert(Light(drawable, dist, light->fade));
}
-
+ mNearbyLights = cur_nearby_lights;
+
// FIND NEW LIGHTS THAT ARE IN RANGE
light_set_t new_nearby_lights;
for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
@@ -5169,8 +5663,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
tc1.setVec(0,0);
tc2.setVec(2,2);
-
-
// power of two between 1 and 1024
U32 glowResPow = gSavedSettings.getS32("RenderGlowResolutionPow");
const U32 glow_res = llmax(1,
@@ -5245,15 +5737,40 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGLViewport[3] = gViewerWindow->getWorldViewRect().getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ tc2.setVec((F32) gViewerWindow->getWorldViewWidth(),
+ (F32) gViewerWindow->getWorldViewHeight());
+
gGL.flush();
+ LLVertexBuffer::unbind();
+
+ if (LLPipeline::sRenderDeferred && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
{
- LLVertexBuffer::unbind();
+ LLGLDisable blend(GL_BLEND);
+ bindDeferredShader(gDeferredGIFinalProgram);
+ S32 channel = gDeferredGIFinalProgram.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
- tc2.setVec((F32) gViewerWindow->getWorldViewWidth(),
- (F32) gViewerWindow->getWorldViewHeight());
+ gGL.end();
+
+ unbindDeferredShader(gDeferredGIFinalProgram);
+ }
+ else
+ {
if (res_mod > 1)
{
@@ -5294,7 +5811,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.getTexUnit(0)->bind(&mGlow[1]);
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE);
-
+
+
//tex unit 1
gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
@@ -5313,6 +5831,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
+
gGL.setSceneBlendType(LLRender::BT_ALPHA);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -5326,46 +5845,194 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
}
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map)
{
+ if (noise_map == 0xFFFFFFFF)
+ {
+ noise_map = mNoiseMap;
+ }
+
+ LLGLState::checkTextureChannels();
+
shader.bind();
S32 channel = 0;
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(0,channel);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
+ if (gi_source)
+ {
+ BOOL has_gi = FALSE;
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(3, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(3, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gGL.getTexUnit(channel)->bind(gi_source, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+
+ glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
+
+ stop_glerror();
+ }
+
+ if (has_gi)
+ {
+ F32 range_x = llmin(mGIRange.mV[0], 1.f);
+ F32 range_y = llmin(mGIRange.mV[1], 1.f);
+
+ LLVector2 scale(range_x,range_y);
+
+ LLVector2 kern[25];
+
+ for (S32 i = 0; i < 5; ++i)
+ {
+ for (S32 j = 0; j < 5; ++j)
+ {
+ S32 idx = i*5+j;
+ kern[idx].mV[0] = (i-2)*0.5f;
+ kern[idx].mV[1] = (j-2)*0.5f;
+ kern[idx].scaleVec(scale);
+ }
+ }
+
+ shader.uniform2fv("gi_kern", 25, (F32*) kern);
+ shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m);
+ shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m);
+ shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m);
+ shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m);
+ }
+ }
+
+ /*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(3, channel);
- }
+ }*/
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
- gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE);
+ gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+
+ glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
+
+ stop_glerror();
+
+ glh::matrix4f projection = glh_get_current_projection();
+ glh::matrix4f inv_proj = projection.inverse();
+
+ shader.uniformMatrix4fv("inv_proj", 1, FALSE, inv_proj.m);
+ shader.uniform4f("viewport", (F32) gGLViewport[0],
+ (F32) gGLViewport[1],
+ (F32) gGLViewport[2],
+ (F32) gGLViewport[3]);
}
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
if (channel > -1)
{
- gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
}
stop_glerror();
@@ -5374,19 +6041,81 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
if (channel > -1)
{
mDeferredLight[light_index].bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
+ if (channel > -1)
+ {
+ mGlow[1].bindTexture(0, channel);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ gi_source->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mEdgeMap.bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredLight[1].bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredLight[2].bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+
stop_glerror();
for (U32 i = 0; i < 4; i++)
{
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i);
stop_glerror();
if (channel > -1)
{
stop_glerror();
- gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE);
+ gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
@@ -5397,17 +6126,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
stop_glerror();
- F32 mat[64];
+ F32 mat[16*6];
for (U32 i = 0; i < 16; i++)
{
mat[i] = mSunShadowMatrix[0].m[i];
mat[i+16] = mSunShadowMatrix[1].m[i];
mat[i+32] = mSunShadowMatrix[2].m[i];
mat[i+48] = mSunShadowMatrix[3].m[i];
+ mat[i+64] = mSunShadowMatrix[4].m[i];
+ mat[i+80] = mSunShadowMatrix[5].m[i];
}
- shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat);
- shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat);
+ shader.uniformMatrix4fv("shadow_matrix[0]", 6, FALSE, mat);
+ shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat);
stop_glerror();
@@ -5456,7 +6187,44 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f);
shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften"));
-}
+ shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset"));
+ shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias"));
+ shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale"));
+ shader.uniform1f("sun_lum_scale", gSavedSettings.getF32("RenderSunLuminanceScale"));
+ shader.uniform1f("sun_lum_offset", gSavedSettings.getF32("RenderSunLuminanceOffset"));
+ shader.uniform1f("lum_lod", gSavedSettings.getF32("RenderLuminanceDetail"));
+ shader.uniform1f("gi_range", gSavedSettings.getF32("RenderGIRange"));
+ shader.uniform1f("gi_brightness", gSavedSettings.getF32("RenderGIBrightness"));
+ shader.uniform1f("gi_luminance", gSavedSettings.getF32("RenderGILuminance"));
+ shader.uniform1f("gi_edge_weight", gSavedSettings.getF32("RenderGIBlurEdgeWeight"));
+ shader.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
+ shader.uniform1f("gi_sample_width", mGILightRadius);
+ shader.uniform1f("gi_noise", gSavedSettings.getF32("RenderGINoise"));
+ shader.uniform1f("gi_attenuation", gSavedSettings.getF32("RenderGIAttenuation"));
+ shader.uniform1f("gi_ambiance", gSavedSettings.getF32("RenderGIAmbiance"));
+ shader.uniform2f("shadow_res", mShadow[0].getWidth(), mShadow[0].getHeight());
+ shader.uniform2f("proj_shadow_res", mShadow[4].getWidth(), mShadow[4].getHeight());
+ shader.uniform1f("depth_cutoff", gSavedSettings.getF32("RenderEdgeDepthCutoff"));
+ shader.uniform1f("norm_cutoff", gSavedSettings.getF32("RenderEdgeNormCutoff"));
+
+ if (shader.getUniformLocation("norm_mat") >= 0)
+ {
+ glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
+ shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
+static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
+static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
+static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
+static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
+static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
+static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
+static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
+static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
+static LLFastTimer::DeclareTimer FTM_POST("Post");
+
void LLPipeline::renderDeferredLighting()
{
@@ -5465,335 +6233,673 @@ void LLPipeline::renderDeferredLighting()
return;
}
- LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
{
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
+ LLFastTimer ftm(FTM_RENDER_DEFERRED);
- //ati doesn't seem to love actually using the stencil buffer on FBO's
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
- gGL.setColorMask(true, true);
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
- mDeferredLight[0].bindTarget();
+ LLGLEnable multisample(GL_MULTISAMPLE_ARB);
- //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
- //draw a cube around every light
- LLVertexBuffer::unbind();
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
- glBlendFunc(GL_ONE, GL_ONE);
- LLGLEnable cull(GL_CULL_FACE);
- LLGLEnable blend(GL_BLEND);
+ //ati doesn't seem to love actually using the stencil buffer on FBO's
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+ gGL.setColorMask(true, true);
+
+ //draw a cube around every light
+ LLVertexBuffer::unbind();
- F32 vert[] =
- {
- -1,1,
- -1,-3,
- 3,1,
- };
+ LLGLEnable cull(GL_CULL_FACE);
+ LLGLEnable blend(GL_BLEND);
- bindDeferredShader(gDeferredSunProgram);
+ glh::matrix4f mat = glh_copy_matrix(gGLModelView);
- glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+ F32 vert[] =
+ {
+ -1,1,
+ -1,-3,
+ 3,1,
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+ glColor3f(1,1,1);
- const U32 slice = 32;
- F32 offset[slice*3];
- for (U32 i = 0; i < 4; i++)
- {
- for (U32 j = 0; j < 8; j++)
{
- glh::vec3f v;
- v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
- v.normalize();
- inv_trans.mult_matrix_vec(v);
- v.normalize();
- offset[(i*8+j)*3+0] = v.v[0];
- offset[(i*8+j)*3+1] = v.v[2];
- offset[(i*8+j)*3+2] = v.v[1];
+ setupHWLights(NULL); //to set mSunDir;
+ LLVector4 dir(mSunDir, 0.f);
+ glh::vec4f tc(dir.mV);
+ mat.mult_matrix_vec(tc);
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
}
- }
- gDeferredSunProgram.uniform3fv("offset", slice, offset);
- gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+ if (gSavedSettings.getBOOL("RenderDeferredShadow"))
+ {
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
- setupHWLights(NULL); //to set mSunDir;
+ mDeferredLight[0].bindTarget();
+ if (gSavedSettings.getBOOL("RenderDeferredSun"))
+ { //paint shadow/SSAO light map (direct lighting lightmap)
+ LLFastTimer ftm(FTM_SUN_SHADOW);
+ bindDeferredShader(gDeferredSunProgram, 0);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ glClearColor(1,1,1,1);
+ mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
- LLVector4 dir(mSunDir, 0.f);
+ glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
- glh::vec4f tc(dir.mV);
- mat.mult_matrix_vec(tc);
- glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
- glColor3f(1,1,1);
-
- glVertexPointer(2, GL_FLOAT, 0, vert);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- stop_glerror();
- }
-
- unbindDeferredShader(gDeferredSunProgram);
+ const U32 slice = 32;
+ F32 offset[slice*3];
+ for (U32 i = 0; i < 4; i++)
+ {
+ for (U32 j = 0; j < 8; j++)
+ {
+ glh::vec3f v;
+ v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
+ v.normalize();
+ inv_trans.mult_matrix_vec(v);
+ v.normalize();
+ offset[(i*8+j)*3+0] = v.v[0];
+ offset[(i*8+j)*3+1] = v.v[2];
+ offset[(i*8+j)*3+2] = v.v[1];
+ }
+ }
- mDeferredLight[0].flush();
+ gDeferredSunProgram.uniform3fv("offset", slice, offset);
+ gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ unbindDeferredShader(gDeferredSunProgram);
+ }
+ else
+ {
+ mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
+ }
- //blur lightmap
- mDeferredLight[1].bindTarget();
+ mDeferredLight[0].flush();
- //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
- bindDeferredShader(gDeferredBlurLightProgram);
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+ {
+ LLFastTimer ftm(FTM_EDGE_DETECTION);
+ //get edge map
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable stencil(GL_STENCIL_TEST);
- LLVector3 gauss[32]; // xweight, yweight, offset
+ {
+ gDeferredEdgeProgram.bind();
+ mEdgeMap.bindTarget();
+ bindDeferredShader(gDeferredEdgeProgram);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ unbindDeferredShader(gDeferredEdgeProgram);
+ mEdgeMap.flush();
+ }
+ }
- LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
- U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1;
- F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ { //get luminance map from previous frame's light map
+ LLGLEnable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable stencil(GL_STENCIL_TEST);
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = -(kern_length/2.0f) + 0.5f;
+ //static F32 fade = 1.f;
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
- }
- /* swap the x=0 position to the start of gauss[] so we can
- treat it specially as an optimization. */
- LLVector3 swap;
- swap = gauss[kern_length/2];
- gauss[kern_length/2] = gauss[0];
- gauss[0] = swap;
- llassert(gauss[0].mV[2] == 0.0f);
+ {
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ gLuminanceGatherProgram.bind();
+ gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+ mLuminanceMap.bindTarget();
+ bindDeferredShader(gLuminanceGatherProgram);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ unbindDeferredShader(gLuminanceGatherProgram);
+ mLuminanceMap.flush();
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ }
- gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
- gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1i("kern_length", kern_length);
- gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+ { //paint noisy GI map (bounce lighting lightmap)
+ LLFastTimer ftm(FTM_GI_TRACE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable test(GL_ALPHA_TEST);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- stop_glerror();
- }
-
- mDeferredLight[1].flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ mGIMapPost[0].bindTarget();
- bindDeferredShader(gDeferredBlurLightProgram, 1);
- mDeferredLight[0].bindTarget();
+ bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0, mTrueNoiseMap);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ unbindDeferredShader(gDeferredGIProgram);
+ mGIMapPost[0].flush();
+ }
- gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
- gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1i("kern_length", kern_length);
- gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+ U32 pass_count = 0;
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+ {
+ pass_count = llclamp(gSavedSettings.getU32("RenderGIBlurPasses"), (U32) 1, (U32) 128);
+ }
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- stop_glerror();
- }
- mDeferredLight[0].flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ for (U32 i = 0; i < pass_count; ++i)
+ { //gather/soften indirect lighting map
+ LLFastTimer ftm(FTM_GI_GATHER);
+ bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL, mTrueNoiseMap);
+ F32 blur_size = gSavedSettings.getF32("RenderGIBlurSize")/((F32) i * gSavedSettings.getF32("RenderGIBlurIncrement")+1.f);
+ gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredPostGIProgram.uniform1f("kern_scale", blur_size);
+ gDeferredPostGIProgram.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
+
+ mGIMapPost[1].bindTarget();
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ mGIMapPost[1].flush();
+ unbindDeferredShader(gDeferredPostGIProgram);
+ bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL, mTrueNoiseMap);
+ mGIMapPost[0].bindTarget();
- stop_glerror();
- glPopMatrix();
- stop_glerror();
- glMatrixMode(GL_MODELVIEW);
- stop_glerror();
- glPopMatrix();
- stop_glerror();
+ gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f);
- //copy depth and stencil from deferred screen
- //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ stop_glerror();
+ }
+ mGIMapPost[0].flush();
+ unbindDeferredShader(gDeferredPostGIProgram);
+ }
+ }
- mScreen.bindTarget();
- mScreen.clear(GL_COLOR_BUFFER_BIT);
-
- bindDeferredShader(gDeferredSoftenProgram);
- {
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+ { //soften direct lighting lightmap
+ LLFastTimer ftm(FTM_SOFTEN_SHADOW);
+ //blur lightmap
+ mDeferredLight[1].bindTarget();
- //full screen blit
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ glClearColor(1,1,1,1);
+ mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
+
+ bindDeferredShader(gDeferredBlurLightProgram);
- glVertexPointer(2, GL_FLOAT, 0, vert);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
+ LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
+ const U32 kern_length = 4;
+ F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
+ F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
- unbindDeferredShader(gDeferredSoftenProgram);
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
- bindDeferredShader(gDeferredLightProgram);
+ LLVector3 gauss[32]; // xweight, yweight, offset
- std::list<LLVector4> fullscreen_lights;
- std::list<LLVector4> light_colors;
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
- F32 v[24];
- glVertexPointer(3, GL_FLOAT, 0, v);
- {
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
- {
- LLDrawable* drawablep = *iter;
+ gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
+ gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
- LLVOVolume* volume = drawablep->getVOVolume();
- if (!volume)
- {
- continue;
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ mDeferredLight[1].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+
+ bindDeferredShader(gDeferredBlurLightProgram, 1);
+ mDeferredLight[0].bindTarget();
+
+ gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+ mDeferredLight[0].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
}
- LLVector3 center = drawablep->getPositionAgent();
- F32* c = center.mV;
- F32 s = volume->getLightRadius()*1.5f;
+ stop_glerror();
+ glPopMatrix();
+ stop_glerror();
+ glMatrixMode(GL_MODELVIEW);
+ stop_glerror();
+ glPopMatrix();
+ stop_glerror();
+ }
+
+ //copy depth and stencil from deferred screen
+ //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
- if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ mDeferredLight[1].bindTarget();
+ mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
+ }
+ else
+ {
+ mScreen.bindTarget();
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (gSavedSettings.getBOOL("RenderDeferredAtmospheric"))
+ { //apply sunlight contribution
+ LLFastTimer ftm(FTM_ATMOSPHERICS);
+ bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]);
{
- continue;
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
}
- sVisibleLightCount++;
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
+ unbindDeferredShader(gDeferredSoftenProgram);
+ }
+
+ { //render sky
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ U32 render_mask = mRenderTypeMask;
+ mRenderTypeMask = mRenderTypeMask &
+ ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
+
- LLColor3 col = volume->getLightColor();
- col *= volume->getLightIntensity();
-
- //vertex positions are encoded so the 3 bits of their vertex index
- //correspond to their axis facing, with bit position 3,2,1 matching
- //axis facing x,y,z, bit set meaning positive facing, bit clear
- //meaning negative facing
- v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
- v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
- v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
- v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
-
- v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
- v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
- v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
- v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
-
- if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f)
- { //draw box if camera is outside box
- glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
- glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center));
+ renderGeomPostDeferred(*LLViewerCamera::getInstance());
+ mRenderTypeMask = render_mask;
+ }
+
+ BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
+ BOOL render_fullscreen = gSavedSettings.getBOOL("RenderDeferredFullscreenLights");
+
+
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ mDeferredLight[1].flush();
+ mDeferredLight[2].bindTarget();
+ mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (render_local || render_fullscreen)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+ std::list<LLVector4> fullscreen_lights;
+ LLDrawable::drawable_list_t spot_lights;
+ LLDrawable::drawable_list_t fullscreen_spot_lights;
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
}
- else
- {
- fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
- light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+
+ std::list<LLVector4> light_colors;
+
+ F32 v[24];
+ glVertexPointer(3, GL_FLOAT, 0, v);
+ BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
+
+ {
+ bindDeferredShader(gDeferredLightProgram);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+ {
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+ if (!volume)
+ {
+ continue;
+ }
+
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ if (col.magVecSquared() < 0.001f)
+ {
+ continue;
+ }
+
+ if (s <= 0.001f)
+ {
+ continue;
+ }
+
+ if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
+ {
+ continue;
+ }
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
+ v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
+ v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
+ v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
+
+ v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+ v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+ v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+ v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+ if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f)
+ { //draw box if camera is outside box
+ if (render_local)
+ {
+ if (volume->getLightTexture())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ LLFastTimer ftm(FTM_LOCAL_LIGHTS);
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center));
+ stop_glerror();
+ }
+ }
+ else if (render_fullscreen)
+ {
+ if (volume->getLightTexture())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ fullscreen_spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+ light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+ }
+ }
+ unbindDeferredShader(gDeferredLightProgram);
}
- }
- }
- unbindDeferredShader(gDeferredLightProgram);
+ if (!spot_lights.empty())
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ bindDeferredShader(gDeferredSpotLightProgram);
- if (!fullscreen_lights.empty())
- {
- bindDeferredShader(gDeferredMultiLightProgram);
- LLGLDepthTest depth(GL_FALSE);
+ gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
- //full screen blit
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+ {
+ LLFastTimer ftm(FTM_PROJECTORS);
+ LLDrawable* drawablep = *iter;
- U32 count = 0;
+ LLVOVolume* volume = drawablep->getVOVolume();
- LLVector4 light[16];
- LLVector4 col[16];
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
- glVertexPointer(2, GL_FLOAT, 0, vert);
+ sVisibleLightCount++;
- while (!fullscreen_lights.empty())
- {
- light[count] = fullscreen_lights.front();
- fullscreen_lights.pop_front();
- col[count] = light_colors.front();
- light_colors.pop_front();
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ setupSpotLight(gDeferredSpotLightProgram, drawablep);
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
+ v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
+ v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
+ v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
+
+ v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+ v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+ v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+ v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center));
+ }
+ gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredSpotLightProgram);
+ }
- count++;
- if (count == 16 || fullscreen_lights.empty())
{
- gDeferredMultiLightProgram.uniform1i("light_count", count);
- gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
- gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
- gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
- gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
- count = 0;
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ bindDeferredShader(gDeferredMultiLightProgram);
+
+ LLGLDepthTest depth(GL_FALSE);
+
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ U32 count = 0;
+
+ const U32 max_count = 8;
+ LLVector4 light[max_count];
+ LLVector4 col[max_count];
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ F32 far_z = 0.f;
+
+ while (!fullscreen_lights.empty())
+ {
+ LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
+ light[count] = fullscreen_lights.front();
+ fullscreen_lights.pop_front();
+ col[count] = light_colors.front();
+ light_colors.pop_front();
+
+ far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
+
+ count++;
+ if (count == max_count || fullscreen_lights.empty())
+ {
+ gDeferredMultiLightProgram.uniform1i("light_count", count);
+ gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
+ gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
+ gDeferredMultiLightProgram.uniform1f("far_z", far_z);
+ far_z = 0.f;
+ count = 0;
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ }
+ }
+
+ unbindDeferredShader(gDeferredMultiLightProgram);
+
+ bindDeferredShader(gDeferredMultiSpotLightProgram);
+
+ gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+ for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+ {
+ LLFastTimer ftm(FTM_PROJECTORS);
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ }
+
+ gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredMultiSpotLightProgram);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
}
}
+
+ gGL.setColorMask(true, true);
+
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ mDeferredLight[2].flush();
+
+ mScreen.bindTarget();
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
-
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ { //mix various light maps (local, sun, gi)
+ LLFastTimer ftm(FTM_POST);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+
+ bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]);
+
+ gDeferredPostProgram.bind();
+
+ LLVertexBuffer::unbind();
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+ glColor3f(1,1,1);
+
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
- unbindDeferredShader(gDeferredMultiLightProgram);
+ unbindDeferredShader(gDeferredPostProgram);
+ }
+ }
}
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- { //render non-deferred geometry
+ { //render non-deferred geometry (alpha, fullbright, glow)
LLGLDisable blend(GL_BLEND);
LLGLDisable stencil(GL_STENCIL_TEST);
U32 render_mask = mRenderTypeMask;
mRenderTypeMask = mRenderTypeMask &
- ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY) |
- (1 << LLPipeline::RENDER_TYPE_ALPHA) |
- (1 << LLPipeline::RENDER_TYPE_AVATAR) |
- (1 << LLPipeline::RENDER_TYPE_WATER) |
+ ((1 << LLPipeline::RENDER_TYPE_ALPHA) |
(1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) |
(1 << LLPipeline::RENDER_TYPE_VOLUME) |
(1 << LLPipeline::RENDER_TYPE_GLOW) |
- (1 << LLPipeline::RENDER_TYPE_BUMP));
+ (1 << LLPipeline::RENDER_TYPE_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_GLOW) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_GRASS) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_AVATAR));
renderGeomPostDeferred(*LLViewerCamera::getInstance());
mRenderTypeMask = render_mask;
@@ -5803,6 +6909,136 @@ void LLPipeline::renderDeferredLighting()
}
+void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
+{
+ //construct frustum
+ LLVOVolume* volume = drawablep->getVOVolume();
+ LLVector3 params = volume->getSpotLightParams();
+
+ F32 fov = params.mV[0];
+ F32 focus = params.mV[1];
+
+ LLVector3 pos = drawablep->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
+ LLVector3 scale = volume->getScale();
+
+ //get near clip plane
+ LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+ at_axis *= quat;
+
+ LLVector3 np = pos+at_axis;
+ at_axis.normVec();
+
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+ LLVector3 origin = np - at_axis*dist;
+
+ //matrix from volume space to agent space
+ LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
+
+ glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
+ glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
+
+ glh::matrix4f screen_to_light = light_to_screen.inverse();
+
+ F32 s = volume->getLightRadius()*1.5f;
+ F32 near_clip = dist;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = s+dist-scale.mV[VZ];
+
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width/height;
+
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ glh::vec3f p1(0, 0, -(near_clip+0.01f));
+ glh::vec3f p2(0, 0, -(near_clip+1.f));
+
+ glh::vec3f screen_origin(0, 0, 0);
+
+ light_to_screen.mult_matrix_vec(p1);
+ light_to_screen.mult_matrix_vec(p2);
+ light_to_screen.mult_matrix_vec(screen_origin);
+
+ glh::vec3f n = p2-p1;
+ n.normalize();
+
+ F32 proj_range = far_clip - near_clip;
+ glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
+ screen_to_light = trans * light_proj * screen_to_light;
+ shader.uniformMatrix4fv("proj_mat", 1, FALSE, screen_to_light.m);
+ shader.uniform1f("proj_near", near_clip);
+ shader.uniform3fv("proj_p", 1, p1.v);
+ shader.uniform3fv("proj_n", 1, n.v);
+ shader.uniform3fv("proj_origin", 1, screen_origin.v);
+ shader.uniform1f("proj_range", proj_range);
+ shader.uniform1f("proj_ambiance", params.mV[2]);
+ S32 s_idx = -1;
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (mShadowSpotLight[i] == drawablep)
+ {
+ s_idx = i;
+ }
+ }
+
+ shader.uniform1i("proj_shadow_idx", s_idx);
+
+ if (s_idx >= 0)
+ {
+ shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]);
+ }
+ else
+ {
+ shader.uniform1f("shadow_fade", 1.f);
+ }
+
+ {
+ LLDrawable* potential = drawablep;
+ //determine if this is a good light for casting shadows
+ F32 m_pri = volume->getSpotLightPriority();
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ F32 pri = 0.f;
+
+ if (mTargetShadowSpotLight[i].notNull())
+ {
+ pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
+ }
+
+ if (m_pri > pri)
+ {
+ LLDrawable* temp = mTargetShadowSpotLight[i];
+ mTargetShadowSpotLight[i] = potential;
+ potential = temp;
+ m_pri = pri;
+ }
+ }
+ }
+
+ LLViewerTexture* img = volume->getLightTexture();
+
+ S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+ if (channel > -1 && img)
+ {
+ gGL.getTexUnit(channel)->bind(img);
+
+ F32 lod_range = logf(img->getWidth())/logf(2.f);
+
+ shader.uniform1f("proj_focus", focus);
+ shader.uniform1f("proj_lod", lod_range);
+ shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+ }
+}
+
void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
stop_glerror();
@@ -5812,14 +7048,43 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
+ shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
+
for (U32 i = 0; i < 4; i++)
{
+ if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
+ {
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
}
}
+
shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
if (channel > -1)
@@ -5833,6 +7098,8 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->activate();
shader.unbind();
+
+ LLGLState::checkTextureChannels();
}
inline float sgn(float a)
@@ -5866,6 +7133,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
camera.setFar(camera.getFar()*0.87654321f);
LLPipeline::sReflectionRender = TRUE;
S32 occlusion = LLPipeline::sUseOcclusion;
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
LLPipeline::sUseOcclusion = llmin(occlusion, 1);
U32 type_mask = gPipeline.mRenderTypeMask;
@@ -5900,22 +7170,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
water_clip = 1;
}
-
-
if (!LLViewerCamera::getInstance()->cameraUnderWater())
{ //generate planar reflection map
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
glClearColor(0,0,0,0);
- gGL.setColorMask(true, true);
mWaterRef.bindTarget();
mWaterRef.getViewport(gGLViewport);
- mWaterRef.clear();
- gGL.setColorMask(true, false);
-
+
stop_glerror();
- LLVector3 origin = camera.getOrigin();
-
glPushMatrix();
mat.set_scale(glh::vec3f(1,1,-1));
@@ -5930,25 +7193,21 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
- glCullFace(GL_FRONT);
+ glh::matrix4f inv_mat = mat.inverse();
- //initial sky pass (no user clip plane)
- { //mask out everything but the sky
- U32 tmp = mRenderTypeMask;
- mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY));
- static LLCullResult result;
- updateCull(camera, result);
- stateSort(camera, result);
- mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY));
- renderGeom(camera, TRUE);
- mRenderTypeMask = tmp;
- }
+ glh::vec3f origin(0,0,0);
+ inv_mat.mult_matrix_vec(origin);
+ camera.setOrigin(origin.v);
+
+ glCullFace(GL_FRONT);
+
+
+ static LLCullResult ref_result;
+ U32 ref_mask = 0;
if (LLDrawPoolWater::sNeedsDistortionUpdate)
{
+ U32 mask = mRenderTypeMask;
mRenderTypeMask &= ~((1<<LLPipeline::RENDER_TYPE_WATER) |
(1<<LLPipeline::RENDER_TYPE_GROUND) |
(1<<LLPipeline::RENDER_TYPE_SKY) |
@@ -5971,24 +7230,60 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
}
}
- LLSpatialPartition::sFreezeState = TRUE;
- LLPipeline::sSkipUpdate = TRUE;
LLGLUserClipPlane clip_plane(plane, mat, projection);
- static LLCullResult result;
- updateCull(camera, result, 1);
- stateSort(camera, result);
+ LLGLDisable cull(GL_CULL_FACE);
+ updateCull(camera, ref_result, 1);
+ stateSort(camera, ref_result);
+ gGL.setColorMask(true, true);
+ mWaterRef.clear();
+ gGL.setColorMask(true, false);
+
+ }
+ else
+ {
+ gGL.setColorMask(true, true);
+ mWaterRef.clear();
+ gGL.setColorMask(true, false);
+ }
+
+ ref_mask = mRenderTypeMask;
+ mRenderTypeMask = mask;
+ }
+
+ //initial sky pass (no user clip plane)
+ { //mask out everything but the sky
+ U32 tmp = mRenderTypeMask;
+ mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
+ static LLCullResult result;
+ updateCull(camera, result);
+ stateSort(camera, result);
+ mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
+ renderGeom(camera, TRUE);
+ mRenderTypeMask = tmp;
+ }
+
+
+ if (LLDrawPoolWater::sNeedsDistortionUpdate)
+ {
+ mRenderTypeMask = ref_mask;
+ if (gSavedSettings.getBOOL("RenderWaterReflections"))
+ {
+ gPipeline.grabReferences(ref_result);
+ LLGLUserClipPlane clip_plane(plane, mat, projection);
renderGeom(camera);
- LLSpatialPartition::sFreezeState = FALSE;
- LLPipeline::sSkipUpdate = FALSE;
}
}
glCullFace(GL_BACK);
glPopMatrix();
mWaterRef.flush();
-
glh_set_current_modelview(current);
}
+ camera.setOrigin(camera_in.getOrigin());
+
//render distortion map
static BOOL last_update = TRUE;
if (last_update)
@@ -6012,12 +7307,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLColor4& col = LLDrawPoolWater::sWaterFogColor;
glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
- gGL.setColorMask(true, true);
mWaterDis.bindTarget();
mWaterDis.getViewport(gGLViewport);
- mWaterDis.clear();
- gGL.setColorMask(true, false);
-
+
if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
{
//clip out geometry on the same side of water as the camera
@@ -6026,6 +7318,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
static LLCullResult result;
updateCull(camera, result, water_clip);
stateSort(camera, result);
+
+ gGL.setColorMask(true, true);
+ mWaterDis.clear();
+ gGL.setColorMask(true, false);
+
renderGeom(camera);
}
@@ -6078,7 +7375,6 @@ glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
dirN = dir;
dirN.normVec();
-
ret.m[ 0] = lftN[0];
ret.m[ 1] = upN[0];
@@ -6133,10 +7429,484 @@ static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
-void LLPipeline::generateSunShadow(LLCamera& camera)
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
+{
+ LLFastTimer t(FTM_SHADOW_RENDER);
+
+ //clip out geometry on the same side of water as the camera
+ S32 occlude = LLPipeline::sUseOcclusion;
+ if (!use_occlusion)
+ {
+ LLPipeline::sUseOcclusion = 0;
+ }
+ LLPipeline::sShadowRender = TRUE;
+
+ U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, LLRenderPass::PASS_FULLBRIGHT_SHINY };
+ LLGLEnable cull(GL_CULL_FACE);
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.bind();
+ }
+
+ updateCull(shadow_cam, result);
+ stateSort(shadow_cam, result);
+
+ //generate shadow map
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(proj.m);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf(view.m);
+
+ stop_glerror();
+ gGLLastMatrix = NULL;
+
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ glColor4f(1,1,1,1);
+
+ stop_glerror();
+
+ gGL.setColorMask(false, false);
+
+ //glCullFace(GL_FRONT);
+
+ {
+ LLFastTimer ftm(FTM_SHADOW_SIMPLE);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->disable();
+ for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
+ {
+ renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+ }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ renderGeomShadow(shadow_cam);
+ gDeferredShadowProgram.bind();
+ }
+ else
+ {
+ renderGeomShadow(shadow_cam);
+ }
+
+ {
+ LLFastTimer ftm(FTM_SHADOW_ALPHA);
+ LLGLEnable test(GL_ALPHA_TEST);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
+ renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
+ glColor4f(1,1,1,1);
+ renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+ gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+ }
+
+ //glCullFace(GL_BACK);
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+ doOcclusion(shadow_cam);
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ }
+
+ gGL.setColorMask(true, true);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ gGLLastMatrix = NULL;
+
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = FALSE;
+}
+
+
+BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
+{
+ //get point cloud of intersection of frust and min, max
+
+ //get set of planes
+ std::vector<LLPlane> ps;
+
+ if (getVisibleExtents(camera, min, max))
+ {
+ return FALSE;
+ }
+
+ ps.push_back(LLPlane(min, LLVector3(-1,0,0)));
+ ps.push_back(LLPlane(min, LLVector3(0,-1,0)));
+ ps.push_back(LLPlane(min, LLVector3(0,0,-1)));
+ ps.push_back(LLPlane(max, LLVector3(1,0,0)));
+ ps.push_back(LLPlane(max, LLVector3(0,1,0)));
+ ps.push_back(LLPlane(max, LLVector3(0,0,1)));
+
+ /*if (!light_dir.isExactlyZero())
+ {
+ LLPlane ucp;
+ LLPlane mcp;
+
+ F32 maxd = -1.f;
+ F32 mind = 1.f;
+
+ for (U32 i = 0; i < ps.size(); ++i)
+ { //pick the plane most aligned to lightDir for user clip plane
+ LLVector3 n(ps[i].mV);
+ F32 da = n*light_dir;
+ if (da > maxd)
+ {
+ maxd = da;
+ ucp = ps[i];
+ }
+
+ if (da < mind)
+ {
+ mind = da;
+ mcp = ps[i];
+ }
+ }
+
+ camera.setUserClipPlane(ucp);
+
+ ps.clear();
+ ps.push_back(ucp);
+ ps.push_back(mcp);
+ }*/
+
+ for (U32 i = 0; i < 6; i++)
+ {
+ ps.push_back(camera.getAgentPlane(i));
+ }
+
+ //get set of points where planes intersect and points are not above any plane
+ fp.clear();
+
+ for (U32 i = 0; i < ps.size(); ++i)
+ {
+ for (U32 j = 0; j < ps.size(); ++j)
+ {
+ for (U32 k = 0; k < ps.size(); ++k)
+ {
+ if (i == j ||
+ i == k ||
+ k == j)
+ {
+ continue;
+ }
+
+ LLVector3 n1,n2,n3;
+ F32 d1,d2,d3;
+
+ n1.setVec(ps[i].mV);
+ n2.setVec(ps[j].mV);
+ n3.setVec(ps[k].mV);
+
+ d1 = ps[i].mV[3];
+ d2 = ps[j].mV[3];
+ d3 = ps[k].mV[3];
+
+ //get point of intersection of 3 planes "p"
+ LLVector3 p = (-d1*(n2%n3)-d2*(n3%n1)-d3*(n1%n2))/(n1*(n2%n3));
+
+ if (llround(p*n1+d1, 0.0001f) == 0.f &&
+ llround(p*n2+d2, 0.0001f) == 0.f &&
+ llround(p*n3+d3, 0.0001f) == 0.f)
+ { //point is on all three planes
+ BOOL found = TRUE;
+ for (U32 l = 0; l < ps.size() && found; ++l)
+ {
+ if (llround(ps[l].dist(p), 0.0001f) > 0.0f)
+ { //point is above some plane, not contained
+ found = FALSE;
+ }
+ }
+
+ if (found)
+ {
+ fp.push_back(p);
+ }
+ }
+ }
+ }
+ }
+
+ if (fp.empty())
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc)
+{
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) < 3)
+ {
+ return;
+ }
+
+ LLVector3 up;
+
+ //LLGLEnable depth_clamp(GL_DEPTH_CLAMP_NV);
+
+ if (lightDir.mV[2] > 0.5f)
+ {
+ up = LLVector3(1,0,0);
+ }
+ else
+ {
+ up = LLVector3(0, 0, 1);
+ }
+
+
+ F32 gi_range = gSavedSettings.getF32("RenderGIRange");
+
+ U32 res = mGIMap.getWidth();
+
+ F32 atten = llmax(gSavedSettings.getF32("RenderGIAttenuation"), 0.001f);
+
+ //set radius to range at which distance attenuation of incoming photons is near 0
+
+ F32 lrad = sqrtf(1.f/(atten*0.01f));
+
+ F32 lrange = lrad+gi_range*0.5f;
+
+ LLVector3 pad(lrange,lrange,lrange);
+
+ glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up);
+
+ LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f);
+
+ glh::vec3f scp(cp.mV);
+ view.mult_matrix_vec(scp);
+ cp.setVec(scp.v);
+
+ F32 pix_width = lrange/(res*0.5f);
+
+ //move cp to the nearest pix_width
+ for (U32 i = 0; i < 3; i++)
+ {
+ cp.mV[i] = llround(cp.mV[i], pix_width);
+ }
+
+ LLVector3 min = cp-pad;
+ LLVector3 max = cp+pad;
+
+ //set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point
+ mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res;
+ mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res;
+ mGILightRadius = lrad/lrange*0.5f;
+
+ glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+
+ LLCamera sun_cam = camera;
+
+ glh::matrix4f eye_view = glh_get_current_modelview();
+
+ //get eye space to camera space matrix
+ mGIMatrix = view*eye_view.inverse();
+ mGINormalMatrix = mGIMatrix.inverse().transpose();
+ mGIInvProj = proj.inverse();
+ mGIMatrixProj = proj*mGIMatrix;
+
+ //translate and scale to [0,1]
+ glh::matrix4f trans(.5f, 0.f, 0.f, .5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ mGIMatrixProj = trans*mGIMatrixProj;
+
+ glh_set_current_modelview(view);
+ glh_set_current_projection(proj);
+
+ LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE);
+
+ sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+ static LLCullResult result;
+
+ U32 type_mask = mRenderTypeMask;
+
+ mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
+ (1<<LLPipeline::RENDER_TYPE_BUMP) |
+ (1<<LLPipeline::RENDER_TYPE_VOLUME) |
+ (1<<LLPipeline::RENDER_TYPE_TREE) |
+ (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
+ (1<<LLPipeline::RENDER_TYPE_WATER) |
+ (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) |
+ (1<<LLPipeline::RENDER_TYPE_AVATAR) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY));
+
+
+
+ S32 occlude = LLPipeline::sUseOcclusion;
+ //LLPipeline::sUseOcclusion = 0;
+ LLPipeline::sShadowRender = TRUE;
+
+ //only render large objects into GI map
+ sMinRenderSize = gSavedSettings.getF32("RenderGIMinRenderSize");
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_GI_SOURCE;
+ mGIMap.bindTarget();
+
+ F64 last_modelview[16];
+ F64 last_projection[16];
+ for (U32 i = 0; i < 16; i++)
+ {
+ last_modelview[i] = gGLLastModelView[i];
+ last_projection[i] = gGLLastProjection[i];
+ gGLLastModelView[i] = mGIModelview.m[i];
+ gGLLastProjection[i] = mGIProjection.m[i];
+ }
+
+ sun_cam.setOrigin(0.f, 0.f, 0.f);
+ updateCull(sun_cam, result);
+ stateSort(sun_cam, result);
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = last_modelview[i];
+ gGLLastProjection[i] = last_projection[i];
+ }
+
+ mGIProjection = proj;
+ mGIModelview = view;
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ //generate GI map
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(proj.m);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf(view.m);
+
+ stop_glerror();
+ gGLLastMatrix = NULL;
+
+ mGIMap.clear();
+
+ {
+ //LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+ renderGeomDeferred(camera);
+ }
+
+ mGIMap.flush();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ gGLLastMatrix = NULL;
+
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = FALSE;
+ sMinRenderSize = 0.f;
+
+ mRenderTypeMask = type_mask;
+
+}
+
+void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
{
+ if (obj && obj->getVolume())
+ {
+ for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
+ {
+ renderHighlight(*iter, fade);
+ }
+
+ LLDrawable* drawable = obj->mDrawable;
+ if (drawable)
+ {
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ if (face)
+ {
+ face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
+ }
+ }
+ }
+ }
+}
+
+void LLPipeline::generateHighlight(LLCamera& camera)
+{
+ //render highlighted object as white into offscreen render target
+
+ if (mHighlightObject.notNull())
+ {
+ mHighlightSet.insert(HighlightItem(mHighlightObject));
+ }
+
+ if (!mHighlightSet.empty())
+ {
+ F32 transition = gFrameIntervalSeconds/gSavedSettings.getF32("RenderHighlightFadeTime");
+
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ mHighlight.bindTarget();
+ disableLights();
+ gGL.setColorMask(true, true);
+ mHighlight.clear();
+
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+ for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
+ {
+ std::set<HighlightItem>::iterator cur_iter = iter++;
+
+ if (cur_iter->mItem.isNull())
+ {
+ mHighlightSet.erase(cur_iter);
+ continue;
+ }
+
+ if (cur_iter->mItem == mHighlightObject)
+ {
+ cur_iter->incrFade(transition);
+ }
+ else
+ {
+ cur_iter->incrFade(-transition);
+ if (cur_iter->mFade <= 0.f)
+ {
+ mHighlightSet.erase(cur_iter);
+ continue;
+ }
+ }
+
+ renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
+ }
- if (!sRenderDeferred)
+ mHighlight.flush();
+ gGL.setColorMask(true, false);
+ }
+}
+
+
+void LLPipeline::generateSunShadow(LLCamera& camera)
+{
+ if (!sRenderDeferred || !gSavedSettings.getBOOL("RenderDeferredShadow"))
{
return;
}
@@ -6149,98 +7919,173 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (clear)
{
clear = FALSE;
- for (U32 i = 0; i < 4; i++)
+ for (U32 i = 0; i < 6; i++)
{
- mSunShadow[i].bindTarget();
- mSunShadow[i].clear();
- mSunShadow[i].flush();
+ mShadow[i].bindTarget();
+ mShadow[i].clear();
+ mShadow[i].flush();
}
}
return;
}
clear = TRUE;
+ F64 last_modelview[16];
+ F64 last_projection[16];
+ for (U32 i = 0; i < 16; i++)
+ { //store last_modelview of world camera
+ last_modelview[i] = gGLLastModelView[i];
+ last_projection[i] = gGLLastProjection[i];
+ }
+
+ U32 type_mask = mRenderTypeMask;
+ mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1<<LLPipeline::RENDER_TYPE_ALPHA) |
+ (1<<LLPipeline::RENDER_TYPE_GRASS) |
+ (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
+ (1<<LLPipeline::RENDER_TYPE_BUMP) |
+ (1<<LLPipeline::RENDER_TYPE_VOLUME) |
+ (1<<LLPipeline::RENDER_TYPE_AVATAR) |
+ (1<<LLPipeline::RENDER_TYPE_TREE) |
+ (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
+ (1<<LLPipeline::RENDER_TYPE_WATER) |
+ (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY));
+
gGL.setColorMask(false, false);
//get sun view matrix
- F32 range = 128.f;
-
//store current projection/modelview matrix
glh::matrix4f saved_proj = glh_get_current_projection();
glh::matrix4f saved_view = glh_get_current_modelview();
glh::matrix4f inv_view = saved_view.inverse();
- glh::matrix4f view[4];
- glh::matrix4f proj[4];
- LLVector3 up;
-
+ glh::matrix4f view[6];
+ glh::matrix4f proj[6];
+
//clip contains parallel split distances for 3 splits
LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes");
+ //F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
+
//far clip on last split is minimum of camera view distance and 128
mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
- const LLPickInfo& pick_info = gViewerWindow->getLastPick();
-
- if (!pick_info.mPosGlobal.isExactlyZero())
- { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object
- F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec();
- mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]);
- }
-
- // convenience array of 4 near clip plane distances
- F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+ clip = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
+ mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
//currently used for amount to extrude frusta corners for constructing shadow frusta
LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist");
- F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+ //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
- for (S32 j = 0; j < 4; j++)
- {
- //restore render matrices
- glh_set_current_modelview(saved_view);
- glh_set_current_projection(saved_proj);
+ LLVector3 lightDir = -mSunDir;
+ lightDir.normVec();
- //get center of far clip plane (for point of interest later)
- LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range;
+ glh::vec3f light_dir(lightDir.mV);
- LLVector3 eye = camera.getOrigin();
+ //create light space camera matrix
+
+ LLVector3 at = lightDir;
- //camera used for shadow cull/render
- LLCamera shadow_cam;
-
- // perspective shadow map
- glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space)
- glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space)
-
- LLVector3 lightDir = -mSunDir;
- glh::vec3f light_dir(lightDir.mV);
+ LLVector3 up = camera.getAtAxis();
+
+ if (fabsf(up*lightDir) > 0.75f)
+ {
+ up = camera.getUpAxis();
+ }
+
+ /*LLVector3 left = up%at;
+ up = at%left;*/
- //create light space camera matrix
- LLVector3 at;
- F32 dl = camera.getLeftAxis() * lightDir;
- F32 du = camera.getUpAxis() * lightDir;
+ up.normVec();
+ at.normVec();
+
+
+ F32 near_clip = 0.f;
+ {
+ //get visible point cloud
+ std::vector<LLVector3> fp;
- //choose an at axis such that up will be most aligned with lightDir
- if (dl*dl < du*du)
+ LLVector3 min,max;
+ getVisiblePointCloud(camera,min,max,fp);
+
+ if (fp.empty())
{
- at = lightDir%camera.getLeftAxis();
+ mRenderTypeMask = type_mask;
+ return;
}
- else
+
+ generateGI(camera, lightDir, fp);
+
+ //get good split distances for frustum
+ for (U32 i = 0; i < fp.size(); ++i)
{
- at = lightDir%camera.getUpAxis();
+ glh::vec3f v(fp[i].mV);
+ saved_view.mult_matrix_vec(v);
+ fp[i].setVec(v.v);
}
- if (at * camera.getAtAxis() < 0)
+ min = fp[0];
+ max = fp[0];
+
+ //get camera space bounding box
+ for (U32 i = 1; i < fp.size(); ++i)
{
- at = -at;
+ update_min_max(min, max, fp[i]);
}
+
+ near_clip = -max.mV[2];
+ F32 far_clip = -min.mV[2]*2.f;
+
+ far_clip = llmin(far_clip, 128.f);
+ far_clip = llmin(far_clip, camera.getFar());
+
+ F32 range = far_clip-near_clip;
+
+ LLVector3 split_exp = gSavedSettings.getVector3("RenderShadowSplitExponent");
+
+ F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
- LLVector3 left = lightDir%at;
- up = left%lightDir;
- up.normVec();
+ da = powf(da, split_exp.mV[2]);
+
+ F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
+
+
+ for (U32 i = 0; i < 4; ++i)
+ {
+ F32 x = (F32)(i+1)/4.f;
+ x = powf(x, sxp);
+ mSunClipPlanes.mV[i] = near_clip+range*x;
+ }
+ }
+
+ // convenience array of 4 near clip plane distances
+ F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+
+ for (S32 j = 0; j < 4; j++)
+ {
+ if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowFrustPoints[j].clear();
+ }
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
+
+ //restore render matrices
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+
+ LLVector3 eye = camera.getOrigin();
+
+ //camera used for shadow cull/render
+ LLCamera shadow_cam;
+
//create world space camera frustum for this split
shadow_cam = camera;
shadow_cam.setFar(16.f);
@@ -6251,8 +8096,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLVector3 pn = shadow_cam.getAtAxis();
- LLVector3 frust_center;
-
LLVector3 min, max;
//construct 8 corners of split frustum section
@@ -6263,21 +8106,19 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
F32 dp = delta*pn;
frust[i] = eye + (delta*dist[j])/dp;
frust[i+4] = eye + (delta*dist[j+1])/dp;
- frust_center += frust[i] + frust[i+4];
}
-
- //get frustum center
- frust_center /= 8.f;
shadow_cam.calcAgentFrustumPlanes(frust);
-
+ shadow_cam.mFrustumCornerDist = 0.f;
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
mShadowCamera[j] = shadow_cam;
}
- if (gPipeline.getVisibleExtents(shadow_cam, min, max))
+ std::vector<LLVector3> fp;
+
+ if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
{
//no possible shadow receivers
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
@@ -6287,6 +8128,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowCamera[j+4] = shadow_cam;
}
+ mShadow[j].bindTarget();
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mShadow[j].clear();
+ }
+ mShadow[j].flush();
+
+ mShadowError.mV[j] = 0.f;
+ mShadowFOV.mV[j] = 0.f;
+
continue;
}
@@ -6294,53 +8145,263 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
{
mShadowExtents[j][0] = min;
mShadowExtents[j][1] = max;
+ mShadowFrustPoints[j] = fp;
}
- view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up);
- F32 shadow_dist = nearDist[j];
- for (U32 i = 0; i < 8; i++)
+ //find a good origin for shadow projection
+ LLVector3 origin;
+
+ //get a temporary view projection
+ view[j] = look(camera.getOrigin(), lightDir, -up);
+
+ std::vector<LLVector3> wpf;
+
+ for (U32 i = 0; i < fp.size(); i++)
{
- //points in worldspace (wp) and light camera space (p)
- //that must be included in shadow generation
- wp[i] = glh::vec3f(frust[i].mV);
- wp[i+8] = wp[i] - light_dir*shadow_dist;
- view[j].mult_matrix_vec(wp[i], p[i]);
- view[j].mult_matrix_vec(wp[i+8], p[i+8]);
+ glh::vec3f p = glh::vec3f(fp[i].mV);
+ view[j].mult_matrix_vec(p);
+ wpf.push_back(LLVector3(p.v));
}
-
- min = LLVector3(p[0].v);
- max = LLVector3(p[0].v);
- LLVector3 fmin = min;
- LLVector3 fmax = max;
+ min = wpf[0];
+ max = wpf[0];
- for (U32 i = 1; i < 16; i++)
- { //find camera space AABB of frustum in light camera space
- update_min_max(min, max, LLVector3(p[i].v));
- if (i < 8)
- {
- update_min_max(fmin, fmax, LLVector3(p[i].v));
+ for (U32 i = 0; i < fp.size(); ++i)
+ { //get AABB in camera space
+ update_min_max(min, max, wpf[i]);
+ }
+
+ // Construct a perspective transform with perspective along y-axis that contains
+ // points in wpf
+ //Known:
+ // - far clip plane
+ // - near clip plane
+ // - points in frustum
+ //Find:
+ // - origin
+
+ //get some "interesting" points of reference
+ LLVector3 center = (min+max)*0.5f;
+ LLVector3 size = (max-min)*0.5f;
+ LLVector3 near_center = center;
+ near_center.mV[1] += size.mV[1]*2.f;
+
+
+ //put all points in wpf in quadrant 0, reletive to center of min/max
+ //get the best fit line using least squares
+ F32 bfm = 0.f;
+ F32 bfb = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ wpf[i] -= center;
+ wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
+ wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
+ }
+
+ if (!wpf.empty())
+ {
+ F32 sx = 0.f;
+ F32 sx2 = 0.f;
+ F32 sy = 0.f;
+ F32 sxy = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ sx += wpf[i].mV[0];
+ sx2 += wpf[i].mV[0]*wpf[i].mV[0];
+ sy += wpf[i].mV[1];
+ sxy += wpf[i].mV[0]*wpf[i].mV[1];
}
+
+ bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
+ bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
}
+
+ {
+ // best fit line is y=bfm*x+bfb
+
+ //find point that is furthest to the right of line
+ F32 off_x = -1.f;
+ LLVector3 lp;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ //y = bfm*x+bfb
+ //x = (y-bfb)/bfm
+ F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+
+ lx = wpf[i].mV[0]-lx;
+
+ if (off_x < lx)
+ {
+ off_x = lx;
+ lp = wpf[i];
+ }
+ }
+
+ //get line with slope bfm through lp
+ // bfb = y-bfm*x
+ bfb = lp.mV[1]-bfm*lp.mV[0];
+
+ //calculate error
+ mShadowError.mV[j] = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+ mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
+ }
+
+ mShadowError.mV[j] /= wpf.size();
+ mShadowError.mV[j] /= size.mV[0];
+
+ if (mShadowError.mV[j] > gSavedSettings.getF32("RenderShadowErrorCutoff"))
+ { //just use ortho projection
+ mShadowFOV.mV[j] = -1.f;
+ origin.clearVec();
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+ }
+ else
+ {
+ //origin is where line x = 0;
+ origin.setVec(0,bfb,0);
- //generate perspective matrix that contains frustum
- //proj[j] = matrix_perspective(min, max);
- proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ F32 fovz = 1.f;
+ F32 fovx = 1.f;
+
+ LLVector3 zp;
+ LLVector3 xp;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ LLVector3 atz = wpf[i]-origin;
+ atz.mV[0] = 0.f;
+ atz.normVec();
+ if (fovz > -atz.mV[1])
+ {
+ zp = wpf[i];
+ fovz = -atz.mV[1];
+ }
+
+ LLVector3 atx = wpf[i]-origin;
+ atx.mV[2] = 0.f;
+ atx.normVec();
+ if (fovx > -atx.mV[1])
+ {
+ fovx = -atx.mV[1];
+ xp = wpf[i];
+ }
+ }
+
+ fovx = acos(fovx);
+ fovz = acos(fovz);
+
+ F32 cutoff = llmin(gSavedSettings.getF32("RenderShadowFOVCutoff"), 1.4f);
+
+ mShadowFOV.mV[j] = fovx;
+
+ if (fovx < cutoff && fovz > cutoff)
+ {
+ //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
+ F32 d = zp.mV[2]/tan(cutoff);
+ F32 ny = zp.mV[1] + fabsf(d);
+
+ origin.mV[1] = ny;
+
+ fovz = 1.f;
+ fovx = 1.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ LLVector3 atz = wpf[i]-origin;
+ atz.mV[0] = 0.f;
+ atz.normVec();
+ fovz = llmin(fovz, -atz.mV[1]);
+
+ LLVector3 atx = wpf[i]-origin;
+ atx.mV[2] = 0.f;
+ atx.normVec();
+ fovx = llmin(fovx, -atx.mV[1]);
+ }
+
+ fovx = acos(fovx);
+ fovz = acos(fovz);
+
+ if (fovx > cutoff || llround(fovz, 0.01f) > cutoff)
+ {
+ // llerrs << "WTF?" << llendl;
+ }
+
+ mShadowFOV.mV[j] = cutoff;
+ }
+
+
+ origin += center;
+
+ F32 ynear = -(max.mV[1]-origin.mV[1]);
+ F32 yfar = -(min.mV[1]-origin.mV[1]);
+
+ if (ynear < 0.1f) //keep a sensible near clip plane
+ {
+ F32 diff = 0.1f-ynear;
+ origin.mV[1] += diff;
+ ynear += diff;
+ yfar += diff;
+ }
+
+ if (fovx > cutoff)
+ { //just use ortho projection
+ origin.clearVec();
+ mShadowError.mV[j] = -1.f;
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
min.mV[1], max.mV[1],
-max.mV[2], -min.mV[2]);
-
+ }
+ else
+ {
+ //get perspective projection
+ view[j] = view[j].inverse();
+
+ glh::vec3f origin_agent(origin.mV);
+
+ //translate view to origin
+ view[j].mult_matrix_vec(origin_agent);
+
+ eye = LLVector3(origin_agent.v);
+
+ if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowFrustOrigin[j] = eye;
+ }
+
+ view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
+
+ F32 fx = 1.f/tanf(fovx);
+ F32 fz = 1.f/tanf(fovz);
+
+ proj[j] = glh::matrix4f(-fx, 0, 0, 0,
+ 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
+ 0, 0, -fz, 0,
+ 0, -1.f, 0, 0);
+ }
+ }
+ }
+
shadow_cam.setFar(128.f);
shadow_cam.setOriginAndLookAt(eye, up, center);
+ shadow_cam.setOrigin(0,0,0);
+
glh_set_current_modelview(view[j]);
glh_set_current_projection(proj[j]);
LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0],
- fmin.mV[1], fmax.mV[1],
- -fmax.mV[2], -fmin.mV[2]);
+ shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
//translate and scale to from [-1, 1] to [0, 1]
glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
@@ -6351,113 +8412,168 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
glh_set_current_modelview(view[j]);
glh_set_current_projection(proj[j]);
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = mShadowModelview[j].m[i];
+ gGLLastProjection[i] = mShadowProjection[j].m[i];
+ }
+
+ mShadowModelview[j] = view[j];
+ mShadowProjection[j] = proj[j];
+
+
mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
- U32 type_mask = mRenderTypeMask;
- mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
- (1<<LLPipeline::RENDER_TYPE_ALPHA) |
- (1<<LLPipeline::RENDER_TYPE_GRASS) |
- (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
- (1<<LLPipeline::RENDER_TYPE_BUMP) |
- (1<<LLPipeline::RENDER_TYPE_VOLUME) |
- (1<<LLPipeline::RENDER_TYPE_AVATAR) |
- (1<<LLPipeline::RENDER_TYPE_TREE) |
- (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
- 0);
-
- //clip out geometry on the same side of water as the camera
- static LLCullResult result;
- S32 occlude = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 1;
- LLPipeline::sShadowRender = TRUE;
- //hack to prevent LOD updates from using sun camera origin
- shadow_cam.setOrigin(camera.getOrigin());
- updateCull(shadow_cam, result);
- stateSort(shadow_cam, result);
-
+ stop_glerror();
+
+ mShadow[j].bindTarget();
+ mShadow[j].getViewport(gGLViewport);
+
+ {
+ static LLCullResult result[4];
+
+ //LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+ renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
+ }
+
+ mShadow[j].flush();
+
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
mShadowCamera[j+4] = shadow_cam;
}
+ }
- LLFastTimer t(FTM_SHADOW_RENDER);
+
- stop_glerror();
+ F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
+
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
+
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
+
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
- mSunShadow[j].bindTarget();
- mSunShadow[j].getViewport(gGLViewport);
+ for (S32 i = 0; i < 2; i++)
+ {
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+ if (mShadowSpotLight[i].isNull())
{
- LLGLDepthTest depth(GL_TRUE);
- mSunShadow[j].clear();
+ continue;
}
- U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP };
- LLGLEnable cull(GL_CULL_FACE);
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- //generate sun shadow map
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadMatrixf(proj[j].m);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadMatrixf(view[j].m);
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- stop_glerror();
- gGLLastMatrix = NULL;
+ LLDrawable* drawable = mShadowSpotLight[i];
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- glColor4f(1,1,1,1);
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
+
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
+
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+ at_axis *= quat;
+
+ LLVector3 np = center+at_axis;
+ at_axis.normVec();
+
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+ LLVector3 origin = np - at_axis*dist;
+
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+
+ view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+
+ view[i+4] = view[i+4].inverse();
+
+ //get perspective matrix
+ F32 near_clip = dist+0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist+volume->getLightRadius()*1.5f;
+
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width/height;
- glCullFace(GL_FRONT);
+ proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- stop_glerror();
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- gGL.setColorMask(false, false);
+ glh_set_current_modelview(view[i+4]);
+ glh_set_current_projection(proj[i+4]);
- gDeferredShadowProgram.bind();
- {
- LLFastTimer ftm(FTM_SHADOW_SIMPLE);
- LLGLDisable test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->disable();
- for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
- {
- renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
- }
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
+ mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
+ for (U32 j = 0; j < 16; j++)
{
- LLFastTimer ftm(FTM_SHADOW_ALPHA);
- LLGLEnable test(GL_ALPHA_TEST);
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
- renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
- glColor4f(1,1,1,1);
- renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+ gGLLastModelView[j] = mShadowModelview[i+4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i+4].m[j];
}
-
- gDeferredShadowProgram.unbind();
- renderGeomShadow(shadow_cam);
+ mShadowModelview[i+4] = view[i+4];
+ mShadowProjection[i+4] = proj[i+4];
- gGL.setColorMask(true, true);
+ LLCamera shadow_cam = camera;
+ shadow_cam.setFar(far_clip);
+ shadow_cam.setOrigin(origin);
- glCullFace(GL_BACK);
- LLPipeline::sUseOcclusion = occlude;
- LLPipeline::sShadowRender = FALSE;
- mRenderTypeMask = type_mask;
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- gGLLastMatrix = NULL;
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- mSunShadow[j].flush();
- }
+ stop_glerror();
+
+ mShadow[i+4].bindTarget();
+ mShadow[i+4].getViewport(gGLViewport);
+
+ static LLCullResult result[2];
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
+
+ renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
+
+ mShadow[i+4].flush();
+ }
if (!gSavedSettings.getBOOL("CameraOffset"))
{
@@ -6474,6 +8590,14 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
glMatrixMode(GL_MODELVIEW);
}
gGL.setColorMask(true, false);
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = last_modelview[i];
+ gGLLastProjection[i] = last_projection[i];
+ }
+
+ mRenderTypeMask = type_mask;
}
void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
@@ -6482,7 +8606,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu
{
LLSpatialGroup* group = *i;
if (!group->isDead() &&
- (!sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) &&
+ (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
group->mDrawMap.find(type) != group->mDrawMap.end())
{
@@ -6525,7 +8649,16 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
(1<<LLPipeline::RENDER_TYPE_SIMPLE) |
(1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
(1<<LLPipeline::RENDER_TYPE_ALPHA) |
- (1<<LLPipeline::RENDER_TYPE_INVISIBLE);
+ (1<<LLPipeline::RENDER_TYPE_INVISIBLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
}
mask = mask & gPipeline.getRenderTypeMask();
@@ -6535,6 +8668,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
S32 occlusion = sUseOcclusion;
sUseOcclusion = 0;
sReflectionRender = sRenderDeferred ? FALSE : TRUE;
+ sShadowRender = TRUE;
sImpostorRender = TRUE;
markVisible(avatar->mDrawable, *LLViewerCamera::getInstance());
@@ -6611,20 +8745,23 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
resY != avatar->mImpostor.getHeight())
{
+ avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
+
if (LLPipeline::sRenderDeferred)
{
- avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE);
addDeferredAttachments(avatar->mImpostor);
}
- else
- {
- avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
- }
+
gGL.getTexUnit(0)->bind(&avatar->mImpostor);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilMask(0xFFFFFFFF);
+ glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
{
LLGLEnable scissor(GL_SCISSOR_TEST);
glScissor(0, 0, resX, resY);
@@ -6632,15 +8769,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
avatar->mImpostor.clear();
}
- LLGLEnable stencil(GL_STENCIL_TEST);
-
- glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
if (LLPipeline::sRenderDeferred)
{
stop_glerror();
renderGeomDeferred(camera);
+ renderGeomPostDeferred(camera);
}
else
{
@@ -6650,11 +8783,16 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
- if (!sRenderDeferred || muted)
- {
+ { //create alpha mask based on stencil buffer (grey out if muted)
LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
+ if (LLPipeline::sRenderDeferred)
+ {
+ GLuint buff = GL_COLOR_ATTACHMENT0_EXT;
+ glDrawBuffersARB(1, &buff);
+ }
+
LLGLEnable blend(muted ? 0 : GL_BLEND);
if (muted)
@@ -6693,6 +8831,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
sUseOcclusion = occlusion;
sReflectionRender = FALSE;
sImpostorRender = FALSE;
+ sShadowRender = FALSE;
gPipeline.mRenderTypeMask = saved_mask;
glMatrixMode(GL_PROJECTION);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 8f6867aa01..ce50a37405 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -150,6 +150,8 @@ public:
void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE);
void markShift(LLDrawable *drawablep);
void markTextured(LLDrawable *drawablep);
+ void markGLRebuild(LLGLUpdate* glu);
+ void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE);
void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);
//get the object between start and end that's closest to start.
@@ -200,10 +202,14 @@ public:
void updateMove();
BOOL visibleObjectsInFrustum(LLCamera& camera);
BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max);
+ BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0));
void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
void createObjects(F32 max_dtime);
void createObject(LLViewerObject* vobj);
void updateGeom(F32 max_dtime);
+ void updateGL();
+ void rebuildPriorityGroups();
+ void rebuildGroups();
//calculate pixel area of given box from vantage point of given camera
static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera);
@@ -224,12 +230,21 @@ public:
void renderGeomDeferred(LLCamera& camera);
void renderGeomPostDeferred(LLCamera& camera);
void renderGeomShadow(LLCamera& camera);
- void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0);
+ void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* gi_source = NULL, LLRenderTarget* last_gi_post = NULL, U32 noise_map = 0xFFFFFFFF);
+ void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
+
void unbindDeferredShader(LLGLSLShader& shader);
void renderDeferredLighting();
void generateWaterReflection(LLCamera& camera);
void generateSunShadow(LLCamera& camera);
+ void generateHighlight(LLCamera& camera);
+ void renderHighlight(const LLViewerObject* obj, F32 fade);
+ void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; }
+
+
+ void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE);
+ void generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc);
void renderHighlights();
void renderDebug();
@@ -324,23 +339,35 @@ public:
enum LLRenderTypeMask
{
// Following are pool types (some are also object types)
- RENDER_TYPE_SKY = LLDrawPool::POOL_SKY,
- RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY,
- RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND,
- RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN,
- RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE,
- RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS,
- RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT,
- RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP,
- RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
- RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
- RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
- RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
- RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
- RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
-
+ RENDER_TYPE_SKY = LLDrawPool::POOL_SKY,
+ RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY,
+ RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND,
+ RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN,
+ RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE,
+ RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS,
+ RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT,
+ RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP,
+ RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
+ RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
+ RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
+ RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
+ RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
+ RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
+ RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE,
+ RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS,
+ RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT,
+ RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE,
+ RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY,
+ RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY,
+ RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY,
+ RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP,
+ RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW,
+ RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA,
+ RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK,
+ RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK,
+ RENDER_TYPE_PASS_ALPHA_SHADOW = LLRenderPass::PASS_ALPHA_SHADOW,
// Following are object types (only used in drawable mRenderType)
- RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES,
+ RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES,
RENDER_TYPE_VOLUME,
RENDER_TYPE_PARTICLES,
RENDER_TYPE_CLOUDS,
@@ -383,7 +410,8 @@ public:
RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000,
RENDER_DEBUG_SCULPTED = 0x0080000,
RENDER_DEBUG_AVATAR_VOLUME = 0x0100000,
- RENDER_DEBUG_AGENT_TARGET = 0x0200000,
+ RENDER_DEBUG_BUILD_QUEUE = 0x0200000,
+ RENDER_DEBUG_AGENT_TARGET = 0x0400000,
};
public:
@@ -423,7 +451,6 @@ public:
static BOOL sUseFBO;
static BOOL sUseFarClip;
static BOOL sShadowRender;
- static BOOL sSkipUpdate; //skip lod updates
static BOOL sWaterReflections;
static BOOL sDynamicLOD;
static BOOL sPickAvatar;
@@ -437,19 +464,47 @@ public:
static BOOL sRenderAttachedParticles;
static BOOL sRenderDeferred;
static S32 sVisibleLightCount;
+ static F32 sMinRenderSize;
//screen texture
LLRenderTarget mScreen;
+ LLRenderTarget mUIScreen;
LLRenderTarget mDeferredScreen;
- LLRenderTarget mDeferredLight[2];
+ LLRenderTarget mEdgeMap;
+ LLRenderTarget mDeferredDepth;
+ LLRenderTarget mDeferredLight[3];
LLMultisampleBuffer mSampleBuffer;
+ LLRenderTarget mGIMap;
+ LLRenderTarget mGIMapPost[2];
+ LLRenderTarget mLuminanceMap;
+ LLRenderTarget mHighlight;
//sun shadow map
- LLRenderTarget mSunShadow[4];
+ LLRenderTarget mShadow[6];
+ std::vector<LLVector3> mShadowFrustPoints[4];
+ LLVector4 mShadowError;
+ LLVector4 mShadowFOV;
+ LLVector3 mShadowFrustOrigin[4];
LLCamera mShadowCamera[8];
LLVector3 mShadowExtents[4][2];
- glh::matrix4f mSunShadowMatrix[4];
+ glh::matrix4f mSunShadowMatrix[6];
+ glh::matrix4f mShadowModelview[6];
+ glh::matrix4f mShadowProjection[6];
+ glh::matrix4f mGIMatrix;
+ glh::matrix4f mGIMatrixProj;
+ glh::matrix4f mGIModelview;
+ glh::matrix4f mGIProjection;
+ glh::matrix4f mGINormalMatrix;
+ glh::matrix4f mGIInvProj;
+ LLVector2 mGIRange;
+ F32 mGILightRadius;
+
+ LLPointer<LLDrawable> mShadowSpotLight[2];
+ F32 mSpotLightFade[2];
+ LLPointer<LLDrawable> mTargetShadowSpotLight[2];
+
LLVector4 mSunClipPlanes;
+ LLVector4 mSunOrthoClipPlanes;
LLVector2 mScreenScale;
@@ -464,6 +519,8 @@ public:
//noise map
U32 mNoiseMap;
+ U32 mTrueNoiseMap;
+ U32 mLightFunc;
LLColor4 mSunDiffuse;
LLVector3 mSunDir;
@@ -524,12 +581,45 @@ protected:
//
LLDrawable::drawable_list_t mBuildQ1; // priority
LLDrawable::drawable_list_t mBuildQ2; // non-priority
+ LLSpatialGroup::sg_list_t mGroupQ1; //priority
+ LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority
+
LLViewerObject::vobj_list_t mCreateQ;
LLDrawable::drawable_set_t mActiveQ;
LLDrawable::drawable_set_t mRetexturedList;
+ class HighlightItem
+ {
+ public:
+ const LLPointer<LLDrawable> mItem;
+ mutable F32 mFade;
+
+ HighlightItem(LLDrawable* item)
+ : mItem(item), mFade(0)
+ {
+ }
+
+ bool operator<(const HighlightItem& rhs) const
+ {
+ return mItem < rhs.mItem;
+ }
+
+ bool operator==(const HighlightItem& rhs) const
+ {
+ return mItem == rhs.mItem;
+ }
+
+ void incrFade(F32 val) const
+ {
+ mFade = llclamp(mFade+val, 0.f, 1.f);
+ }
+ };
+
+ std::set<HighlightItem> mHighlightSet;
+ LLPointer<LLDrawable> mHighlightObject;
+
//////////////////////////////////////////////////
//
// Draw pools are responsible for storing all rendered data,
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 327dc07cbe..46679c19d2 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -2124,29 +2124,50 @@
name="colorswatch"
tool_tip="Click to open Color Picker"
width="40" />
- <spinner
+ <texture_picker
+ allow_no_texture="true"
+ top_delta="0"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="48"
+ label=""
+ left_delta="57"
+ mouse_opaque="true"
+ name="light texture control"
+ tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)"
+ width="32" />
+ <spinner
follows="left|top"
height="19"
initial_value="0.5"
label="Intensity"
label_width="70"
layout="topleft"
- left_pad="15"
+ left="10"
name="Light Intensity"
- top_pad="-50"
+ top_pad="3"
width="128" />
- <spinner
+ <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16"
+ increment="0.1" initial_val="0.5" label="FOV" label_width="55"
+ left="144" max_val="3" min_val="0" mouse_opaque="true"
+ name="Light FOV" width="120" />
+ <spinner
follows="left|top"
height="19"
initial_value="5"
label="Radius"
label_width="70"
layout="topleft"
- left_delta="0"
+ left="10"
max_val="20"
name="Light Radius"
top_pad="3"
width="128" />
+ <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16"
+ increment="0.5" initial_val="0.5" label="Focus" label_width="55"
+ left="144" max_val="20" min_val="-20" mouse_opaque="true"
+ name="Light Focus" width="120" />
<spinner
follows="left|top"
height="19"
@@ -2155,13 +2176,17 @@
label="Falloff"
label_width="70"
layout="topleft"
- left_delta="0"
+ left="10"
max_val="2"
name="Light Falloff"
top_pad="3"
width="128" />
+ <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16"
+ increment="0.05" initial_val="1" label="Ambiance" label_width="55"
+ left="144" max_val="1" min_val="0" mouse_opaque="true"
+ name="Light Ambiance" width="120" />
</panel>
- <panel
+ <panel
border="false"
follows="left|top|right|bottom"
height="367"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ee15e6f29c..13350c1bf3 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2143,6 +2143,147 @@
</menu>
<menu_item_separator
layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Render Metadata"
+ layout="topleft"
+ name="Render Metadata"
+ tear_off="true">
+ <menu_item_check
+ label="Bounding Boxes"
+ layout="topleft"
+ name="Bounding Boxes">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="bboxes" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="bboxes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Octree"
+ layout="topleft"
+ name="Octree">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="octree" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="octree" />
+ </menu_item_check>
+ <menu_item_check
+ label="Shadow Frusta"
+ layout="topleft"
+ name="Shadow Frusta">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="shadow frusta" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="shadow frusta" />
+ </menu_item_check>
+ <menu_item_check
+ label="Occlusion"
+ layout="topleft"
+ name="Occlusion">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="occlusion" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="occlusion" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Batches"
+ layout="topleft"
+ name="Render Batches">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="render batches" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="render batches" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Anim"
+ layout="topleft"
+ name="Texture Anim">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture anim" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture anim" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Priority"
+ layout="topleft"
+ name="Texture Priority">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture priority" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture priority" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Area"
+ layout="topleft"
+ name="Texture Area">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture area" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture area" />
+ </menu_item_check>
+ <menu_item_check
+ label="Face Area"
+ layout="topleft"
+ name="Face Area">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="face area" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="face area" />
+ </menu_item_check>
+ <menu_item_check
+ label="Lights"
+ layout="topleft"
+ name="Lights">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="lights" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="lights" />
+ </menu_item_check>
+ <menu_item_check
+ label="Collision Skeleton"
+ layout="topleft"
+ name="Collision Skeleton">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="collision skeleton" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="collision skeleton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Raycast"
+ layout="topleft"
+ name="Raycast">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="raycast" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="raycast" />
+ </menu_item_check>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
<menu
create_jump_keys="true"
label="Display Info"
@@ -2406,7 +2547,47 @@
<menu_item_check.on_enable
function="Advanced.EnableObjectObjectOcclusion" />
</menu_item_check>
- <menu_item_check
+ <menu_item_check
+ label="Framebuffer Objects"
+ layout="topleft"
+ name="Framebuffer Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderUseFBO" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderUseFBO" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderFBO" />
+ </menu_item_check>
+ <menu_item_check
+ label="Deferred Rendering"
+ layout="topleft"
+ name="Deferred Rendering">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDeferred" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDeferred" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderDeferred" />
+ </menu_item_check>
+ <menu_item_check
+ label="Global Illumintation"
+ layout="topleft"
+ name="Global Illumination">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDeferredGI" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDeferredGI" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderDeferredGI" />
+ </menu_item_check>
+
+ <menu_item_check
label="Debug GL"
layout="topleft"
name="Debug GL">
@@ -2461,6 +2642,16 @@
function="Advanced.ToggleDisableTextures" />
</menu_item_check>
<menu_item_check
+ label="Texture Atlas"
+ layout="topleft"
+ name="Texture Atlas">
+ <menu_item_check.on_check
+ function="Advanced.CheckTextureAtlas"
+ parameter="TextureAtlas" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleTextureAtlas" />
+ </menu_item_check>
+ <menu_item_check
label="Render Attached Lights"
layout="topleft"
name="Render Attached Lights">