summaryrefslogtreecommitdiff
path: root/indra/newview/lldrawpoolavatar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lldrawpoolavatar.cpp')
-rw-r--r--indra/newview/lldrawpoolavatar.cpp1084
1 files changed, 1015 insertions, 69 deletions
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 8cf4dc1b95..ccc060f3fa 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -2,25 +2,31 @@
* @file lldrawpoolavatar.cpp
* @brief LLDrawPoolAvatar class implementation
*
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
+ * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
*
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
+ * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * 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.
*
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * 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$
*/
@@ -31,15 +37,21 @@
#include "llvoavatar.h"
#include "m3math.h"
+#include "llmatrix4a.h"
+#include "llagent.h" //for gAgent.needsRenderAvatar()
#include "lldrawable.h"
+#include "lldrawpoolbump.h"
#include "llface.h"
+#include "llmeshrepository.h"
#include "llsky.h"
#include "llviewercamera.h"
#include "llviewerregion.h"
#include "noise.h"
#include "pipeline.h"
#include "llviewershadermgr.h"
+#include "llvovolume.h"
+#include "llvolume.h"
#include "llappviewer.h"
#include "llrendersphere.h"
#include "llviewerpartsim.h"
@@ -47,10 +59,15 @@
static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
static U32 sShaderLevel = 0;
-static LLGLSLShader* sVertexProgram = NULL;
+
+LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
+S32 LLDrawPoolAvatar::sDiffuseChannel = 0;
+
+
+static bool is_deferred_render = false;
extern BOOL gUseGLPick;
@@ -86,7 +103,22 @@ BOOL gAvatarEmbossBumpMap = FALSE;
static BOOL sRenderingSkinned = FALSE;
S32 normal_channel = -1;
S32 specular_channel = -1;
-S32 diffuse_channel = -1;
+S32 cube_channel = -1;
+
+#if LL_MESH_ENABLED
+static const U32 rigged_data_mask[] = {
+ LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,
+ LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK,
+ LLDrawPoolAvatar::RIGGED_SHINY_MASK,
+ LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK,
+ LLDrawPoolAvatar::RIGGED_GLOW_MASK,
+ LLDrawPoolAvatar::RIGGED_ALPHA_MASK,
+ LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK,
+ LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK,
+ LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK,
+};
+#endif
+
static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow");
@@ -142,21 +174,17 @@ LLMatrix4& LLDrawPoolAvatar::getModelView()
//-----------------------------------------------------------------------------
-S32 LLDrawPoolAvatar::getNumDeferredPasses()
-{
- return getNumPasses();
-}
void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
{
LLFastTimer t(FTM_RENDER_CHARACTERS);
sSkipTransparent = TRUE;
-
+ is_deferred_render = true;
+
if (LLPipeline::sImpostorRender)
- {
- beginDeferredSkinned();
- return;
+ { //impostor pass does not have rigid or impostor rendering
+ pass += 2;
}
switch (pass)
@@ -170,6 +198,14 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
case 2:
beginDeferredSkinned();
break;
+#if LL_MESH_ENABLED
+ case 3:
+ beginDeferredRiggedSimple();
+ break;
+ case 4:
+ beginDeferredRiggedBump();
+ break;
+#endif
}
}
@@ -178,11 +214,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)
LLFastTimer t(FTM_RENDER_CHARACTERS);
sSkipTransparent = FALSE;
+ is_deferred_render = false;
if (LLPipeline::sImpostorRender)
{
- endDeferredSkinned();
- return;
+ pass += 2;
}
switch (pass)
@@ -196,6 +232,14 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)
case 2:
endDeferredSkinned();
break;
+#if LL_MESH_ENABLED
+ case 3:
+ endDeferredRiggedSimple();
+ break;
+ case 4:
+ endDeferredRiggedBump();
+ break;
+#endif
}
}
@@ -206,11 +250,42 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass)
S32 LLDrawPoolAvatar::getNumPostDeferredPasses()
{
+#if LL_MESH_ENABLED
+ return 6;
+#else
return 1;
+#endif
}
void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
{
+ switch (pass)
+ {
+ case 0:
+ beginPostDeferredAlpha();
+ break;
+#if LL_MESH_ENABLED
+ case 1:
+ beginRiggedFullbright();
+ break;
+ case 2:
+ beginRiggedFullbrightShiny();
+ break;
+ case 3:
+ beginDeferredRiggedAlpha();
+ break;
+ case 4:
+ beginRiggedFullbrightAlpha();
+ break;
+ case 5:
+ beginRiggedGlow();
+ break;
+#endif
+ }
+}
+
+void LLDrawPoolAvatar::beginPostDeferredAlpha()
+{
sSkipOpaque = TRUE;
sShaderLevel = mVertexShaderLevel;
sVertexProgram = &gDeferredAvatarAlphaProgram;
@@ -219,64 +294,144 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
gPipeline.bindDeferredShader(*sVertexProgram);
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
+#if LL_MESH_ENABLED
+void LLDrawPoolAvatar::beginDeferredRiggedAlpha()
+{
+ sVertexProgram = &gDeferredSkinnedAlphaProgram;
+ gPipeline.bindDeferredShader(*sVertexProgram);
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+ gPipeline.enableLightsDynamic();
+}
+
+void LLDrawPoolAvatar::endDeferredRiggedAlpha()
+{
+ LLVertexBuffer::unbind();
+ gPipeline.unbindDeferredShader(*sVertexProgram);
+ sDiffuseChannel = 0;
+ LLVertexBuffer::sWeight4Loc = -1;
+ sVertexProgram = NULL;
+}
+#endif
+
void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)
{
+ switch (pass)
+ {
+ case 0:
+ endPostDeferredAlpha();
+ break;
+#if LL_MESH_ENABLED
+ case 1:
+ endRiggedFullbright();
+ break;
+ case 2:
+ endRiggedFullbrightShiny();
+ break;
+ case 3:
+ endDeferredRiggedAlpha();
+ break;
+ case 4:
+ endRiggedFullbrightAlpha();
+ break;
+ case 5:
+ endRiggedGlow();
+ break;
+#endif
+ }
+}
+
+void LLDrawPoolAvatar::endPostDeferredAlpha()
+{
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
sRenderingSkinned = FALSE;
sSkipOpaque = FALSE;
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
gPipeline.unbindDeferredShader(*sVertexProgram);
-
+ sDiffuseChannel = 0;
sShaderLevel = mVertexShaderLevel;
}
void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
{
- render(2); //pass 2 = skinned
+ const S32 actual_pass[] =
+ { //map post deferred pass numbers to what render() expects
+ 2, //skinned
+ 4, // rigged fullbright
+ 6, //rigged fullbright shiny
+ 7, //rigged alpha
+ 8, //rigged fullbright alpha
+ 9, //rigged glow
+ };
+
+ render(actual_pass[pass]);
}
S32 LLDrawPoolAvatar::getNumShadowPasses()
{
+#if LL_MESH_ENABLED
+ return 2;
+#else
return 1;
+#endif
}
void LLDrawPoolAvatar::beginShadowPass(S32 pass)
{
LLFastTimer t(FTM_SHADOW_AVATAR);
- sVertexProgram = &gDeferredAvatarShadowProgram;
- if (sShaderLevel > 0)
+
+ if (pass == 0)
{
- gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
- }
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
-
- glColor4f(1,1,1,1);
+ sVertexProgram = &gDeferredAvatarShadowProgram;
+ if (sShaderLevel > 0)
+ {
+ gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
+ }
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
+
+ glColor4f(1,1,1,1);
- if ((sShaderLevel > 0)) // for hardware blending
+ if ((sShaderLevel > 0)) // for hardware blending
+ {
+ sRenderingSkinned = TRUE;
+ sVertexProgram->bind();
+ enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
+ }
+ }
+ else
{
- sRenderingSkinned = TRUE;
+ sVertexProgram = &gDeferredAttachmentShadowProgram;
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
sVertexProgram->bind();
- enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
}
-
}
void LLDrawPoolAvatar::endShadowPass(S32 pass)
{
LLFastTimer t(FTM_SHADOW_AVATAR);
- if (sShaderLevel > 0)
+ if (pass == 0)
{
- sRenderingSkinned = FALSE;
+ if (sShaderLevel > 0)
+ {
+ sRenderingSkinned = FALSE;
+ sVertexProgram->unbind();
+ disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
+ }
+ }
+ else
+ {
+ LLVertexBuffer::unbind();
sVertexProgram->unbind();
- disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
+ LLVertexBuffer::sWeight4Loc = -1;
+ sVertexProgram = NULL;
}
-
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
void LLDrawPoolAvatar::renderShadow(S32 pass)
@@ -306,20 +461,65 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
return;
}
- if (sShaderLevel > 0)
+ if (pass == 0)
{
- gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
- }
-
- avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
+ if (sShaderLevel > 0)
+ {
+ gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
+ }
+ avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
+ }
+#if LL_MESH_ENABLED
+ else
+ {
+ renderRigged(avatarp, RIGGED_SIMPLE);
+ renderRigged(avatarp, RIGGED_ALPHA);
+ renderRigged(avatarp, RIGGED_FULLBRIGHT);
+ renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY);
+ renderRigged(avatarp, RIGGED_SHINY);
+ renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA);
+ }
+#endif
}
S32 LLDrawPoolAvatar::getNumPasses()
{
- return LLPipeline::sImpostorRender ? 1 : 3;
+#if LL_MESH_ENABLED
+ if (LLPipeline::sImpostorRender)
+ {
+ return 8;
+ }
+ else
+ {
+ return 10;
+ }
+#else
+ if (LLPipeline::sImpostorRender)
+ {
+ return 1;
+ }
+ else
+ {
+ return 3;
+ }
+#endif
+}
+
+
+S32 LLDrawPoolAvatar::getNumDeferredPasses()
+{
+ if (LLPipeline::sImpostorRender)
+ {
+ return 3;
+ }
+ else
+ {
+ return 5;
+ }
}
+
void LLDrawPoolAvatar::render(S32 pass)
{
LLFastTimer t(FTM_RENDER_CHARACTERS);
@@ -339,9 +539,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)
LLVertexBuffer::unbind();
if (LLPipeline::sImpostorRender)
- {
- beginSkinned();
- return;
+ { //impostor render does not have impostors or rigid rendering
+ pass += 2;
}
switch (pass)
@@ -355,6 +554,29 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)
case 2:
beginSkinned();
break;
+#if LL_MESH_ENABLED
+ case 3:
+ beginRiggedSimple();
+ break;
+ case 4:
+ beginRiggedFullbright();
+ break;
+ case 5:
+ beginRiggedShinySimple();
+ break;
+ case 6:
+ beginRiggedFullbrightShiny();
+ break;
+ case 7:
+ beginRiggedAlpha();
+ break;
+ case 8:
+ beginRiggedFullbrightAlpha();
+ break;
+ case 9:
+ beginRiggedGlow();
+ break;
+#endif
}
}
@@ -364,8 +586,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)
if (LLPipeline::sImpostorRender)
{
- endSkinned();
- return;
+ pass += 2;
}
switch (pass)
@@ -378,6 +599,30 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)
break;
case 2:
endSkinned();
+ break;
+#if LL_MESH_ENABLED
+ case 3:
+ endRiggedSimple();
+ break;
+ case 4:
+ endRiggedFullbright();
+ break;
+ case 5:
+ endRiggedShinySimple();
+ break;
+ case 6:
+ endRiggedFullbrightShiny();
+ break;
+ case 7:
+ endRiggedAlpha();
+ break;
+ case 8:
+ endRiggedFullbrightAlpha();
+ break;
+ case 9:
+ endRiggedGlow();
+ break;
+#endif
}
}
@@ -390,7 +635,7 @@ void LLDrawPoolAvatar::beginImpostor()
}
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
- diffuse_channel = 0;
+ sDiffuseChannel = 0;
}
void LLDrawPoolAvatar::endImpostor()
@@ -441,9 +686,9 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
sVertexProgram = &gDeferredImpostorProgram;
- normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
- diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
sVertexProgram->bind();
}
@@ -563,6 +808,256 @@ void LLDrawPoolAvatar::endSkinned()
gGL.getTexUnit(0)->activate();
}
+#if LL_MESH_ENABLED
+void LLDrawPoolAvatar::beginRiggedSimple()
+{
+ if (sShaderLevel > 0)
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gSkinnedObjectSimpleWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gSkinnedObjectSimpleProgram;
+ }
+ }
+ else
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gObjectSimpleWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gObjectSimpleProgram;
+ }
+ }
+
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ sDiffuseChannel = 0;
+ sVertexProgram->bind();
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+ }
+}
+
+void LLDrawPoolAvatar::endRiggedSimple()
+{
+ LLVertexBuffer::unbind();
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ sVertexProgram->unbind();
+ sVertexProgram = NULL;
+ LLVertexBuffer::sWeight4Loc = -1;
+ }
+}
+
+void LLDrawPoolAvatar::beginRiggedAlpha()
+{
+ beginRiggedSimple();
+}
+
+void LLDrawPoolAvatar::endRiggedAlpha()
+{
+ endRiggedSimple();
+}
+
+
+void LLDrawPoolAvatar::beginRiggedFullbrightAlpha()
+{
+ beginRiggedFullbright();
+}
+
+void LLDrawPoolAvatar::endRiggedFullbrightAlpha()
+{
+ endRiggedFullbright();
+}
+
+void LLDrawPoolAvatar::beginRiggedGlow()
+{
+ beginRiggedFullbright();
+}
+
+void LLDrawPoolAvatar::endRiggedGlow()
+{
+ endRiggedFullbright();
+}
+
+void LLDrawPoolAvatar::beginRiggedFullbright()
+{
+ if (sShaderLevel > 0)
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gSkinnedObjectFullbrightWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gSkinnedObjectFullbrightProgram;
+ }
+ }
+ else
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gObjectFullbrightWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gObjectFullbrightProgram;
+ }
+ }
+
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ sDiffuseChannel = 0;
+ sVertexProgram->bind();
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+ }
+}
+
+void LLDrawPoolAvatar::endRiggedFullbright()
+{
+ LLVertexBuffer::unbind();
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ sVertexProgram->unbind();
+ sVertexProgram = NULL;
+ LLVertexBuffer::sWeight4Loc = -1;
+ }
+}
+
+void LLDrawPoolAvatar::beginRiggedShinySimple()
+{
+ if (sShaderLevel > 0)
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gSkinnedObjectShinySimpleProgram;
+ }
+ }
+ else
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gObjectShinyWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gObjectShinyProgram;
+ }
+ }
+
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ sVertexProgram->bind();
+ LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+ }
+}
+
+void LLDrawPoolAvatar::endRiggedShinySimple()
+{
+ LLVertexBuffer::unbind();
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
+ sVertexProgram->unbind();
+ sVertexProgram = NULL;
+ LLVertexBuffer::sWeight4Loc = -1;
+ }
+}
+
+void LLDrawPoolAvatar::beginRiggedFullbrightShiny()
+{
+ if (sShaderLevel > 0)
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gSkinnedObjectFullbrightShinyProgram;
+ }
+ }
+ else
+ {
+ if (LLPipeline::sUnderWaterRender)
+ {
+ sVertexProgram = &gObjectFullbrightShinyWaterProgram;
+ }
+ else
+ {
+ sVertexProgram = &gObjectFullbrightShinyProgram;
+ }
+ }
+
+
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ sVertexProgram->bind();
+ LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+ }
+}
+
+void LLDrawPoolAvatar::endRiggedFullbrightShiny()
+{
+ LLVertexBuffer::unbind();
+ if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
+ {
+ LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
+ sVertexProgram->unbind();
+ sVertexProgram = NULL;
+ LLVertexBuffer::sWeight4Loc = -1;
+ }
+}
+
+
+void LLDrawPoolAvatar::beginDeferredRiggedSimple()
+{
+ sVertexProgram = &gDeferredSkinnedDiffuseProgram;
+ sDiffuseChannel = 0;
+ sVertexProgram->bind();
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+}
+
+void LLDrawPoolAvatar::endDeferredRiggedSimple()
+{
+ LLVertexBuffer::unbind();
+ sVertexProgram->unbind();
+ LLVertexBuffer::sWeight4Loc = -1;
+ sVertexProgram = NULL;
+}
+
+void LLDrawPoolAvatar::beginDeferredRiggedBump()
+{
+ sVertexProgram = &gDeferredSkinnedBumpProgram;
+ sVertexProgram->bind();
+ normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+}
+
+void LLDrawPoolAvatar::endDeferredRiggedBump()
+{
+ LLVertexBuffer::unbind();
+ sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
+ sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ sVertexProgram->unbind();
+ LLVertexBuffer::sWeight4Loc = -1;
+ normal_channel = -1;
+ sDiffuseChannel = 0;
+ sVertexProgram = NULL;
+}
+#endif
+
void LLDrawPoolAvatar::beginDeferredSkinned()
{
sShaderLevel = mVertexShaderLevel;
@@ -690,7 +1185,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
avatarp->mImpostor.bindTexture(1, specular_channel);
}
}
- avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel);
+ avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);
}
return;
}
@@ -706,6 +1201,90 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
avatarp->renderRigid();
return;
}
+
+#if LL_MESH_ENABLED
+ if (pass == 3)
+ {
+ if (is_deferred_render)
+ {
+ renderDeferredRiggedSimple(avatarp);
+ }
+ else
+ {
+ renderRiggedSimple(avatarp);
+ }
+ return;
+ }
+
+ if (pass == 4)
+ {
+ if (is_deferred_render)
+ {
+ renderDeferredRiggedBump(avatarp);
+ }
+ else
+ {
+ renderRiggedFullbright(avatarp);
+ }
+
+ return;
+ }
+
+ if (pass == 5)
+ {
+ renderRiggedShinySimple(avatarp);
+ return;
+ }
+
+ if (pass == 6)
+ {
+ renderRiggedFullbrightShiny(avatarp);
+ return;
+ }
+
+ if (pass >= 7 && pass < 9)
+ {
+ LLGLEnable blend(GL_BLEND);
+
+ gGL.setColorMask(true, true);
+ gGL.blendFunc(LLRender::BF_SOURCE_ALPHA,
+ LLRender::BF_ONE_MINUS_SOURCE_ALPHA,
+ LLRender::BF_ZERO,
+ LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
+
+
+ if (pass == 7)
+ {
+ renderRiggedAlpha(avatarp);
+ return;
+ }
+
+ if (pass == 8)
+ {
+ renderRiggedFullbrightAlpha(avatarp);
+ return;
+ }
+ }
+
+ if (pass == 9)
+ {
+ LLGLEnable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.flush();
+
+ LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.0f, -1.0f);
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ gGL.setColorMask(false, true);
+
+ renderRiggedGlow(avatarp);
+ gGL.setColorMask(true, false);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ return;
+ }
+#endif
if (sShaderLevel > 0)
{
@@ -743,13 +1322,320 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
+#if LL_MESH_ENABLED
+void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
+{
+ LLVertexBuffer* buffer = face->mVertexBuffer;
+
+ U32 data_mask = 0;
+ for (U32 i = 0; i < face->mRiggedIndex.size(); ++i)
+ {
+ if (face->mRiggedIndex[i] > -1)
+ {
+ data_mask |= rigged_data_mask[i];
+ }
+ }
+
+ if (!buffer ||
+ buffer->getTypeMask() != data_mask ||
+ buffer->getRequestedVerts() != vol_face.mNumVertices)
+ {
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+ face->setSize(vol_face.mNumVertices, vol_face.mNumIndices, true);
+
+ if (sShaderLevel > 0)
+ {
+ face->mVertexBuffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
+ }
+ else
+ {
+ face->mVertexBuffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
+ }
+
+ face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), true);
+
+ U16 offset = 0;
+
+ LLMatrix4 mat_vert = skin->mBindShapeMatrix;
+ glh::matrix4f m((F32*) mat_vert.mMatrix);
+ m = m.inverse().transpose();
+
+ F32 mat3[] =
+ { m.m[0], m.m[1], m.m[2],
+ m.m[4], m.m[5], m.m[6],
+ m.m[8], m.m[9], m.m[10] };
+
+ LLMatrix3 mat_normal(mat3);
+
+ face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
+ buffer = face->mVertexBuffer;
+ }
+
+ if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
+ { //perform software vertex skinning for this face
+ LLStrider<LLVector3> position;
+ LLStrider<LLVector3> normal;
+
+ bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
+ buffer->getVertexStrider(position);
+
+ if (has_normal)
+ {
+ buffer->getNormalStrider(normal);
+ }
+
+ LLVector4a* pos = (LLVector4a*) position.get();
+
+ LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;
+
+ //build matrix palette
+ LLMatrix4a mp[64];
+ LLMatrix4* mat = (LLMatrix4*) mp;
+
+ for (U32 j = 0; j < skin->mJointNames.size(); ++j)
+ {
+ LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
+ if (joint)
+ {
+ mat[j] = skin->mInvBindMatrix[j];
+ mat[j] *= joint->getWorldMatrix();
+ }
+ }
+
+ LLVector4a* weight = vol_face.mWeights;
+
+ LLMatrix4a bind_shape_matrix;
+ bind_shape_matrix.loadu(skin->mBindShapeMatrix);
+
+ for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
+ {
+ LLMatrix4a final_mat;
+ final_mat.clear();
+
+ S32 idx[4];
+
+ LLVector4 wght;
+
+ F32 scale = 0.f;
+ for (U32 k = 0; k < 4; k++)
+ {
+ F32 w = weight[j][k];
+
+ idx[k] = (S32) floorf(w);
+ wght[k] = w - floorf(w);
+ scale += wght[k];
+ }
+
+ wght *= 1.f/scale;
+
+ for (U32 k = 0; k < 4; k++)
+ {
+ F32 w = wght[k];
+
+ LLMatrix4a src;
+ src.setMul(mp[idx[k]], w);
+
+ final_mat.add(src);
+ }
+
+
+ LLVector4a& v = vol_face.mPositions[j];
+ LLVector4a t;
+ LLVector4a dst;
+ bind_shape_matrix.affineTransform(v, t);
+ final_mat.affineTransform(t, dst);
+ pos[j] = dst;
+
+ if (norm)
+ {
+ LLVector4a& n = vol_face.mNormals[j];
+ bind_shape_matrix.rotate(n, t);
+ final_mat.rotate(t, dst);
+ norm[j] = dst;
+ }
+ }
+ }
+}
+
+void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
+{
+ if (avatar->isSelf() && !gAgent.needsRenderAvatar())
+ {
+ return;
+ }
+
+ stop_glerror();
+
+ for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
+ {
+ LLFace* face = mRiggedFace[type][i];
+ LLDrawable* drawable = face->getDrawable();
+ if (!drawable)
+ {
+ continue;
+ }
+
+ LLVOVolume* vobj = drawable->getVOVolume();
+
+ if (!vobj)
+ {
+ continue;
+ }
+
+ LLVolume* volume = vobj->getVolume();
+ S32 te = face->getTEOffset();
+
+ if (!volume || volume->getNumVolumeFaces() <= te)
+ {
+ continue;
+ }
+
+ LLUUID mesh_id = volume->getParams().getSculptID();
+ if (mesh_id.isNull())
+ {
+ continue;
+ }
+
+ const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id);
+ if (!skin)
+ {
+ continue;
+ }
+
+ stop_glerror();
+
+ const LLVolumeFace& vol_face = volume->getVolumeFace(te);
+ updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face);
+
+ stop_glerror();
+
+ U32 data_mask = rigged_data_mask[type];
+
+ LLVertexBuffer* buff = face->mVertexBuffer;
+
+ if (buff)
+ {
+ if (sShaderLevel > 0)
+ { //upload matrix palette to shader
+ LLMatrix4 mat[64];
+
+ for (U32 i = 0; i < skin->mJointNames.size(); ++i)
+ {
+ LLJoint* joint = avatar->getJoint(skin->mJointNames[i]);
+ if (joint)
+ {
+ mat[i] = skin->mInvBindMatrix[i];
+ mat[i] *= joint->getWorldMatrix();
+ }
+ }
+
+ stop_glerror();
+
+ LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette",
+ skin->mJointNames.size(),
+ FALSE,
+ (GLfloat*) mat[0].mMatrix);
+ LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]",
+ skin->mJointNames.size(),
+ FALSE,
+ (GLfloat*) mat[0].mMatrix);
+
+ stop_glerror();
+ }
+ else
+ {
+ data_mask &= ~LLVertexBuffer::MAP_WEIGHT4;
+ }
+
+ buff->setBuffer(data_mask);
+
+ U16 start = face->getGeomStart();
+ U16 end = start + face->getGeomCount()-1;
+ S32 offset = face->getIndicesStart();
+ U32 count = face->getIndicesCount();
+
+ if (glow)
+ {
+ glColor4f(0,0,0,face->getTextureEntry()->getGlow());
+ }
+
+ gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture());
+ if (normal_channel > -1)
+ {
+ LLDrawPoolBump::bindBumpMap(face, normal_channel);
+ }
+
+ if (face->mTextureMatrix)
+ {
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix);
+ buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+ else
+ {
+ buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
+ }
+ }
+ }
+}
+
+void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_DEFERRED_SIMPLE);
+}
+
+void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_DEFERRED_BUMP);
+}
+
+void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_SIMPLE);
+}
+
+void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_FULLBRIGHT);
+}
+
+
+void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_SHINY);
+}
+
+void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY);
+}
+
+void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_ALPHA);
+}
+
+void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA);
+}
+
+void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar)
+{
+ renderRigged(avatar, RIGGED_GLOW, true);
+}
+#endif
+
+
+
//-----------------------------------------------------------------------------
// renderForSelect()
//-----------------------------------------------------------------------------
void LLDrawPoolAvatar::renderForSelect()
{
-
-
if (mDrawFace.empty())
{
return;
@@ -843,6 +1729,63 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
return LLColor3(0.f, 1.f, 0.f);
}
+#if LL_MESH_ENABLED
+void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
+{
+ if (facep->mRiggedIndex.empty())
+ {
+ facep->mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES);
+ for (U32 i = 0; i < facep->mRiggedIndex.size(); ++i)
+ {
+ facep->mRiggedIndex[i] = -1;
+ }
+ }
+
+ if (type >= NUM_RIGGED_PASSES)
+ {
+ llerrs << "Invalid rigged face type." << llendl;
+ }
+
+ if (facep->mRiggedIndex[type] != -1)
+ {
+ llerrs << "Tried to add a rigged face that's referenced elsewhere." << llendl;
+ }
+
+
+ facep->mRiggedIndex[type] = mRiggedFace[type].size();
+ facep->mDrawPoolp = this;
+ mRiggedFace[type].push_back(facep);
+}
+
+void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)
+{
+
+ facep->mDrawPoolp = NULL;
+
+ for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i)
+ {
+ S32 index = facep->mRiggedIndex[i];
+
+ if (index > -1)
+ {
+ if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep)
+ {
+ facep->mRiggedIndex[i] = -1;
+ mRiggedFace[i].erase(mRiggedFace[i].begin()+index);
+ for (U32 j = index; j < mRiggedFace[i].size(); ++j)
+ { //bump indexes down for faces referenced after erased face
+ mRiggedFace[i][j]->mRiggedIndex[i] = j;
+ }
+ }
+ else
+ {
+ llerrs << "Face reference data corrupt for rigged type " << i << llendl;
+ }
+ }
+ }
+}
+#endif
+
LLVertexBufferAvatar::LLVertexBufferAvatar()
: LLVertexBuffer(sDataMask,
GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets
@@ -855,22 +1798,25 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const
{
if (sRenderingSkinned)
{
- U8* base = useVBOs() ? NULL : mMappedData;
+ U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
- glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0));
- glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL]));
- glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0]));
+ glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], (void*)(base + 0));
+ glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL]));
+ glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0]));
- set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT]));
+ set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT],
+ LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_WEIGHT], (F32*)(base + mOffsets[TYPE_WEIGHT]));
if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP)
{
- set_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL]));
+ set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL],
+ LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_BINORMAL], (LLVector3*)(base + mOffsets[TYPE_BINORMAL]));
}
if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)
{
- set_vertex_clothing_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
+ set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING],
+ LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_CLOTHWEIGHT], (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
}
}
else