void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { LLFastTimer t(FTM_RENDER_AVATARS); if (pass == -1) { for (S32 i = 1; i < getNumPasses(); i++) { //skip foot shadows prerender(); beginRenderPass(i); renderAvatars(single_avatar, i); endRenderPass(i); } return; } if (mDrawFace.empty() && !single_avatar) { return; } LLVOAvatar *avatarp; if (single_avatar) { avatarp = single_avatar; } else { const LLFace *facep = mDrawFace[0]; if (!facep->getDrawable()) { return; } avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); } if (avatarp->isDead() || avatarp->mDrawable.isNull()) { return; } if (!single_avatar && !avatarp->isFullyLoaded() ) { if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) { // debug code to draw a sphere in place of avatar gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); gGL.setColorMask(true, true); LLVector3 pos = avatarp->getPositionAgent(); gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f); gGL.pushMatrix(); gGL.translatef((F32)(pos.mV[VX]), (F32)(pos.mV[VY]), (F32)(pos.mV[VZ])); gGL.scalef(0.15f, 0.15f, 0.3f); gSphere.renderGGL(); gGL.popMatrix(); gGL.setColorMask(true, false); } // don't render please return; } BOOL impostor = avatarp->isImpostor() && !single_avatar; if (impostor && pass != 0) { //don't draw anything but the impostor for impostored avatars return; } if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender) { //don't draw foot shadows under water return; } if (pass == 0) { if (!LLPipeline::sReflectionRender) { LLVOAvatar::sNumVisibleAvatars++; } if (impostor) { if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete()) { if (normal_channel > -1) { avatarp->mImpostor.bindTexture(2, normal_channel); } if (specular_channel > -1) { avatarp->mImpostor.bindTexture(1, specular_channel); } } avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel); } //else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) //{ // avatarp->renderFootShadows(); //} return; } llassert(LLPipeline::sImpostorRender || !avatarp->isVisuallyMuted()); /*if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview, 3=morph view { gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f)); }*/ if (pass == 1) { // render rigid meshes (eyeballs) first avatarp->renderRigid(); return; } if (pass == 3) { if (is_deferred_render) { renderDeferredRiggedSimple(avatarp); } else { renderRiggedSimple(avatarp); if (LLPipeline::sRenderDeferred) { //render "simple" materials renderRigged(avatarp, RIGGED_MATERIAL); renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); renderRigged(avatarp, RIGGED_NORMMAP); renderRigged(avatarp, RIGGED_NORMMAP_MASK); renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); renderRigged(avatarp, RIGGED_SPECMAP); renderRigged(avatarp, RIGGED_SPECMAP_MASK); renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); renderRigged(avatarp, RIGGED_NORMSPEC); renderRigged(avatarp, RIGGED_NORMSPEC_MASK); renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); } } return; } if (pass == 4) { if (is_deferred_render) { renderDeferredRiggedBump(avatarp); } else { renderRiggedFullbright(avatarp); } return; } if (is_deferred_render && pass >= 5 && pass <= 21) { S32 p = pass-5; if (p != 1 && p != 5 && p != 9 && p != 13) { renderDeferredRiggedMaterial(avatarp, p); } return; } if (pass == 5) { renderRiggedShinySimple(avatarp); return; } if (pass == 6) { renderRiggedFullbrightShiny(avatarp); return; } if (pass >= 7 && pass < 13) { if (pass == 7) { renderRiggedAlpha(avatarp); if (LLPipeline::sRenderDeferred && !is_post_deferred_render) { //render transparent materials under water 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); renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); renderRigged(avatarp, RIGGED_SPECMAP_BLEND); renderRigged(avatarp, RIGGED_NORMMAP_BLEND); renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.setColorMask(true, false); } return; } if (pass == 8) { renderRiggedFullbrightAlpha(avatarp); return; } if (LLPipeline::sRenderDeferred && is_post_deferred_render) { S32 p = 0; switch (pass) { case 9: p = 1; break; case 10: p = 5; break; case 11: p = 9; break; case 12: p = 13; break; } { LLGLEnable blend(GL_BLEND); renderDeferredRiggedMaterial(avatarp, p); } return; } else if (pass == 9) { renderRiggedGlow(avatarp); return; } } if (pass == 13) { renderRiggedGlow(avatarp); return; } if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) { LLMatrix4 rot_mat; LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); LLMatrix4 cfr(OGL_TO_CFR_ROTATION.getF32ptr()); rot_mat *= cfr; LLVector4 wind; wind.setVec(avatarp->mWindVec); wind.mV[VW] = 0; wind = wind * rot_mat; wind.mV[VW] = avatarp->mWindVec.mV[VW]; sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); F32 phase = -1.f * (avatarp->mRipplePhase); F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); LLVector4 sin_params(freq, freq, freq, phase); sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); gravity = gravity * rot_mat; sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV); } if( !single_avatar || (avatarp == single_avatar) ) { avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } }
void LLViewerPartSim::updateSimulation() { LLMemType mt(LLMemType::MTYPE_PARTICLES); static LLFrameTimer update_timer; const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) { return; } LLFastTimer ftm(FTM_SIMULATE_PARTICLES); // Start at a random particle system so the same // particle system doesn't always get first pick at the // particles. Theoretically we'd want to do this in distance // order or something, but sorting particle sources will be a big // pain. S32 i; S32 count = (S32) mViewerPartSources.size(); S32 start = (S32)ll_frand((F32)count); S32 dir = 1; S32 deldir = 0; if (ll_frand() > 0.5f) { dir = -1; deldir = -1; } S32 num_updates = 0; for (i = start; num_updates < count;) { if (i >= count) { i = 0; } if (i < 0) { i = count - 1; } if (!mViewerPartSources[i]->isDead()) { BOOL upd = TRUE; //if (!LLPipeline::sRenderAttachedParticles) { LLViewerObject* vobj = mViewerPartSources[i]->mSourceObjectp; if (vobj && (vobj->getPCode() == LL_PCODE_VOLUME)) { LLVOVolume* vvo = (LLVOVolume *)vobj; if (vvo && vvo->isAttachment()) { if (!LLPipeline::sRenderAttachedParticles) upd = FALSE; else { LLVOAvatar *avatar = vvo->getAvatar(); if(avatar && avatar->isVisuallyMuted()) upd = FALSE; } } } } if (upd) { mViewerPartSources[i]->update(dt); } } if (mViewerPartSources[i]->isDead()) { mViewerPartSources.erase(mViewerPartSources.begin() + i); count--; i+=deldir; } else { i += dir; } num_updates++; } count = (S32) mViewerPartGroups.size(); for (i = 0; i < count; i++) { LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; S32 visirate = 1; if (vobj) { LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) { visirate = 8; } } if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%visirate == 0) { if (vobj) { gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE); } mViewerPartGroups[i]->updateParticles(dt * visirate); mViewerPartGroups[i]->mSkippedTime=0.0f; if (!mViewerPartGroups[i]->getCount()) { delete mViewerPartGroups[i]; mViewerPartGroups.erase(mViewerPartGroups.begin() + i); i--; count--; } } else { mViewerPartGroups[i]->mSkippedTime+=dt; } } if (LLDrawable::getCurrentFrame()%16==0) { if (sParticleCount > sMaxParticleCount * 0.875f && sParticleAdaptiveRate < 2.0f) { sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT; } else { if (sParticleCount < sMaxParticleCount * 0.5f && sParticleAdaptiveRate > 0.03125f) { sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT_RECIP; } } } updatePartBurstRate() ; //llinfos << "Particles: " << sParticleCount << " Adaptive Rate: " << sParticleAdaptiveRate << llendl; }