diff options
Diffstat (limited to 'indra/newview/lldrawpoolavatar.cpp')
-rw-r--r-- | indra/newview/lldrawpoolavatar.cpp | 1084 |
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 |