12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748 |
- /**
- * @file llviewerdisplay.cpp
- * @brief LLViewerDisplay class implementation
- *
- * $LicenseInfo:firstyear=2004&license=viewergpl$
- *
- * Copyright (c) 2004-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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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 "llviewerdisplay.h"
- #include "llapp.h"
- #include "llcubemap.h"
- #include "lldir.h"
- #include "llfasttimer.h"
- #include "llimagebmp.h"
- #include "llimagedecodethread.h"
- #include "llimagegl.h"
- #include "llrender.h"
- #include "llagent.h"
- #include "llappviewer.h"
- #include "lldynamictexture.h"
- #include "lldrawpoolalpha.h"
- #include "lldrawpoolbump.h"
- #include "lldrawpoolwater.h"
- #include "llenvironment.h"
- #include "llfeaturemanager.h"
- #include "llfloatertools.h"
- #include "llgltfmateriallist.h"
- #include "llgridmanager.h" // For gIsInProductionGrid
- #include "llhudmanager.h"
- #include "llpipeline.h"
- //MK
- #include "mkrlinterface.h"
- //mk
- #include "llselectmgr.h"
- #include "llsky.h"
- #include "llspatialpartition.h"
- #include "llstartup.h"
- #include "llstatusbar.h"
- #include "lltooldraganddrop.h"
- #include "lltoolfocus.h"
- #include "lltoolmgr.h"
- #include "lltoolpie.h"
- #include "lltracker.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewerobjectlist.h"
- #include "llviewerparcelmgr.h"
- #include "llviewerregion.h"
- #include "llviewershadermgr.h"
- #include "llviewertexturelist.h"
- #include "llviewerwindow.h"
- #include "llvoavatarself.h"
- #include "llvograss.h"
- #include "llworld.h"
- extern LLPointer<LLViewerTexture> gStartTexture;
- LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
- // This is how long the sim will try to teleport you before giving up.
- constexpr F32 TELEPORT_EXPIRY = 15.f;
- // Additional time (in seconds) to wait per attachment
- constexpr F32 TELEPORT_EXPIRY_PER_ATTACHMENT = 3.f;
- // Constants used to toggle renderer back on after teleport
- // Time to preload the world before raising the curtain after we've actually
- // already arrived.
- constexpr F32 TELEPORT_ARRIVAL_DELAY = 2.f;
- // Delay to prevent teleports after starting an in-sim teleport.
- constexpr F32 TELEPORT_LOCAL_DELAY = 1.f;
- // Wait this long while reloading textures before we raise the curtain
- constexpr F32 RESTORE_GL_TIME = 5.f;
- // Globals
- LLFrameTimer gTeleportDisplayTimer;
- LLFrameTimer gTeleportArrivalTimer;
- bool gTeleportDisplay = false;
- bool gUpdateDrawDistance = false;
- F32 gSavedDrawDistance = 0.f;
- bool gForceRenderLandFence = false;
- bool gDisplaySwapBuffers = false;
- bool gDepthDirty = false;
- bool gResizeScreenTexture = false;
- bool gResizeShadowTexture = false;
- bool gSnapshot = false;
- bool gCubeSnapshot = false;
- bool gShaderProfileFrame = false;
- bool gScreenIsDirty = false;
- U32 gRecentFrameCount = 0; // Number of 'recent' frames
- U32 gLastFPSAverage = 0;
- LLFrameTimer gRecentFPSTime;
- LLFrameTimer gRecentMemoryTime;
- // Rendering stuff
- void render_hud_attachments();
- void render_ui_3d();
- void render_ui_2d();
- void render_disconnected_background();
- void display_startup()
- {
- if (!gViewerWindowp || !gViewerWindowp->getActive() ||
- !gWindowp->getVisible() || gWindowp->getMinimized())
- {
- return;
- }
- gPipeline.updateGL();
- if (LLViewerFetchedTexture::sWhiteImagep.notNull())
- {
- LLTexUnit::sWhiteTexture =
- LLViewerFetchedTexture::sWhiteImagep->getTexName();
- }
- LLGLSDefault gls_default;
- // Required for HTML update in login screen
- static S32 frame_count = 0;
- LL_GL_CHECK_STATES;
- if (frame_count++ > 1) // Make sure we have rendered a frame first
- {
- LLViewerDynamicTexture::updateAllInstances();
- }
- LL_GL_CHECK_STATES;
- #if 0 // Only enable this should the EE renderer be gutted out. HB
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
- #else
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- #endif
- LLGLSUIDefault gls_ui;
- gPipeline.disableLights();
- gViewerWindowp->setup2DRender();
- gViewerWindowp->draw();
- gGL.flush();
- LLVertexBuffer::unbind();
- LL_GL_CHECK_STATES;
- gWindowp->swapBuffers();
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- void display_update_camera()
- {
- F32 farclip;
- if (gCubeSnapshot)
- {
- static LLCachedControl<F32> dist(gSavedSettings,
- "RenderReflectionProbeDrawDistance");
- farclip = llclamp(F32(dist), 32.f, 1024.f);
- }
- else
- {
- farclip = gAgent.mDrawDistance;
- }
- gViewerCamera.setFar(farclip);
- gViewerWindowp->setup3DRender();
- if (!gCubeSnapshot)
- {
- // Update land visibility
- gWorld.setLandFarClip(farclip);
- }
- }
- // Write some stats to llinfos
- void display_stats()
- {
- static LLCachedControl<S32> background_yield_time(gSavedSettings,
- "BackgroundYieldTime");
- if (!gWindowp->getVisible() ||
- (background_yield_time > 0 && !gFocusMgr.getAppHasFocus()))
- {
- // Do not keep FPS statistics while yielding cooperatively or not
- // visible.
- gRecentFrameCount = 0;
- gRecentFPSTime.reset();
- }
- static LLCachedControl<F32> fps_log_freq(gSavedSettings,
- "FPSLogFrequency");
- if (fps_log_freq > 0.f)
- {
- F32 ellapsed = gRecentFPSTime.getElapsedTimeF32();
- if (ellapsed >= fps_log_freq)
- {
- F32 fps = gRecentFrameCount / ellapsed;
- llinfos << llformat("FPS: %.02f", fps) << llendl;
- gLastFPSAverage = (U32)fps;
- gRecentFrameCount = 0;
- gRecentFPSTime.reset();
- }
- else if (ellapsed >= 10.f)
- {
- gLastFPSAverage = (U32)gRecentFrameCount / ellapsed;
- }
- }
- static LLCachedControl<F32> mem_log_freq(gSavedSettings,
- "MemoryLogFrequency");
- if (mem_log_freq > 0.f &&
- gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
- {
- gMemoryAllocated = LLMemory::getCurrentRSS();
- U32 memory = (U32)(gMemoryAllocated / 1048576UL);
- llinfos << llformat("MEMORY: %d MB", memory) << llendl;
- gRecentMemoryTime.reset();
- }
- }
- static void update_tp_display(bool minimized)
- {
- S32 attach_count = 0;
- if (isAgentAvatarValid())
- {
- attach_count = gAgentAvatarp->getNumAttachments();
- }
- F32 teleport_save_time = TELEPORT_EXPIRY +
- TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
- F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
- F32 teleport_percent = teleport_elapsed * 100.f / teleport_save_time;
- LLAgent::ETeleportState tp_state = gAgent.getTeleportState();
- if (teleport_percent > 100.f && tp_state != LLAgent::TELEPORT_START &&
- tp_state != LLAgent::TELEPORT_QUEUED)
- {
- // Give up. Do not keep the UI locked forever.
- LL_DEBUGS("Teleport") << "TP timeout ?... Resetting to TELEPORT_NONE"
- << LL_ENDL;
- gAgent.setTeleportState(LLAgent::TELEPORT_NONE);
- gAgent.setTeleportMessage("");
- }
- if (minimized)
- {
- gViewerWindowp->setShowProgress(false);
- }
- static LLCachedControl<bool> hide_tp_progress(gSavedSettings,
- "HideTeleportProgress");
- bool show_tp_progress = !hide_tp_progress && !minimized;
- const std::string& message = gAgent.getTeleportMessage();
- switch (gAgent.getTeleportState())
- {
- case LLAgent::TELEPORT_NONE:
- // No teleport in progress
- gViewerWindowp->setShowProgress(false);
- gTeleportDisplay = false;
- gTeleportArrivalTimer.reset();
- break;
- case LLAgent::TELEPORT_START:
- // Transition to REQUESTED. Viewer has sent some kind of
- // TeleportRequest to the source simulator.
- gTeleportDisplayTimer.reset();
- if (show_tp_progress)
- {
- gViewerWindowp->setShowProgress(true);
- gViewerWindowp->setProgressPercent(0);
- gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["requesting"]);
- }
- // Release geometry from old location
- gPipeline.resetVertexBuffers();
- LLSpatialPartition::sTeleportRequested = true;
- gAgent.setTeleportState(LLAgent::TELEPORT_REQUESTED);
- break;
- case LLAgent::TELEPORT_REQUESTED:
- // Waiting for source simulator to respond
- if (show_tp_progress)
- {
- gViewerWindowp->setProgressPercent(llmin(teleport_percent,
- 37.5f));
- gViewerWindowp->setProgressString(message);
- }
- break;
- case LLAgent::TELEPORT_MOVING:
- // Viewer has received destination location from source simulator
- if (show_tp_progress)
- {
- gViewerWindowp->setProgressPercent(llmin(teleport_percent,
- 75.f));
- gViewerWindowp->setProgressString(message);
- }
- break;
- case LLAgent::TELEPORT_START_ARRIVAL:
- // Transition to ARRIVING. Viewer has received avatar update, etc,
- // from destination simulator
- gTeleportArrivalTimer.reset();
- if (show_tp_progress)
- {
- gViewerWindowp->setProgressCancelButtonVisible(false);
- gViewerWindowp->setProgressPercent(75.f);
- gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["arriving"]);
- }
- gAgent.setTeleportState(LLAgent::TELEPORT_ARRIVING);
- if (gSavedSettings.getBool("DisablePrecacheDelayAfterTP"))
- {
- LL_DEBUGS("Teleport") << "No pre-caching, switching to TELEPORT_NONE"
- << LL_ENDL;
- gAgent.setTeleportState(LLAgent::TELEPORT_NONE);
- }
- break;
- case LLAgent::TELEPORT_ARRIVING:
- {
- // Make the user wait while content "pre-caches"
- F32 percent = gTeleportArrivalTimer.getElapsedTimeF32() /
- TELEPORT_ARRIVAL_DELAY;
- if (!show_tp_progress || percent > 1.f)
- {
- percent = 1.f;
- LL_DEBUGS("Teleport") << "Arrived. Switching to TELEPORT_NONE"
- << LL_ENDL;
- gAgent.setTeleportState(LLAgent::TELEPORT_NONE);
- }
- if (show_tp_progress)
- {
- gViewerWindowp->setProgressCancelButtonVisible(false);
- gViewerWindowp->setProgressPercent(percent * 25.f + 75.f);
- gViewerWindowp->setProgressString(message);
- }
- break;
- }
- case LLAgent::TELEPORT_LOCAL:
- // Short delay when teleporting in the same sim (progress screen
- // active but not shown; did not fall-through from TELEPORT_START)
- if (gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY)
- {
- LL_DEBUGS("Teleport") << "Local TP done, switching to TELEPORT_NONE"
- << LL_ENDL;
- gAgent.setTeleportState(LLAgent::TELEPORT_NONE);
- }
- break;
- case LLAgent::TELEPORT_QUEUED:
- gTeleportDisplayTimer.reset();
- if (show_tp_progress)
- {
- gViewerWindowp->setShowProgress(true);
- gViewerWindowp->setProgressPercent(0);
- gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["requesting"]);
- }
- gAgent.fireQueuedTeleport();
- default:
- break;
- }
- }
- // Paint the display
- void display(bool rebuild, F32 zoom_factor, S32 subfield, bool for_snapshot)
- {
- LL_FAST_TIMER(FTM_RENDER);
- if (!gViewerWindowp) return;
- static LLCachedControl<bool> use_pbr(gSavedSettings, "RenderUsePBR");
- if (gUsePBRShaders != use_pbr)
- {
- gPipeline.toggleRenderer();
- }
- stop_glerror();
- if (gResizeScreenTexture)
- {
- // Skip render on frames where window has been resized
- gGL.flush();
- glClear(GL_COLOR_BUFFER_BIT);
- gWindowp->swapBuffers();
- gPipeline.resizeScreenTexture();
- return;
- }
- if (gResizeShadowTexture)
- {
- gPipeline.resizeShadowTexture();
- }
- bool report_materials_stats = false;
- // Reset materials usage stats for this scene.
- if (!for_snapshot)
- {
- LLPipeline::sUsingALM = LLPipeline::sUsingPBR =
- LLPipeline::sLacksLegacyFallback = false;
- report_materials_stats = true;
- }
- if (LLPipeline::sRenderDeferred)
- {
- // *HACK: to make sky show up in deferred snapshots
- for_snapshot = false;
- }
- if (LLPipeline::sRenderFrameTest)
- {
- LLWorld::sendAgentPause();
- }
- gSnapshot = for_snapshot;
- LLGLSDefault gls_default;
- LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
- LLVertexBuffer::unbind();
- LL_GL_CHECK_STATES;
- gPipeline.disableLights();
- // Reset vertex buffers if needed
- gPipeline.doResetVertexBuffers();
- stop_glerror();
- // Do not draw if the window is hidden or minimized. In fact, we must
- // explicitly check the minimized state before drawing. Attempting to draw
- // into a minimized window causes a GL error. JC
- if (!gViewerWindowp->getActive() || !gWindowp->getVisible() ||
- gWindowp->getMinimized())
- {
- // Clean up memory the pools may have allocated
- if (rebuild)
- {
- gPipeline.rebuildPools();
- }
- // Avoid accumulating HUD objects while minimized. HB
- LLHUDObject::removeExpired();
- gViewerWindowp->returnEmptyPicks();
- // We still need to update the teleport progress (to get changes done
- // in TP states, else the sim does not get the messages signaling the
- // agent's arrival). Of course, we do not show/update the TP screen.
- // This fixes BUG-230616. HB
- if (gTeleportDisplay)
- {
- update_tp_display(true);
- }
- return;
- }
- gViewerWindowp->checkSettings();
- {
- LL_FAST_TIMER(FTM_PICK);
- gViewerWindowp->performPick();
- }
- LL_GL_CHECK_STATES;
- //////////////////////////////////////////////////////////
- // Logic for forcing window updates if we are in drone mode.
- // Bail out if we are in the startup state and do not want to try to render
- // the world.
- if (!LLStartUp::isLoggedIn())
- {
- display_startup();
- gScreenIsDirty = false;
- return;
- }
- if (gShaderProfileFrame)
- {
- LLGLSLShader::initProfile();
- }
- #if 0
- LLGLState::verify(false);
- #endif
- /////////////////////////////////////////////////
- // Update GL Texture statistics (used for discard logic)
- stop_glerror();
- LLImageGL::updateStats(gFrameTimeSeconds);
- static LLCachedControl<S32> render_name(gSavedSettings, "RenderName");
- static LLCachedControl<bool> hide_all_titles(gSavedSettings,
- "RenderHideGroupTitleAll");
- LLVOAvatar::sRenderName = render_name;
- LLVOAvatar::sRenderGroupTitles = !hide_all_titles;
- ++gRecentFrameCount;
- LLImageGL::freeDeletedTextures();
- gGL.cleanupVertexBufferCache(++gFrameCount);
- LLImageGL::updateStats(gFrameTimeSeconds);
- //////////////////////////////////////////////////////////
- // Display start screen if we are teleporting, and skip render
- if (gTeleportDisplay)
- {
- update_tp_display(false);
- }
- else if (gAppViewerp->logoutRequestSent())
- {
- F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f /
- gLogoutMaxTime;
- if (percent_done > 100.f)
- {
- percent_done = 100.f;
- }
- if (LLApp::isExiting())
- {
- percent_done = 100.f;
- }
- gViewerWindowp->setProgressPercent(percent_done);
- }
- else if (gRestoreGL)
- {
- F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f /
- RESTORE_GL_TIME;
- if (percent_done > 100.f || LLApp::isExiting())
- {
- gViewerWindowp->setShowProgress(false);
- gRestoreGL = false;
- }
- else
- {
- gViewerWindowp->setProgressPercent(percent_done);
- }
- }
- // Progressively increase draw distance after TP when required and when
- // possible (enough available memory). HB
- else if (gSavedDrawDistance > 0.f && !gAgent.teleportInProgress() &&
- LLViewerTexture::sDesiredDiscardBias <= 2.5f)
- {
- static LLCachedControl<U32> speed_rez_interval(gSavedSettings,
- "SpeedRezInterval");
- if (gTeleportArrivalTimer.getElapsedTimeF32() >= (F32)speed_rez_interval)
- {
- gTeleportArrivalTimer.reset();
- F32 current = gSavedSettings.getF32("RenderFarClip");
- if (gSavedDrawDistance > current)
- {
- current *= 2.f;
- if (current > gSavedDrawDistance)
- {
- current = gSavedDrawDistance;
- }
- gSavedSettings.setF32("RenderFarClip", current);
- }
- if (current >= gSavedDrawDistance)
- {
- gSavedDrawDistance = 0.f;
- gSavedSettings.setF32("SavedRenderFarClip", 0.f);
- }
- }
- }
- // We do this here instead of inside of handleRenderFarClipChanged() in
- // llviewercontrol.cpp to ensure this is not done during rendering, which
- // would cause drawables to get destroyed while LLSpatialGroup::sNoDelete
- // is true and would therefore cause a mess. HB
- if (gUpdateDrawDistance)
- {
- gUpdateDrawDistance = false;
- F32 draw_distance = gSavedSettings.getF32("RenderFarClip");
- gAgent.mDrawDistance = draw_distance;
- gWorld.setLandFarClip(draw_distance);
- LLVOCacheEntry::updateSettings();
- }
- //////////////////////////
- // Prepare for the next frame
- // Update the camera
- gViewerCamera.setZoomParameters(zoom_factor, subfield);
- gViewerCamera.setNear(MIN_NEAR_PLANE);
- if (gDisconnected)
- {
- render_ui();
- }
- //////////////////////////
- // Set rendering options
- stop_glerror();
- ///////////////////////////////////////
- // Slam lighting parameters back to our defaults.
- // Note that these are not the same as GL defaults...
- gGL.setAmbientLightColor(LLColor4::white);
- /////////////////////////////////////
- // Render
- //
- // Actually push all of our triangles to the screen.
- // Do render-to-texture stuff here
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
- {
- LL_FAST_TIMER(FTM_UPDATE_TEXTURES);
- if (LLViewerDynamicTexture::updateAllInstances())
- {
- gGL.setColorMask(true, true);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- }
- gViewerWindowp->setupViewport();
- // Reset per-frame statistics.
- gPipeline.resetFrameStats();
- LLViewerTextureList::resetFrameStats();
- if (!gDisconnected && !LLApp::isExiting())
- {
- if (!gSnapshot && !gTeleportDisplay && LLPipeline::sRenderMirrors)
- {
- gPipeline.mHeroProbeManager.update();
- gPipeline.mHeroProbeManager.renderProbes();
- }
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- // Do not draw hud objects in this frame
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
- {
- // Do not draw hud particles in this frame
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
- }
- display_update_camera();
- // Update all the sky/atmospheric/water settings
- gEnvironment.update();
- stop_glerror();
- {
- LL_FAST_TIMER(FTM_HUD_UPDATE);
- LLHUDManager::updateEffects();
- LLHUDObject::updateAll();
- stop_glerror();
- }
- {
- LL_FAST_TIMER(FTM_DISPLAY_UPDATE_GEOM);
- // 50 ms/second update time:
- const F32 max_geom_update_time = 0.05f * gFrameIntervalSeconds;
- gPipeline.createObjects(max_geom_update_time);
- gPipeline.processPartitionQ();
- gPipeline.updateGeom(max_geom_update_time);
- stop_glerror();
- }
- gPipeline.updateGL();
- stop_glerror();
- // Increment drawable frame counter
- LLDrawable::incrementVisible();
- LLSpatialGroup::sNoDelete = true;
- if (LLViewerFetchedTexture::sWhiteImagep.notNull())
- {
- LLTexUnit::sWhiteTexture =
- LLViewerFetchedTexture::sWhiteImagep->getTexName();
- }
- S32 occlusion = LLPipeline::sUseOcclusion;
- if (gDepthDirty)
- {
- // Depth buffer is invalid, do not overwrite occlusion state
- LLPipeline::sUseOcclusion = llmin(occlusion, 1);
- gDepthDirty = false;
- }
- LL_GL_CHECK_STATES;
- static LLCullResult result;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- LLPipeline::sUnderWaterRender = gViewerCamera.cameraUnderWater();
- gPipeline.updateCull(gViewerCamera, result);
- LL_GL_CHECK_STATES;
- {
- if (gResizeScreenTexture)
- {
- gPipeline.resizeScreenTexture();
- }
- gGL.setColorMask(true, true);
- glClearColor(0.f, 0.f, 0.f, 0.f);
- LL_GL_CHECK_STATES;
- if (!for_snapshot)
- {
- if (gFrameCount > 1)
- {
- // For some reason, ATI 4800 series will error out if you
- // try to generate a shadow before the first frame is
- // through
- gPipeline.generateSunShadow();
- }
- LLVertexBuffer::unbind();
- LL_GL_CHECK_STATES;
- const LLMatrix4a proj = gGLProjection;
- const LLMatrix4a mod = gGLModelView;
- glViewport(0, 0, 512, 512);
- {
- LL_FAST_TIMER(FTM_IMPOSTORS_UPDATE);
- LLViewerCamera::sCurCameraID =
- LLViewerCamera::CAMERA_WORLD;
- LLVOAvatar::updateImpostors();
- }
- gGLProjection = proj;
- gGLModelView = mod;
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.loadMatrix(proj);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadMatrix(mod);
- gViewerWindowp->setupViewport();
- LL_GL_CHECK_STATES;
- }
- if (gUsePBRShaders)
- {
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- else
- {
- glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
- }
- if (!gUsePBRShaders)
- {
- gPipeline.generateWaterReflection();
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
- {
- gPipeline.renderPhysicsDisplay();
- }
- LL_GL_CHECK_STATES;
- }
- //////////////////////////////////////
- // Update images, using the image stats generated during object update
- // and culling. This may put objects onto the retextured list. Doing
- // this here gives hardware occlusion queries extra time to complete...
- {
- LL_FAST_TIMER(FTM_IMAGE_UPDATE);
- {
- LL_FAST_TIMER(FTM_IMAGE_UPDATE_CLASS);
- LLViewerTexture::updateClass();
- }
- {
- LL_FAST_TIMER(FTM_IMAGE_UPDATE_BUMP);
- // Must be called before gTextureList version so that its
- // textures are thrown out first.
- gBumpImageList.updateImages();
- }
- {
- LL_FAST_TIMER(FTM_IMAGE_UPDATE_LIST);
- F32 max_image_decode_time = 0.2f * gFrameIntervalSeconds;
- // Min 2ms/frame, max 20ms/frame)
- max_image_decode_time = llclamp(max_image_decode_time, 0.002f,
- 0.02f);
- gTextureList.updateImages(max_image_decode_time);
- }
- {
- // Remove dead gltf materials
- gGLTFMaterialList.flushMaterials();
- }
- }
- ///////////////////////////////////
- // StateSort
- //
- // Responsible for taking visible objects, and adding them to the
- // appropriate draw orders. In the case of alpha objects, z-sorts them
- // first. Also creates special lists for outlines and selected face
- // rendering.
- {
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- gPipeline.stateSort(gViewerCamera, result);
- if (rebuild)
- {
- // Rebuild pools
- gPipeline.rebuildPools();
- }
- }
- LL_GL_CHECK_STATES;
- LLPipeline::sUseOcclusion = occlusion;
- {
- LL_FAST_TIMER(FTM_UPDATE_SKY);
- gSky.updateSky();
- }
- if (gUseWireframe)
- {
- glClearColor(0.5f, 0.5f, 0.5f, 0.f);
- glClear(GL_COLOR_BUFFER_BIT);
- if (!gUsePBRShaders)
- {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- }
- }
- LLPipeline::sUnderWaterRender = gViewerCamera.cameraUnderWater();
- LL_GL_CHECK_STATES;
- gGL.setColorMask(true, true);
- if (LLPipeline::sRenderDeferred)
- {
- gPipeline.mRT->mDeferredScreen.bindTarget();
- if (gUsePBRShaders && gUseWireframe)
- {
- glClearColor(0.5f, 0.5f, 0.5f, 1.f);
- }
- else
- {
- glClearColor(1.f, 0.f, 1.f, 1.f);
- }
- gPipeline.mRT->mDeferredScreen.clear();
- }
- else
- {
- gPipeline.mRT->mScreen.bindTarget();
- if (LLPipeline::sUnderWaterRender &&
- !gPipeline.canUseWindLightShaders())
- {
- const LLColor4& col = LLDrawPoolWater::sWaterFogColor;
- glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
- }
- gPipeline.mRT->mScreen.clear();
- }
- gGL.setColorMask(true, false);
- if (!gRestoreGL &&
- !(gAppViewerp->logoutRequestSent() &&
- gAppViewerp->hasSavedFinalSnapshot()))
- {
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- if (gUsePBRShaders)
- {
- gGL.setColorMask(true, true);
- gPipeline.renderGeomDeferred(gViewerCamera, true);
- }
- else
- {
- gGL.setColorMask(true, false);
- if (LLPipeline::sRenderDeferred)
- {
- gPipeline.renderGeomDeferred(gViewerCamera);
- }
- else
- {
- gPipeline.renderGeom(gViewerCamera);
- }
- gGL.setColorMask(true, true);
- // Store this frame's modelview matrix for use when rendering
- // next frame's occlusion queries
- gGLLastModelView = gGLModelView;
- gGLLastProjection = gGLProjection;
- }
- stop_glerror();
- }
- {
- LL_FAST_TIMER(FTM_TEXTURE_UNBIND);
- for (S32 i = 0; i < gGLManager.mNumTextureImageUnits; ++i)
- {
- // Dummy cleanup of any currently bound textures
- LLTexUnit* unitp = gGL.getTexUnit(i);
- if (!unitp) continue; // Paranoia
- LLTexUnit::eTextureType type = unitp->getCurrType();
- if (type != LLTexUnit::TT_NONE)
- {
- unitp->unbind(type);
- unitp->disable();
- }
- }
- }
- LLRenderTarget& rt =
- LLPipeline::sRenderDeferred ? gPipeline.mRT->mDeferredScreen
- : gPipeline.mRT->mScreen;
- rt.flush();
- if (!gUsePBRShaders && rt.getFBO() && LLRenderTarget::sUseFBO)
- {
- LLRenderTarget::copyContentsToFramebuffer(rt, 0, 0, rt.getWidth(),
- rt.getHeight(), 0, 0,
- rt.getWidth(),
- rt.getHeight(),
- GL_DEPTH_BUFFER_BIT,
- GL_NEAREST);
- }
- if (LLPipeline::sRenderDeferred)
- {
- gPipeline.renderDeferredLighting();
- }
- LLPipeline::sUnderWaterRender = false;
- if (!for_snapshot)
- {
- render_ui();
- }
- LLSpatialGroup::sNoDelete = false;
- gPipeline.clearReferences();
- }
- stop_glerror();
- if (report_materials_stats && gStatusBarp)
- {
- gStatusBarp->materialsUsage(LLPipeline::sUsingALM,
- LLPipeline::sUsingPBR,
- LLPipeline::sLacksLegacyFallback,
- LLPipeline::sLacksBaseColorFallback);
- }
- if (LLPipeline::sRenderFrameTest)
- {
- LLWorld::sendAgentResume();
- LLPipeline::sRenderFrameTest = false;
- }
- display_stats();
- gShiftFrame = gScreenIsDirty = false;
- if (gShaderProfileFrame)
- {
- gShaderProfileFrame = false;
- LLGLSLShader::finishProfile();
- }
- }
- // For use by the PBR renderer only.
- void display_cube_face()
- {
- if (gRestoreGL || gSnapshot || gTeleportDisplay || !gPipeline.isInit() ||
- gAppViewerp->logoutRequestSent())
- {
- return;
- }
- LLGLSDefault gls_default;
- LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
- LLVertexBuffer::unbind();
- gPipeline.disableLights();
- gViewerWindowp->setupViewport();
- // Do not render HUDs in this frame
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
- {
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
- }
- display_update_camera();
- // We need to update environment related uniforms and mark them dirty in
- // shaders used during the cube snapshot.
- gEnvironment.updateSettingsUniforms();
- gEnvironment.dirtyUniforms();
- LLSpatialGroup::sNoDelete = true;
- {
- // Occlusion data is from main camera point of view, do not read or
- // write it during cube snapshots.
- LLDisableOcclusionCulling no_occlusion;
- static LLCullResult result;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- LLPipeline::sUnderWaterRender = gViewerCamera.cameraUnderWater();
- gPipeline.updateCull(gViewerCamera, result);
- gGL.setColorMask(true, true);
- glClearColor(0.f, 0.f, 0.f, 0.f);
- gPipeline.generateSunShadow();
- glClear(GL_DEPTH_BUFFER_BIT);
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- gPipeline.stateSort(gViewerCamera, result);
- }
- LLPipeline::sUnderWaterRender = gViewerCamera.cameraUnderWater();
- gGL.setColorMask(true, true);
- gPipeline.mRT->mDeferredScreen.bindTarget();
- if (gUseWireframe)
- {
- glClearColor(0.5f, 0.5f, 0.5f, 1.f);
- }
- else
- {
- glClearColor(1.f, 0.f, 1.f, 1.f);
- }
- gPipeline.mRT->mDeferredScreen.clear();
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- gPipeline.renderGeomDeferred(gViewerCamera, false);
- gPipeline.mRT->mDeferredScreen.flush();
- gPipeline.renderDeferredLighting();
- LLPipeline::sUnderWaterRender = false;
- LLSpatialGroup::sNoDelete = false;
- gPipeline.clearReferences();
- }
- void render_hud_attachments()
- {
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- const LLMatrix4a current_proj = gGLProjection;
- const LLMatrix4a current_mod = gGLModelView;
- F32 current_zoom = gAgent.mHUDCurZoom;
- F32 target_zoom = gAgent.getHUDTargetZoom();
- if (current_zoom != target_zoom)
- {
- // Smoothly interpolate current zoom level
- gAgent.mHUDCurZoom = lerp(current_zoom, target_zoom,
- LLCriticalDamp::getInterpolant(0.03f));
- }
- if (LLPipeline::sShowHUDAttachments && !gDisconnected &&
- setup_hud_matrices())
- {
- LLPipeline::sRenderingHUDs = true;
- LLCamera hud_cam = gViewerCamera;
- hud_cam.setOrigin(-1.f, 0.f, 0.f);
- hud_cam.setAxes(LLVector3::x_axis, LLVector3::y_axis,
- LLVector3::z_axis);
- LLViewerCamera::updateFrustumPlanes(hud_cam, true);
- static LLCachedControl<bool> render_hud_particles(gSavedSettings,
- "RenderHUDParticles");
- bool render_particles =
- render_hud_particles &&
- gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
- // Only render hud objects
- gPipeline.pushRenderTypeMask();
- // Turn off everything
- gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
- // Turn on HUD
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- // Turn on HUD particles
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
- // If particles are off, turn off hud-particles as well
- if (!render_particles)
- {
- // Turn back off HUD particles
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
- }
- bool has_ui =
- gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
- if (has_ui)
- {
- gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- // Disable occlusion from now on and until end of context
- LLDisableOcclusionCulling no_occlusion;
- // Cull, sort, and render hud objects
- static LLCullResult result;
- LLSpatialGroup::sNoDelete = true;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- gPipeline.updateCull(hud_cam, result, NULL, true);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_MASK);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK);
- 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_MATERIAL);
- 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);
- if (gUsePBRShaders)
- {
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_MAT_PBR);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_MAT_PBR_ALPHA_MASK);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MAT_PBR);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MAT_ALPHA_MASK_PBR);
- }
- gPipeline.stateSort(hud_cam, result);
- if (gUsePBRShaders)
- {
- gPipeline.renderGeomPostDeferred(hud_cam);
- }
- else
- {
- gPipeline.renderGeom(hud_cam);
- }
- LLSpatialGroup::sNoDelete = false;
- #if 0
- gPipeline.clearReferences();
- #endif
- render_hud_elements();
- // Restore type mask
- gPipeline.popRenderTypeMask();
- if (has_ui)
- {
- gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- LLPipeline::sRenderingHUDs = false;
- }
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- gGLProjection = current_proj;
- gGLModelView = current_mod;
- }
- bool setup_hud_matrices()
- {
- LLRect whole_screen = gViewerWindowp->getVirtualWindowRect();
- // Apply camera zoom transform (for high res screenshots)
- F32 zoom_factor = gViewerCamera.getZoomFactor();
- S16 sub_region = gViewerCamera.getZoomSubRegion();
- if (zoom_factor > 1.f)
- {
- S32 num_horizontal_tiles = llceil(zoom_factor);
- S32 tile_width = ll_roundp((F32)gViewerWindowp->getWindowWidth() /
- zoom_factor);
- S32 tile_height = ll_roundp((F32)gViewerWindowp->getWindowHeight() /
- zoom_factor);
- S32 tile_y = sub_region / num_horizontal_tiles;
- S32 tile_x = sub_region - (tile_y * num_horizontal_tiles);
- whole_screen.setLeftTopAndSize(tile_x * tile_width,
- gViewerWindowp->getWindowHeight() -
- (tile_y * tile_height),
- tile_width, tile_height);
- }
- return setup_hud_matrices(whole_screen);
- }
- bool setup_hud_matrices(const LLRect& screen_region)
- {
- LLMatrix4a proj, model;
- if (!get_hud_matrices(screen_region, proj, model))
- {
- return false;
- }
- // Set up transform to keep HUD objects in front of camera
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.loadMatrix(proj);
- gGLProjection = proj;
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadMatrix(model);
- gGLModelView = model;
- return true;
- }
- bool get_hud_matrices(LLMatrix4a& proj, LLMatrix4a& model)
- {
- LLRect whole_screen = gViewerWindowp->getVirtualWindowRect();
- return get_hud_matrices(whole_screen, proj, model);
- }
- bool get_hud_matrices(const LLRect& screen_region,
- LLMatrix4a& proj, LLMatrix4a& model)
- {
- if (!isAgentAvatarValid() || !gAgentAvatarp->hasHUDAttachment())
- {
- return false;
- }
- LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
- F32 aspect_ratio = gViewerCamera.getAspect();
- F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
- proj = gl_ortho(-0.5f * aspect_ratio, 0.5f * aspect_ratio, -0.5f, 0.5f,
- 0.f, hud_depth);
- proj.getRow<2>().copyComponent<2>(LLVector4a(-0.01f));
- F32 wwidth = (F32)gViewerWindowp->getWindowWidth();
- F32 wheight = (F32)gViewerWindowp->getWindowHeight();
- F32 scale_x = wwidth / (F32)screen_region.getWidth();
- F32 scale_y = wheight /(F32)screen_region.getHeight();
- F32 delta_x = screen_region.getCenterX() - screen_region.mLeft;
- F32 delta_y = screen_region.getCenterY() - screen_region.mBottom;
- proj.applyTranslationAffine(clamp_rescale(delta_x, 0.f, wwidth,
- 0.5f * scale_x * aspect_ratio,
- -0.5f * scale_x * aspect_ratio),
- clamp_rescale(delta_y, 0.f, wheight,
- 0.5f * scale_y,
- -0.5f * scale_y), 0.f);
- proj.applyScaleAffine(scale_x, scale_y, 1.f);
- model = OGL_TO_CFR_ROT4A;
- model.applyTranslationAffine(LLVector3(hud_depth * 0.5f -
- hud_bbox.getCenterLocal().mV[VX],
- 0.f, 0.f));
- model.applyScaleAffine(gAgent.mHUDCurZoom);
- return true;
- }
- void render_ui(F32 zoom_factor)
- {
- gGL.flush();
- {
- LL_FAST_TIMER(FTM_RENDER_UI);
- LL_GL_CHECK_STATES;
- const LLMatrix4a saved_view = gGLModelView;
- bool not_snaphot = !gSnapshot;
- if (not_snaphot)
- {
- gGL.pushMatrix();
- gGL.loadMatrix(gGLLastModelView);
- gGLModelView = gGLLastModelView;
- }
- // Finalize scene
- gPipeline.renderFinalize();
- //MK
- {
- LL_TRACY_TIMER(TRC_RLV_RENDER_LIMITS);
- // Possibly draw a big black sphere around our avatar if the camera
- // render is limited
- if (gRLenabled && !gRLInterface.mRenderLimitRenderedThisFrame &&
- !(isAgentAvatarValid() && gAgentAvatarp->isFullyLoaded()))
- {
- gRLInterface.drawRenderLimit(true);
- }
- }
- //mk
- render_hud_elements();
- render_hud_attachments();
- LLGLSDefault gls_default;
- LLGLSUIDefault gls_ui;
- gPipeline.disableLights();
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- if (!gDisconnected)
- {
- render_ui_3d();
- LL_GL_CHECK_STATES;
- }
- else
- {
- render_disconnected_background();
- }
- if (gUsePBRShaders)
- {
- LLHUDObject::renderAll();
- }
- render_ui_2d();
- LL_GL_CHECK_STATES;
- }
- else
- {
- // Make sure particle effects disappear
- LLHUDObject::removeExpired();
- }
- if (!gUsePBRShaders)
- {
- gGL.flush();
- }
- gViewerWindowp->setup2DRender();
- gViewerWindowp->updateDebugText();
- gViewerWindowp->drawDebugText();
- if (!gUsePBRShaders)
- {
- LLVertexBuffer::unbind();
- }
- if (not_snaphot)
- {
- gGLModelView = saved_view;
- gGL.popMatrix();
- }
- gGL.flush();
- }
- // Do not include this in FTM_RENDER_UI, since during the swap all sorts
- // non-UI stuff will be drawn... HB
- if (gDisplaySwapBuffers)
- {
- gWindowp->swapBuffers();
- }
- gDisplaySwapBuffers = true;
- }
- void renderCoordinateAxes()
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.begin(LLRender::LINES);
- gGL.color3f(1.f, 0.f, 0.f); // i direction = X-Axis = red
- gGL.vertex3f(0.f, 0.f, 0.f);
- gGL.vertex3f(2.f, 0.f, 0.f);
- gGL.vertex3f(3.f, 0.f, 0.f);
- gGL.vertex3f(5.f, 0.f, 0.f);
- gGL.vertex3f(6.f, 0.f, 0.f);
- gGL.vertex3f(8.f, 0.f, 0.f);
- // Make an X
- gGL.vertex3f(11.f, 1.f, 1.f);
- gGL.vertex3f(11.f, -1.f, -1.f);
- gGL.vertex3f(11.f, 1.f, -1.f);
- gGL.vertex3f(11.f, -1.f, 1.f);
- gGL.color3f(0.f, 1.f, 0.f); // j direction = Y-Axis = green
- gGL.vertex3f(0.f, 0.f, 0.f);
- gGL.vertex3f(0.f, 2.f, 0.f);
- gGL.vertex3f(0.f, 3.f, 0.f);
- gGL.vertex3f(0.f, 5.f, 0.f);
- gGL.vertex3f(0.f, 6.f, 0.f);
- gGL.vertex3f(0.f, 8.f, 0.f);
- // Make a Y
- gGL.vertex3f(1.f, 11.f, 1.f);
- gGL.vertex3f(0.f, 11.f, 0.f);
- gGL.vertex3f(-1.f, 11.f, 1.f);
- gGL.vertex3f(0.f, 11.f, 0.f);
- gGL.vertex3f(0.f, 11.f, 0.f);
- gGL.vertex3f(0.f, 11.f, -1.f);
- gGL.color3f(0.f, 0.f, 1.f); // Z-Axis = blue
- gGL.vertex3f(0.f, 0.f, 0.f);
- gGL.vertex3f(0.f, 0.f, 2.f);
- gGL.vertex3f(0.f, 0.f, 3.f);
- gGL.vertex3f(0.f, 0.f, 5.f);
- gGL.vertex3f(0.f, 0.f, 6.f);
- gGL.vertex3f(0.f, 0.f, 8.f);
- // Make a Z
- gGL.vertex3f(-1.f, 1.f, 11.f);
- gGL.vertex3f(1.f, 1.f, 11.f);
- gGL.vertex3f(1.f, 1.f, 11.f);
- gGL.vertex3f(-1.f, -1.f, 11.f);
- gGL.vertex3f(-1.f, -1.f, 11.f);
- gGL.vertex3f(1.f, -1.f, 11.f);
- gGL.end();
- }
- void draw_axes()
- {
- LLGLSUIDefault gls_ui;
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- // A vertical white line at origin
- LLVector3 v = gAgent.getPositionAgent();
- gGL.begin(LLRender::LINES);
- gGL.color3f(1.f, 1.f, 1.f);
- gGL.vertex3f(0.f, 0.f, 0.f);
- gGL.vertex3f(0.f, 0.f, 40.f);
- gGL.end();
- // Some coordinate axes
- gGL.pushMatrix();
- gGL.translatef(v.mV[VX], v.mV[VY], v.mV[VZ]);
- renderCoordinateAxes();
- gGL.popMatrix();
- }
- void render_ui_3d()
- {
- LLGLSPipeline gls_pipeline;
- //////////////////////////////////////
- // Render 3D UI elements
- // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
- // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
- /////////////////////////////////////////////////////////////
- // Render 2.5D elements (2D elements in the world)
- // Stuff without z writes
- // Debugging stuff goes before the UI.
- gUIProgram.bind();
- if (gUsePBRShaders)
- {
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- }
- // Coordinate axes
- static LLCachedControl<bool> show_axes(gSavedSettings, "ShowAxes");
- if (show_axes)
- {
- draw_axes();
- }
- // Non HUD call in render_hud_elements
- gViewerWindowp->renderSelections(false, false, true);
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
- gSky.addSunMoonBeacons();
- }
- // Make sure particle effects disappear
- LLHUDObject::removeExpired();
- stop_glerror();
- }
- // Renders 2D UI elements that overlay the world (no z compare)
- void render_ui_2d()
- {
- LLGLSUIDefault gls_ui;
- // Disable wireframe mode below here, as this is HUD/menus
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- // Menu overlays, HUD, etc
- gViewerWindowp->setup2DRender();
- F32 zoom_factor = gViewerCamera.getZoomFactor();
- S16 sub_region = gViewerCamera.getZoomSubRegion();
- if (zoom_factor > 1.f)
- {
- // Decompose subregion number to x and y values
- S32 pos_y = sub_region / llceil(zoom_factor);
- S32 pos_x = sub_region - pos_y * llceil(zoom_factor);
- // offset for this tile
- LLFontGL::sCurOrigin.mX -=
- ll_round((F32)gViewerWindowp->getWindowWidth() * (F32)pos_x /
- zoom_factor);
- LLFontGL::sCurOrigin.mY -=
- ll_round((F32)gViewerWindowp->getWindowHeight() * (F32)pos_y /
- zoom_factor);
- }
- // Render outline for HUD
- static LLCachedControl<F32> hud_scale(gSavedSettings, "HUDScaleFactor");
- F32 zoom = gAgent.mHUDCurZoom / llmax(0.5f, hud_scale);
- if (isAgentAvatarValid() && zoom <= 0.98f)
- {
- if (gUsePBRShaders)
- {
- gUIProgram.bind();
- }
- gGL.pushMatrix();
- S32 half_width = gViewerWindowp->getWindowWidth() / 2;
- S32 half_height = gViewerWindowp->getWindowHeight() / 2;
- gGL.scalef(LLUI::sGLScaleFactor.mV[0],
- LLUI::sGLScaleFactor.mV[1], 1.f);
- gGL.translatef((F32)half_width, (F32)half_height, 0.f);
- gGL.scalef(zoom, zoom, 1.f);
- gGL.color4fv(LLColor4::white.mV);
- gl_rect_2d(-half_width, half_height, half_width, -half_height, false);
- gGL.popMatrix();
- if (gUsePBRShaders)
- {
- gUIProgram.unbind();
- }
- }
- gViewerWindowp->draw();
- // Reset current origin for font rendering, in case of tiling render
- LLFontGL::sCurOrigin.set(0, 0);
- stop_glerror();
- }
- void render_disconnected_background()
- {
- gUIProgram.bind();
- LLTexUnit* unit0 = gGL.getTexUnit(0);
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- if (!gDisconnectedImagep && gDisconnected)
- {
- std::string temp = gDirUtil.getLindenUserDir() + LL_DIR_DELIM_STR;
- if (gIsInProductionGrid)
- {
- temp += SCREEN_LAST_FILENAME;
- }
- else
- {
- temp += SCREEN_LAST_BETA_FILENAME;
- }
- LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
- if (!image_bmp->load(temp))
- {
- return;
- }
- llinfos << "Loaded last bitmap: " << temp << llendl;
- LLPointer<LLImageRaw> raw = new LLImageRaw;
- if (!image_bmp->decode(raw))
- {
- llwarns << "Bitmap decode failed" << llendl;
- gDisconnectedImagep = NULL;
- return;
- }
- U8* rawp = raw->getData();
- S32 npixels = (S32)image_bmp->getWidth() * (S32)image_bmp->getHeight();
- for (S32 i = 0; i < npixels; ++i)
- {
- S32 sum = 0;
- sum = *rawp + *(rawp + 1) + *(rawp + 2);
- sum /= 3;
- *rawp = ((S32)sum * 6 + *rawp) / 7;
- rawp++;
- *rawp = ((S32)sum * 6 + *rawp) / 7;
- rawp++;
- *rawp = ((S32)sum * 6 + *rawp) / 7;
- rawp++;
- }
- raw->expandToPowerOfTwo();
- gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(),
- false);
- gStartTexture = gDisconnectedImagep;
- unit0->unbind(LLTexUnit::TT_TEXTURE);
- }
- // Make sure the progress view always fills the entire window.
- S32 width = gViewerWindowp->getWindowWidth();
- S32 height = gViewerWindowp->getWindowHeight();
- if (gDisconnectedImagep)
- {
- LLGLSUIDefault gls_ui;
- gViewerWindowp->setup2DRender();
- gGL.pushMatrix();
- {
- // scale ui to reflect UIScaleFactor
- // this can't be done in setup2DRender because it requires a
- // pushMatrix/popMatrix pair
- const LLVector2& display_scale = gViewerWindowp->getDisplayScale();
- gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
- unit0->bind(gDisconnectedImagep);
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- gl_rect_2d_simple_tex(width, height);
- unit0->unbind(LLTexUnit::TT_TEXTURE);
- }
- gGL.popMatrix();
- }
- gGL.flush();
- gUIProgram.unbind();
- }
- void display_cleanup()
- {
- gDisconnectedImagep = NULL;
- }
- void hud_render_text(const LLWString& wstr, const LLVector3& pos_agent,
- const LLFontGL& font, U8 style, F32 x_offset,
- F32 y_offset, const LLColor4& color, bool orthographic)
- {
- // Do cheap plane culling
- LLVector3 dir_vec = pos_agent - gViewerCamera.getOrigin();
- dir_vec /= dir_vec.length();
- if (wstr.empty() ||
- (!orthographic && dir_vec * gViewerCamera.getAtAxis() <= 0.f))
- {
- return;
- }
- LLVector3 right_axis;
- LLVector3 up_axis;
- if (orthographic)
- {
- F32 height_inv = 1.f / (F32)gViewerWindowp->getWindowHeight();
- right_axis.set(0.f, -height_inv, 0.f);
- up_axis.set(0.f, 0.f, height_inv);
- }
- else
- {
- gViewerCamera.getPixelVectors(pos_agent, up_axis, right_axis);
- }
- LLQuaternion rot;
- if (!orthographic)
- {
- rot = gViewerCamera.getQuaternion();
- rot = rot * LLQuaternion(-F_PI_BY_TWO, gViewerCamera.getYAxis());
- rot = rot * LLQuaternion(F_PI_BY_TWO, gViewerCamera.getXAxis());
- }
- else
- {
- rot = LLQuaternion(-F_PI_BY_TWO, LLVector3::z_axis);
- rot = rot * LLQuaternion(-F_PI_BY_TWO, LLVector3::y_axis);
- }
- F32 angle;
- LLVector3 axis;
- rot.getAngleAxis(&angle, axis);
- LLVector3 render_pos = pos_agent + floorf(x_offset) * right_axis +
- floorf(y_offset) * up_axis;
- // Get the render_pos in screen space
- LLVector3 win_coord;
- LLRect viewport(gGLViewport[0], gGLViewport[1] + gGLViewport[3],
- gGLViewport[0] + gGLViewport[2], gGLViewport[1]);
- gGL.projectf(render_pos, gGLModelView, gGLProjection, viewport, win_coord);
- // Fonts all render orthographically, set up projection
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- LLUI::pushMatrix();
- gl_state_for_2d(gViewerWindowp->getWindowDisplayWidth(),
- gViewerWindowp->getWindowDisplayHeight());
- gViewerWindowp->setupViewport();
- LLUI::loadIdentity();
- gGL.loadIdentity();
- LLUI::translate(win_coord.mV[VX] / LLFontGL::sScaleX,
- win_coord.mV[VY] / LLFontGL::sScaleY,
- -2.f * win_coord.mV[VZ] + 1.f);
- F32 right_x;
- font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE,
- style, wstr.length(), 1000, &right_x);
- LLUI::popMatrix();
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- }
|