diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 26d5c42a66..fabb692f8d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -23411,6 +23411,17 @@ Change of this parameter will affect the layout of buttons in notification toast Value 13 + FSSimpleAvatarShadows + + Comment + How to render deferred avatar shadows. 0=none, 1=simplified (no rigged mesh shadows), 2=optimized (slower but still faster than legacy when several avatars are around), 3=legacy (like the SL viewer, slow with complex rigged attachments). + Persist + 1 + Type + U32 + Value + 3 + diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d26efefb2f..65061a655d 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -462,6 +462,14 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) { LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); + // Chalice Yao's simple avatar shadows via Marine Kelley + static LLCachedControl fsSimpleAvatarShadows(gSavedSettings, "FSSimpleAvatarShadows", 3); + if (fsSimpleAvatarShadows == 0) + { + return; + } + // + if (mDrawFace.empty()) { return; @@ -489,6 +497,18 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) { avatarp->renderSkinned(); } + // Chalice Yao's simple avatar shadows via Marine Kelley + else if (fsSimpleAvatarShadows == 1) + { + // Don't render the shadow of anything that is rigged. Instead, force the shadow of the avatar shape to render instead. + // See LLVOAvatar::isTextureVisible() and LLVOAvatarSelf::isTextureVisible() + return; + } + else if (fsSimpleAvatarShadows == 2) + { + renderRiggedShadows(avatarp); + } + // else { for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) @@ -2018,6 +2038,169 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) } } +// Chalice Yao's simple avatar shadows via Marine Kelley +void LLDrawPoolAvatar::renderRiggedShadows(LLVOAvatar* avatar) +{ + if (avatar->isSelf() && !gAgent.needsRenderAvatar()) + { + return; + } + + stop_glerror(); + + U32 rigTypes[18] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,21 }; + for (U32 j = 0; j < 18; ++j) + for (U32 i = 0; i < mRiggedFace[rigTypes[j]].size(); ++i) + { + LLFace* face = mRiggedFace[rigTypes[j]][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 || !volume->isMeshAssetLoaded()) + { + continue; + } + + LLUUID mesh_id = volume->getParams().getSculptID(); + if (mesh_id.isNull()) + { + continue; + } + + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); + if (!skin) + { + continue; + } + + U32 data_mask = LLFace::getRiggedDataMask(24); + + LLVertexBuffer* buff = face->getVertexBuffer(); + + if (buff) + { + if (sShaderLevel > 0) + { //upload matrix palette to shader + LLMatrix4 mat[JOINT_COUNT]; + + U32 count = llmin((U32)skin->mJointNames.size(), (U32)JOINT_COUNT); + + for (U32 i = 0; i < count; ++i) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); + if (joint) + { + mat[i] = skin->mInvBindMatrix[i]; + mat[i] *= joint->getWorldMatrix(); + } + } + + stop_glerror(); + + F32 mp[JOINT_COUNT * 9]; + + F32 transp[JOINT_COUNT * 3]; + + for (U32 i = 0; i < count; ++i) + { + F32* m = (F32*)mat[i].mMatrix; + + U32 idx = i * 9; + + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + + mp[idx + 3] = m[4]; + mp[idx + 4] = m[5]; + mp[idx + 5] = m[6]; + + mp[idx + 6] = m[8]; + mp[idx + 7] = m[9]; + mp[idx + 8] = m[10]; + + idx = i * 3; + + transp[idx + 0] = m[12]; + transp[idx + 1] = m[13]; + transp[idx + 2] = m[14]; + } + + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)mp); + + LLDrawPoolAvatar::sVertexProgram->uniform3fv(LLShaderMgr::AVATAR_TRANSLATION, count, transp); + + + stop_glerror(); + } + else + { + data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; + } + + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount() - 1; + S32 offset = face->getIndicesStart(); + U32 count = face->getIndicesCount(); + + if ((rigTypes[j] < 4) || (rigTypes[j] == 5) || (rigTypes[j] == 6) || (rigTypes[j] == 9) || (rigTypes[j] == 10) || (rigTypes[j] == 13) || (rigTypes[j] == 14) || (rigTypes[j] == 21)) + { + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); + sVertexProgram->setMinimumAlpha(0.f); + + if ((rigTypes[j] == 2) || (rigTypes[j] == 6) || (rigTypes[j] == 10) || (rigTypes[j] == 14)) + { + const LLTextureEntry* te = face->getTextureEntry(); + LLMaterial* mat = te->getMaterialParams().get(); + + if (mat) + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff() / 255.f); + } + + if (face->mTextureMatrix && vobj->mTexAnimMode) + { + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((F32*)face->mTextureMatrix->mMatrix); + buff->setBuffer(data_mask); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + else + { + buff->setBuffer(data_mask); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + } + else + { + buff->setBuffer(data_mask); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); + } + } +} +// + void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) { renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b9d2204052..2002fe3451 100755 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -142,6 +142,9 @@ public: void updateRiggedVertexBuffers(LLVOAvatar* avatar); void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); + // Chalice Yao's simple avatar shadows via Marine Kelley + void renderRiggedShadows(LLVOAvatar* avatar); + // void renderRiggedSimple(LLVOAvatar* avatar); void renderRiggedAlpha(LLVOAvatar* avatar); void renderRiggedFullbrightAlpha(LLVOAvatar* avatar); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 19ae19cc20..720d04015f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -9268,6 +9268,17 @@ BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, } else { + // Chalice Yao's simple avatar shadows via Marine Kelley + if (LLPipeline::sShadowRender) + { + static LLCachedControl fsSimpleAvatarShadows(gSavedSettings, "FSSimpleAvatarShadows", 3); + if (fsSimpleAvatarShadows == 1) + { + return TRUE; + } + } + // + // baked textures can use TE images directly return ((isTextureDefined(type) || isSelf()) && (getTEImage(type)->getID() != IMG_INVISIBLE diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 6edc60c698..b4abdcbc34 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1918,6 +1918,17 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex t return LLVOAvatar::isTextureVisible(type, (U32)0); } + // Chalice Yao's simple avatar shadows via Marine Kelley + if (LLPipeline::sShadowRender) + { + static LLCachedControl fsSimpleAvatarShadows(gSavedSettings, "FSSimpleAvatarShadows", 3); + if (fsSimpleAvatarShadows == 1) + { + return TRUE; + } + } + // + LLUUID tex_id = getLocalTextureID(type,index); return (tex_id != IMG_INVISIBLE) || (LLDrawPoolAlpha::sShowDebugAlpha);