void LLVOWLSky::drawDome(void) { if (mStripsVerts.empty()) { updateGeometry(mDrawable); } LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; #if DOME_SLICES std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips; end_strips = mStripsVerts.end(); for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter) { LLVertexBuffer * strips_segment = strips_vbo_iter->get(); strips_segment->setBuffer(data_mask); strips_segment->drawRange( LLRender::TRIANGLE_STRIP, 0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), 0); gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices(), LLRender::TRIANGLE_STRIP); } #else mStripsVerts->setBuffer(data_mask); glDrawRangeElements( GL_TRIANGLES, 0, mStripsVerts->getNumVerts()-1, mStripsVerts->getNumIndices(), GL_UNSIGNED_SHORT, mStripsVerts->getIndicesPointer()); #endif LLVertexBuffer::unbind(); }
void LLViewerObjectList::renderObjectBeacons() { if (mDebugBeacons.empty()) { return; } LLGLSUIDefault gls_ui; if (LLGLSLShader::sNoFixedFunction) { gUIProgram.bind(); } { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); S32 last_line_width = -1; // gGL.begin(LLRender::LINES); // Always happens in (line_width != last_line_width) for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter) { const LLDebugBeacon &debug_beacon = *iter; LLColor4 color = debug_beacon.mColor; color.mV[3] *= 0.25f; S32 line_width = debug_beacon.mLineWidth; if (line_width != last_line_width) { gGL.flush(); glLineWidth( (F32)line_width ); last_line_width = line_width; } const LLVector3 &thisline = debug_beacon.mPositionAgent; gGL.begin(LLRender::LINES); gGL.color4fv(color.mV); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] - 50.f); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] + 50.f); gGL.vertex3f(thisline.mV[VX] - 2.f,thisline.mV[VY],thisline.mV[VZ]); gGL.vertex3f(thisline.mV[VX] + 2.f,thisline.mV[VY],thisline.mV[VZ]); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] - 2.f,thisline.mV[VZ]); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] + 2.f,thisline.mV[VZ]); draw_line_cube(0.10f, thisline); gGL.end(); } } { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); S32 last_line_width = -1; // gGL.begin(LLRender::LINES); // Always happens in (line_width != last_line_width) for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter) { const LLDebugBeacon &debug_beacon = *iter; S32 line_width = debug_beacon.mLineWidth; if (line_width != last_line_width) { gGL.flush(); glLineWidth( (F32)line_width ); last_line_width = line_width; } const LLVector3 &thisline = debug_beacon.mPositionAgent; gGL.begin(LLRender::LINES); gGL.color4fv(debug_beacon.mColor.mV); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] - 0.5f); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] + 0.5f); gGL.vertex3f(thisline.mV[VX] - 0.5f,thisline.mV[VY],thisline.mV[VZ]); gGL.vertex3f(thisline.mV[VX] + 0.5f,thisline.mV[VY],thisline.mV[VZ]); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] - 0.5f,thisline.mV[VZ]); gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] + 0.5f,thisline.mV[VZ]); draw_line_cube(0.10f, thisline); gGL.end(); } gGL.flush(); glLineWidth(1.f); for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(); iter != mDebugBeacons.end(); ++iter) { LLDebugBeacon &debug_beacon = *iter; if (debug_beacon.mString == "") { continue; } LLHUDText *hud_textp = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); hud_textp->setZCompare(FALSE); LLColor4 color; color = debug_beacon.mTextColor; color.mV[3] *= 1.f; hud_textp->setString(debug_beacon.mString); hud_textp->setColor(color); hud_textp->setPositionAgent(debug_beacon.mPositionAgent); debug_beacon.mHUDObject = hud_textp; } } }
void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLViewerRegion* regionp) { S32 x, y; F32 x1, y1; // start point F32 x2, y2; // end point F32 alpha = 0; F32 dist = 0; F32 dx, dy; F32 collision_height; const S32 STRIDE = (mParcelsPerEdge+1); LLVector3 pos = gAgent.getPositionAgent(); F32 pos_x = pos.mV[VX]; F32 pos_y = pos.mV[VY]; LLGLSUIDefault gls_ui; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); if (mCollisionBanned == BA_BANNED) { collision_height = BAN_HEIGHT; } else { collision_height = PARCEL_HEIGHT; } if (use_pass && (mCollisionBanned == BA_NOT_ON_LIST)) { gGL.getTexUnit(0)->bind(mPassImage); } else { gGL.getTexUnit(0)->bind(mBlockedImage); } gGL.begin(LLRender::QUADS); for (y = 0; y < STRIDE; y++) { for (x = 0; x < STRIDE; x++) { U8 segment_mask = segments[x + y*STRIDE]; U8 direction; const F32 MAX_ALPHA = 0.95f; const S32 DIST_OFFSET = 5; const S32 MIN_DIST_SQ = DIST_OFFSET*DIST_OFFSET; const S32 MAX_DIST_SQ = 169; if (segment_mask & SOUTH_MASK) { x1 = x * PARCEL_GRID_STEP_METERS; y1 = y * PARCEL_GRID_STEP_METERS; x2 = x1 + PARCEL_GRID_STEP_METERS; y2 = y1; dy = (pos_y - y1) + DIST_OFFSET; if (pos_x < x1) dx = pos_x - x1; else if (pos_x > x2) dx = pos_x - x2; else dx = 0; dist = dx*dx+dy*dy; if (dist < MIN_DIST_SQ) alpha = MAX_ALPHA; else if (dist > MAX_DIST_SQ) alpha = 0.0f; else alpha = 30/dist; alpha = llclamp(alpha, 0.0f, MAX_ALPHA); gGL.color4f(1.f, 1.f, 1.f, alpha); if ((pos_y - y1) < 0) direction = SOUTH_MASK; else direction = NORTH_MASK; // avoid Z fighting renderOneSegment(x1+0.1f, y1+0.1f, x2+0.1f, y2+0.1f, collision_height, direction, regionp); } if (segment_mask & WEST_MASK) { x1 = x * PARCEL_GRID_STEP_METERS; y1 = y * PARCEL_GRID_STEP_METERS; x2 = x1; y2 = y1 + PARCEL_GRID_STEP_METERS; dx = (pos_x - x1) + DIST_OFFSET; if (pos_y < y1) dy = pos_y - y1; else if (pos_y > y2) dy = pos_y - y2; else dy = 0; dist = dx*dx+dy*dy; if (dist < MIN_DIST_SQ) alpha = MAX_ALPHA; else if (dist > MAX_DIST_SQ) alpha = 0.0f; else alpha = 30/dist; alpha = llclamp(alpha, 0.0f, MAX_ALPHA); gGL.color4f(1.f, 1.f, 1.f, alpha); if ((pos_x - x1) > 0) direction = WEST_MASK; else direction = EAST_MASK; // avoid Z fighting renderOneSegment(x1+0.1f, y1+0.1f, x2+0.1f, y2+0.1f, collision_height, direction, regionp); } } } gGL.end(); }
void LLViewerParcelMgr::renderHighlightSegments(const U8* segments, LLViewerRegion* regionp) { S32 x, y; F32 x1, y1; // start point F32 x2, y2; // end point bool has_segments = false; LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); gGL.color4f(1.f, 1.f, 0.f, 0.2f); const S32 STRIDE = (mParcelsPerEdge+1); // Cheat and give this the same pick-name as land for (y = 0; y < STRIDE; y++) { for (x = 0; x < STRIDE; x++) { U8 segment_mask = segments[x + y*STRIDE]; if (segment_mask & SOUTH_MASK) { x1 = x * PARCEL_GRID_STEP_METERS; y1 = y * PARCEL_GRID_STEP_METERS; x2 = x1 + PARCEL_GRID_STEP_METERS; y2 = y1; if (!has_segments) { has_segments = true; gGL.begin(LLRender::QUADS); } renderOneSegment(x1, y1, x2, y2, PARCEL_POST_HEIGHT, SOUTH_MASK, regionp); } if (segment_mask & WEST_MASK) { x1 = x * PARCEL_GRID_STEP_METERS; y1 = y * PARCEL_GRID_STEP_METERS; x2 = x1; y2 = y1 + PARCEL_GRID_STEP_METERS; if (!has_segments) { has_segments = true; gGL.begin(LLRender::QUADS); } renderOneSegment(x1, y1, x2, y2, PARCEL_POST_HEIGHT, WEST_MASK, regionp); } } } if (has_segments) { gGL.end(); } }
// Used by lltoolselectland void LLViewerParcelMgr::renderRect(const LLVector3d &west_south_bottom_global, const LLVector3d &east_north_top_global ) { LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLVector3 west_south_bottom_agent = gAgent.getPosAgentFromGlobal(west_south_bottom_global); F32 west = west_south_bottom_agent.mV[VX]; F32 south = west_south_bottom_agent.mV[VY]; // F32 bottom = west_south_bottom_agent.mV[VZ] - 1.f; LLVector3 east_north_top_agent = gAgent.getPosAgentFromGlobal(east_north_top_global); F32 east = east_north_top_agent.mV[VX]; F32 north = east_north_top_agent.mV[VY]; // F32 top = east_north_top_agent.mV[VZ] + 1.f; // HACK: At edge of last region of world, we need to make sure the region // resolves correctly so we can get a height value. const F32 FUDGE = 0.01f; F32 sw_bottom = LLWorld::getInstance()->resolveLandHeightAgent( LLVector3( west, south, 0.f ) ); F32 se_bottom = LLWorld::getInstance()->resolveLandHeightAgent( LLVector3( east-FUDGE, south, 0.f ) ); F32 ne_bottom = LLWorld::getInstance()->resolveLandHeightAgent( LLVector3( east-FUDGE, north-FUDGE, 0.f ) ); F32 nw_bottom = LLWorld::getInstance()->resolveLandHeightAgent( LLVector3( west, north-FUDGE, 0.f ) ); F32 sw_top = sw_bottom + PARCEL_POST_HEIGHT; F32 se_top = se_bottom + PARCEL_POST_HEIGHT; F32 ne_top = ne_bottom + PARCEL_POST_HEIGHT; F32 nw_top = nw_bottom + PARCEL_POST_HEIGHT; LLUI::setLineWidth(2.f); gGL.color4f(1.f, 1.f, 0.f, 1.f); // Cheat and give this the same pick-name as land gGL.begin(LLRender::LINES); gGL.vertex3f(west, north, nw_bottom); gGL.vertex3f(west, north, nw_top); gGL.vertex3f(east, north, ne_bottom); gGL.vertex3f(east, north, ne_top); gGL.vertex3f(east, south, se_bottom); gGL.vertex3f(east, south, se_top); gGL.vertex3f(west, south, sw_bottom); gGL.vertex3f(west, south, sw_top); gGL.end(); gGL.color4f(1.f, 1.f, 0.f, 0.2f); gGL.begin(LLRender::QUADS); gGL.vertex3f(west, north, nw_bottom); gGL.vertex3f(west, north, nw_top); gGL.vertex3f(east, north, ne_top); gGL.vertex3f(east, north, ne_bottom); gGL.vertex3f(east, north, ne_bottom); gGL.vertex3f(east, north, ne_top); gGL.vertex3f(east, south, se_top); gGL.vertex3f(east, south, se_bottom); gGL.vertex3f(east, south, se_bottom); gGL.vertex3f(east, south, se_top); gGL.vertex3f(west, south, sw_top); gGL.vertex3f(west, south, sw_bottom); gGL.vertex3f(west, south, sw_bottom); gGL.vertex3f(west, south, sw_top); gGL.vertex3f(west, north, nw_top); gGL.vertex3f(west, north, nw_bottom); gGL.end(); LLUI::setLineWidth(1.f); }
// for low end hardware void LLDrawPoolWater::renderOpaqueLegacyWater() { LLVOSky *voskyp = gSky.mVOSkyp; LLGLSLShader* shader = NULL; if (LLGLSLShader::sNoFixedFunction) { if (LLPipeline::sUnderWaterRender) { shader = &gObjectSimpleNonIndexedTexGenWaterProgram; } else { shader = &gObjectSimpleNonIndexedTexGenProgram; } shader->bind(); } stop_glerror(); // Depth sorting and write to depth buffer // since this is opaque, we should see nothing // behind the water. No blending because // of no transparency. And no face culling so // that the underside of the water is also opaque. LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); LLGLDisable no_cull(GL_CULL_FACE); LLGLDisable no_blend(GL_BLEND); gPipeline.disableLights(); //Singu note: This is a hack around bizarre opensim behavior. The opaque water texture we get is pure white and only has one channel. // This behavior is clearly incorrect, so we try to detect that case, purge it from the cache, and try to re-fetch the texture. // If the re-fetched texture is still invalid, or doesn't exist, we use transparent water, which is fine since alphablend is unset. // The current logic for refetching is crude here, and probably wont work if, say, a prim were to also have the texture for some reason, // however it works well enough otherwise, and is much cleaner than diving into LLTextureList, LLViewerFetchedTexture, and LLViewerTexture. // Perhaps a proper reload mechanism could be done if we ever add user-level texture reloading, but until then it's not a huge priority. // Failing to fully refetch will just give us the same invalid texture we started with, which will result in the fallback texture being used. if(mOpaqueWaterImagep != mWaterImagep) { if(mOpaqueWaterImagep->isMissingAsset()) { mOpaqueWaterImagep = mWaterImagep; } else if(mOpaqueWaterImagep->hasGLTexture() && mOpaqueWaterImagep->getComponents() < 3) { LLAppViewer::getTextureCache()->removeFromCache(mOpaqueWaterImagep->getID()); static bool sRefetch = true; if(sRefetch) { sRefetch = false; ((LLViewerFetchedTexture*)mOpaqueWaterImagep.get())->forceRefetch(); } else mOpaqueWaterImagep = mWaterImagep; } } mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); // Activate the texture binding and bind one // texture since all images will have the same texture gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->bind(mOpaqueWaterImagep); // Automatically generate texture coords for water texture if (!shader) { glEnable(GL_TEXTURE_GEN_S); //texture unit 0 glEnable(GL_TEXTURE_GEN_T); //texture unit 0 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } // Use the fact that we know all water faces are the same size // to save some computation // Slowly move texture coordinates over time so the water appears // to be moving. F32 movement_period_secs = 50.f; static const LLCachedControl<bool> freeze_time("FreezeTime",false); static F32 frame_time; if (!freeze_time) frame_time = gFrameTimeSeconds; F32 offset = fmod(frame_time, movement_period_secs); if (movement_period_secs != 0) { offset /= movement_period_secs; } else { offset = 0; } F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset }; F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset }; if (!shader) { glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); } else { shader->uniform4fv("object_plane_s", 1, tp0); shader->uniform4fv("object_plane_t", 1, tp1); } gGL.diffuseColor3f(1.f, 1.f, 1.f); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if (voskyp->isReflFace(face)) { continue; } face->renderIndexed(); } stop_glerror(); if (!shader) { // Reset the settings back to expected values glDisable(GL_TEXTURE_GEN_S); //texture unit 0 glDisable(GL_TEXTURE_GEN_T); //texture unit 0 } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); }
// Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(LLFastTimer::FTM_RENDER); if (LLPipeline::sRenderFrameTest) { send_agent_pause(); } gSnapshot = for_snapshot; LLGLSDefault gls_default; LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); gPipeline.disableLights(); // Don't draw if the window is hidden or minimized. // In fact, must explicitly check the minimized state before drawing. // Attempting to draw into a minimized window causes a GL error. JC if ( !gViewerWindow->getActive() || !gViewerWindow->mWindow->getVisible() || gViewerWindow->mWindow->getMinimized() ) { // Clean up memory the pools may have allocated if (rebuild) { gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); } gViewerWindow->returnEmptyPicks(); return; } gViewerWindow->checkSettings(); { LLFastTimer ftm(LLFastTimer::FTM_PICK); LLAppViewer::instance()->pingMainloopTimeout("Display:Pick"); gViewerWindow->performPick(); } LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); LLGLState::checkStates(); LLGLState::checkTextureChannels(); ////////////////////////////////////////////////////////// // // Logic for forcing window updates if we're in drone mode. // if (gNoRender) { #if LL_WINDOWS static F32 last_update_time = 0.f; if ((gFrameTimeSeconds - last_update_time) > 1.f) { InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); last_update_time = gFrameTimeSeconds; } #elif LL_DARWIN // MBW -- Do something clever here. #endif // Not actually rendering, don't bother. return; } // // Bail out if we're in the startup state and don't want to try to // render the world. // if (LLStartUp::getStartupState() < STATE_STARTED) { LLAppViewer::instance()->pingMainloopTimeout("Display:Startup"); display_startup(); return; } //LLGLState::verify(FALSE); ///////////////////////////////////////////////// // // Update GL Texture statistics (used for discard logic?) // LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats"); gFrameStats.start(LLFrameStats::UPDATE_TEX_STATS); stop_glerror(); LLImageGL::updateStats(gFrameTimeSeconds); LLVOAvatar::sRenderName = gSavedSettings.getS32("RenderName"); LLVOAvatar::sRenderGroupTitles = !gSavedSettings.getBOOL("RenderHideGroupTitleAll"); gPipeline.mBackfaceCull = TRUE; gFrameCount++; gRecentFrameCount++; if (gFocusMgr.getAppHasFocus()) { gForegroundFrameCount++; } ////////////////////////////////////////////////////////// // // Display start screen if we're teleporting, and skip render // if (gTeleportDisplay) { LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. S32 attach_count = 0; if (gAgent.getAvatarObject()) { attach_count = gAgent.getAvatarObject()->getAttachmentCount(); } 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); if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) { // Give up. Don't keep the UI locked forever. gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); gAgent.setTeleportMessage(std::string()); } const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(0); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: // Waiting for source simulator to respond gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_MOVING: // Viewer has received destination location from source simulator gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_START_ARRIVAL: // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator gTeleportArrivalTimer.reset(); gViewerWindow->setProgressCancelButtonVisible(FALSE, std::string("Cancel")); //TODO: Translate gViewerWindow->setProgressPercent(75.f); gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gImageList.mForceResetTextureStats = TRUE; gAgent.resetView(TRUE, TRUE); break; case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); if( arrival_fraction > 1.f ) { arrival_fraction = 1.f; LLFirstUse::useTeleport(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } gViewerWindow->setProgressCancelButtonVisible(FALSE, std::string("Cancel")); //TODO: Translate gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); gViewerWindow->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 ) { LLFirstUse::useTeleport(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } } break; case LLAgent::TELEPORT_NONE: // No teleport in progress gViewerWindow->setShowProgress(FALSE); gTeleportDisplay = FALSE; break; default: break; } } else if(LLAppViewer::instance()->logoutRequestSent()) { LLAppViewer::instance()->pingMainloopTimeout("Display:Logout"); F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; if (percent_done > 100.f) { percent_done = 100.f; } if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } else if (gRestoreGL) { LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL"); F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; if( percent_done > 100.f ) { gViewerWindow->setShowProgress(FALSE); gRestoreGL = FALSE; } else { if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } } ////////////////////////// // // Prepare for the next frame // ///////////////////////////// // // Update the camera // // LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); ////////////////////////// // // clear the next buffer // (must follow dynamic texture writing since that uses the frame buffer) // if (gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected"); render_ui(); render_disconnected_background(); } ////////////////////////// // // Set rendering options // // LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup"); stop_glerror(); /////////////////////////////////////// // // Slam lighting parameters back to our defaults. // Note that these are not the same as GL defaults... stop_glerror(); F32 one[4] = {1.f, 1.f, 1.f, 1.f}; glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one); stop_glerror(); ///////////////////////////////////// // // 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)) { LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); LLFastTimer t(LLFastTimer::FTM_UPDATE_TEXTURES); if (LLDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); glClear(GL_DEPTH_BUFFER_BIT); } } gViewerWindow->setupViewport(); gPipeline.resetFrameStats(); // Reset per-frame statistics. if (!gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { //don't draw hud objects in this frame gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); } if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES)) { //don't draw hud particles in this frame gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); } //upkeep gl name pools LLGLNamePool::upkeepPools(); stop_glerror(); display_update_camera(); stop_glerror(); // *TODO: merge these two methods LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); stop_glerror(); gFrameStats.start(LLFrameStats::UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); gPipeline.updateGeom(max_geom_update_time); stop_glerror(); gFrameStats.start(LLFrameStats::UPDATE_CULL); S32 water_clip = 0; if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER))) { if (LLViewerCamera::getInstance()->cameraUnderWater()) { water_clip = -1; } else { water_clip = 1; } } LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); //Increment drawable frame counter LLDrawable::incrementVisible(); LLSpatialGroup::sNoDelete = TRUE; LLPipeline::sUseOcclusion = (!gUseWireframe && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) { //force occlusion on for all render types if doing deferred render LLPipeline::sUseOcclusion = 3; } LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha"); LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state LLPipeline::sUseOcclusion = llmin(occlusion, 1); } gDepthDirty = FALSE; LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); static LLCullResult result; gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); BOOL to_texture = !for_snapshot && gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); { { LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); LLVertexBuffer::clientCopy(0.016); } if (gResizeScreenTexture) { gResizeScreenTexture = FALSE; gPipeline.resizeScreenTexture(); } gGL.setColorMask(true, true); glClearColor(0,0,0,0); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); 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(*LLViewerCamera::getInstance()); } LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); glh::matrix4f proj = glh_get_current_projection(); glh::matrix4f mod = glh_get_current_modelview(); glViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; LLVOAvatar::updateImpostors(); glh_set_current_projection(proj); glh_set_current_modelview(mod); glMatrixMode(GL_PROJECTION); glLoadMatrixf(proj.m); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(mod.m); gViewerWindow->setupViewport(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); } glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!for_snapshot) { LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); } ////////////////////////////////////// // // Update images, using the image stats generated during object update/culling // // Can put objects onto the retextured list. // // Doing this here gives hardware occlusion queries extra time to complete LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); LLError::LLCallStacks::clear() ; llpushcallstacks ; gFrameStats.start(LLFrameStats::IMAGE_UPDATE); { LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE); LLViewerImage::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); gBumpImageList.updateImages(); // must be called before gImageList version so that it's textures are thrown out first. F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time max_image_decode_time = llclamp(max_image_decode_time, 0.001f, 0.005f ); // min 1ms/frame, max 5ms/frame) gImageList.updateImages(max_image_decode_time); stop_glerror(); } llpushcallstacks ; /////////////////////////////////// // // 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. // LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); { gFrameStats.start(LLFrameStats::STATE_SORT); gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); if (rebuild) { ////////////////////////////////////// // // rebuildPools // // gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); stop_glerror(); } } LLPipeline::sUseOcclusion = occlusion; { LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); LLFastTimer t(LLFastTimer::FTM_UPDATE_SKY); gSky.updateSky(); } if(gUseWireframe) { glClearColor(0.5f, 0.5f, 0.5f, 0.f); glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); //// render frontmost floater opaque for occlusion culling purposes //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); //// assumes frontmost floater with focus is opaque //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) //{ // glMatrixMode(GL_MODELVIEW); // glPushMatrix(); // { // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); // glLoadIdentity(); // LLRect floater_rect = frontmost_floaterp->getScreenRect(); // // deflate by one pixel so rounding errors don't occlude outside of floater extents // floater_rect.stretch(-1); // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidth(), // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeight(), // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidth(), // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeight()); // floater_3d_rect.translate(-0.5f, -0.5f); // glTranslatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear()); // glScalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f); // gGL.color4fv(LLColor4::white.mV); // gGL.begin(LLVertexBuffer::QUADS); // { // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); // } // gGL.end(); // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // } // glPopMatrix(); //} LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; LLPipeline::updateRenderDeferred(); stop_glerror(); if (to_texture) { gGL.setColorMask(true, true); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.bindTarget(); gPipeline.mDeferredScreen.clear(); } else { gPipeline.mScreen.bindTarget(); gPipeline.mScreen.clear(); } gGL.setColorMask(true, false); } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom"); if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) && !gRestoreGL) { gGL.setColorMask(true, false); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); } else { gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); } gGL.setColorMask(true, true); //store this frame's modelview matrix for use //when rendering next frame's occlusion queries for (U32 i = 0; i < 16; i++) { gGLLastModelView[i] = gGLModelView[i]; } stop_glerror(); } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) { if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.flush(); } else { gPipeline.mScreen.flush(); } } /// We copy the frame buffer straight into a texture here, /// and then display it again with compositor effects. /// Using render to texture would be faster/better, but I don't have a /// grasp of their full display stack just yet. // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.renderDeferredLighting(); } LLPipeline::sUnderWaterRender = FALSE; LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); if (!for_snapshot) { gFrameStats.start(LLFrameStats::RENDER_UI); render_ui(); } LLSpatialGroup::sNoDelete = FALSE; } LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); gFrameStats.start(LLFrameStats::MISC_END); stop_glerror(); if (LLPipeline::sRenderFrameTest) { send_agent_resume(); LLPipeline::sRenderFrameTest = FALSE; } display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); }
//-------------------------------------------------------------------- // render() //-------------------------------------------------------------------- U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) { stop_glerror(); U32 triangle_count = 0; //---------------------------------------------------------------- // ignore invisible objects //---------------------------------------------------------------- if ( mValid ) { //---------------------------------------------------------------- // if object is transparent, defer it, otherwise // give the joint subclass a chance to draw itself //---------------------------------------------------------------- if ( is_dummy ) { triangle_count += drawShape( pixelArea, first_pass, is_dummy ); } else if (LLPipeline::sShadowRender) { triangle_count += drawShape(pixelArea, first_pass, is_dummy ); } else if ( isTransparent() && !LLPipeline::sReflectionRender) { // Hair and Skirt if ((pixelArea > MIN_PIXEL_AREA_3PASS_HAIR)) { // render all three passes LLGLDisable cull(GL_CULL_FACE); // first pass renders without writing to the z buffer { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); triangle_count += drawShape( pixelArea, first_pass, is_dummy ); } // second pass writes to z buffer only gGL.setColorMask(false, false); { triangle_count += drawShape( pixelArea, FALSE, is_dummy ); } // third past respects z buffer and writes color gGL.setColorMask(true, false); { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); triangle_count += drawShape( pixelArea, FALSE, is_dummy ); } } else { // Render Inside (no Z buffer write) glCullFace(GL_FRONT); { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); triangle_count += drawShape( pixelArea, first_pass, is_dummy ); } // Render Outside (write to the Z buffer) glCullFace(GL_BACK); { triangle_count += drawShape( pixelArea, FALSE, is_dummy ); } } } else { // set up render state triangle_count += drawShape( pixelArea, first_pass ); } } //---------------------------------------------------------------- // render children //---------------------------------------------------------------- for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); ++iter) { LLViewerJoint* joint = (LLViewerJoint*)(*iter); F32 jointLOD = joint->getLOD(); if (pixelArea >= jointLOD || sDisableLOD) { triangle_count += joint->render( pixelArea, TRUE, is_dummy ); if (jointLOD != DEFAULT_LOD) { break; } } } return triangle_count; }
//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- BOOL LLPreviewAnimation::render() { mNeedsUpdate = FALSE; LLVOAvatar* avatarp = mDummyAvatar; gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); gGL.loadIdentity(); gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); gGL.loadIdentity(); if (LLGLSLShader::sNoFixedFunction) { gUIProgram.bind(); } LLGLSUIDefault def; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); gl_rect_2d_simple( mFullWidth, mFullHeight ); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); gGL.flush(); LLVector3 target_pos = avatarp->mRoot.getWorldPosition(); LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * LLQuaternion(mCameraYaw, LLVector3::z_axis); LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot; LLViewerCamera::getInstance()->setOriginAndLookAt( target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera LLVector3::z_axis, // up target_pos + (mCameraOffset * av_rot) ); // point of interest LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); mCameraRelPos = LLViewerCamera::getInstance()->getOrigin() - avatarp->mHeadp->getWorldPosition(); //avatarp->setAnimationData("LookAtPoint", (void *)&mCameraRelPos); //SJB: Animation is updated in LLVOAvatar::updateCharacter if (avatarp->mDrawable.notNull()) { avatarp->updateLOD(); LLVertexBuffer::unbind(); LLGLDepthTest gls_depth(GL_TRUE); LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); avatarp->dirtyMesh(); avatarPoolp->renderAvatars(avatarp); // renders only one avatar } gGL.color4f(1,1,1,1); return TRUE; }
//----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- BOOL LLVisualParamHint::render() { LLVisualParamReset::sDirty = TRUE; LLVOAvatar* avatarp = gAgent.getAvatarObject(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); LLGLSUIDefault gls_ui; //LLGLState::verify(TRUE); mBackgroundp->draw(0, 0, mWidth, mHeight); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); mNeedsUpdate = FALSE; mIsVisible = TRUE; LLViewerJointMesh* cam_target_joint = NULL; const std::string& cam_target_mesh_name = mVisualParam->getCameraTargetName(); if( !cam_target_mesh_name.empty() ) { cam_target_joint = (LLViewerJointMesh*)avatarp->getJoint( cam_target_mesh_name ); } if( !cam_target_joint ) { cam_target_joint = (LLViewerJointMesh*)gMorphView->getCameraTargetJoint(); } if( !cam_target_joint ) { cam_target_joint = (LLViewerJointMesh*)avatarp->getJoint("mHead"); } LLQuaternion avatar_rotation; LLJoint* root_joint = avatarp->getRootJoint(); if( root_joint ) { avatar_rotation = root_joint->getWorldRotation(); } LLVector3 target_joint_pos = cam_target_joint->getWorldPosition(); LLVector3 target_offset( 0, 0, mVisualParam->getCameraElevation() ); LLVector3 target_pos = target_joint_pos + (target_offset * avatar_rotation); F32 cam_angle_radians = mVisualParam->getCameraAngle() * DEG_TO_RAD; LLVector3 camera_snapshot_offset( mVisualParam->getCameraDistance() * cosf( cam_angle_radians ), mVisualParam->getCameraDistance() * sinf( cam_angle_radians ), mVisualParam->getCameraElevation() ); LLVector3 camera_pos = target_joint_pos + (camera_snapshot_offset * avatar_rotation); gGL.flush(); LLViewerCamera::getInstance()->setAspect((F32)mWidth / (F32)mHeight); LLViewerCamera::getInstance()->setOriginAndLookAt( camera_pos, // camera LLVector3(0.f, 0.f, 1.f), // up target_pos ); // point of interest LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE); if (avatarp->mDrawable.notNull()) { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); gGL.setAlphaRejectSettings(LLRender::CF_ALWAYS); gGL.setSceneBlendType(LLRender::BT_REPLACE); avatarPoolp->renderAvatars(avatarp); // renders only one avatar gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight); gGL.color4f(1,1,1,1); mTexture->setGLTextureCreated(true); return TRUE; }
//----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::render() { if (gSavedSettings.getBOOL("EmeraldDontShowMyLookAt") && (gAgent.getAvatarObject() == ((LLVOAvatar*)(LLViewerObject*)mSourceObject))) return; if (sDebugLookAt && mSourceObject.notNull()) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLVector3 target = mTargetPos + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->mHeadp->getWorldPosition(); glMatrixMode(GL_MODELVIEW); gGL.pushMatrix(); gGL.translatef(target.mV[VX], target.mV[VY], target.mV[VZ]); glScalef(0.3f, 0.3f, 0.3f); gGL.begin(LLRender::LINES); { LLColor3 color = (*mAttentions)[mTargetType].mColor; gGL.color3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]); gGL.vertex3f(-1.f, 0.f, 0.f); gGL.vertex3f(1.f, 0.f, 0.f); gGL.vertex3f(0.f, -1.f, 0.f); gGL.vertex3f(0.f, 1.f, 0.f); gGL.vertex3f(0.f, 0.f, -1.f); gGL.vertex3f(0.f, 0.f, 1.f); } gGL.end(); gGL.popMatrix(); if( gSavedSettings.getBOOL("EmeraldShowLookAtNames") ) { //const LLFontGL* fontp = LLFontGL::sSansSerifSmall; const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); LLGLEnable color_mat(GL_COLOR_MATERIAL); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLState gls_blend(GL_BLEND, TRUE); LLGLState gls_alpha(GL_ALPHA_TEST, TRUE); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); // Well.. after that nasty complex try at somehow getting it to work initialising all sorts of stuff // It seems to work and fix the previous bug of merely displaying untextured cubes, // probably due to the helpful getTexUnit->enable. - Nexii glMatrixMode(GL_MODELVIEW); glPushMatrix(); LLVector3 render_pos = target + LLVector3( 0.f, 0.f, 0.25f ); LLColor4 Color = LLColor4( (*mAttentions)[mTargetType].mColor, 1.0f ); std::string text = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->getFullname(); // [RLVa:KB] - Alternate: Emerald-370 // Show anonyms in place of actual names when @shownames=n restricted if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { text = RlvStrings::getAnonym(text); } // [/RLVa:KB] // render shadow first // gViewerWindow->setupViewport(1, -1); // hud_render_utf8text(text, render_pos, *fontp, LLFontGL::NORMAL, -0.5f * fontp->getWidthF32(text), 3.f, LLColor4( 0.f, 0.f, 0.f, 0.5f ), FALSE ); gViewerWindow->setupViewport(); hud_render_utf8text(text, render_pos, *fontp, LLFontGL::NORMAL, -0.5f * fontp->getWidthF32(text), 3.f, Color, FALSE ); glPopMatrix(); } } }
void LLHUDNameTag::renderText(BOOL for_select) { if (!mVisible || mHidden) { return; } // don't pick text that isn't bound to a viewerobject if (for_select && (!mSourceObject || mSourceObject->mDrawable.isNull())) { return; } if (for_select) { gGL.getTexUnit(0)->disable(); } else { gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); } LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE); LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE); LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f); F32 alpha_factor = 1.f; LLColor4 text_color = mColor; if (mDoFade) { if (mLastDistance > mFadeDistance) { alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange); text_color.mV[3] = text_color.mV[3]*alpha_factor; } } if (text_color.mV[3] < 0.01f) { return; } shadow_color.mV[3] = text_color.mV[3]; mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); // *TODO: cache this image // <FS:Ansariel> Performance improvement //LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Rect"); // *TODO: make this a per-text setting //LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground"); //bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); static LLUIColor s_bg_color = LLUIColorTable::instance().getColor("NameTagBackground"); static LLCachedControl<F32> chatBubbleOpacity(gSavedSettings, "ChatBubbleOpacity"); LLColor4 bg_color = s_bg_color.get(); F32 color_alpha = chatBubbleOpacity * alpha_factor; bg_color.setAlpha(color_alpha); // </FS:Ansariel> // scale screen size of borders down //RN: for now, text on hud objects is never occluded LLVector3 x_pixel_vec; LLVector3 y_pixel_vec; LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); LLVector3 width_vec = mWidth * x_pixel_vec; LLVector3 height_vec = mHeight * y_pixel_vec; mRadius = (width_vec + height_vec).magVec() * 0.5f; LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLRect screen_rect; screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); // <FS:Ansariel> Performance improvement //imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); mRoundedRectImg->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); // </FS:Ansariel> if (mLabelSegments.size()) { // <FS:Ansariel> Performance improvement //LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); LLRect label_top_rect = screen_rect; const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); label_top_rect.mBottom = label_top_rect.mTop - label_height; LLColor4 label_top_color = text_color; // <FS:Ansariel> Performance improvement //label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; label_top_color.mV[VALPHA] = color_alpha; // </FS:Ansariel> // <FS:Ansariel> Performance improvement //rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); mRoundedRectTopImg->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); // </FS:Ansariel> } F32 y_offset = (F32)mOffsetY; // Render label { //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin(); segment_iter != mLabelSegments.end(); ++segment_iter ) { // Label segments use default font const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp; y_offset -= fontp->getLineHeight(); F32 x_offset; if (mTextAlignment == ALIGN_TEXT_CENTER) { x_offset = -0.5f*segment_iter->getWidth(fontp); } else // ALIGN_LEFT { x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f); } LLColor4 label_color(0.f, 0.f, 0.f, 1.f); label_color.mV[VALPHA] = alpha_factor; hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, FALSE); } } // Render text { // -1 mMaxLines means unlimited lines. S32 start_segment; S32 max_lines = getMaxLines(); if (max_lines < 0) { start_segment = 0; } else { start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines); } for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment; segment_iter != mTextSegments.end(); ++segment_iter ) { const LLFontGL* fontp = segment_iter->mFont; y_offset -= fontp->getLineHeight(); y_offset -= LINE_PADDING; U8 style = segment_iter->mStyle; LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW; F32 x_offset; if (mTextAlignment== ALIGN_TEXT_CENTER) { x_offset = -0.5f*segment_iter->getWidth(fontp); } else // ALIGN_LEFT { x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f); // *HACK x_offset += 1; } text_color = segment_iter->mColor; text_color.mV[VALPHA] *= alpha_factor; hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, FALSE); } } /// Reset the default color to white. The renderer expects this to be the default. gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f); if (for_select) { gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); } }
void LLDrawPoolSky::render(S32 pass) { gGL.flush(); if (mDrawFace.empty()) { return; } // Don't draw the sky box if we can and are rendering the WL sky dome. if (gPipeline.canUseWindLightShaders()) { return; } // don't render sky under water (background just gets cleared to fog color) if(mVertexShaderLevel > 0 && LLPipeline::sUnderWaterRender) { return; } if (LLGLSLShader::sNoFixedFunction) { //just use the UI shader (generic single texture no lighting) gOneTextureNoColorProgram.bind(); } else { // don't use shaders! if (gGLManager.mHasShaderObjects) { // Ironically, we must support shader objects to be // able to use this call. LLGLSLShader::bindNoShader(); } mShader = NULL; } LLGLSPipelineSkyBox gls_skybox; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLSquashToFarClip far_clip(glh_get_current_projection()); LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0); gPipeline.disableLights(); LLGLDisable clip(GL_CLIP_PLANE0); gGL.pushMatrix(); LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); S32 face_count = (S32)mDrawFace.size(); LLVertexBuffer::unbind(); gGL.diffuseColor4f(1,1,1,1); for (S32 i = 0; i < llmin(6, face_count); ++i) { renderSkyCubeFace(i); } gGL.popMatrix(); }
// for low end hardware void LLDrawPoolWater::renderOpaqueLegacyWater() { LLVOSky *voskyp = gSky.mVOSkyp; stop_glerror(); // Depth sorting and write to depth buffer // since this is opaque, we should see nothing // behind the water. No blending because // of no transparency. And no face culling so // that the underside of the water is also opaque. LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); LLGLDisable no_cull(GL_CULL_FACE); LLGLDisable no_blend(GL_BLEND); gPipeline.disableLights(); mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); // Activate the texture binding and bind one // texture since all images will have the same texture gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->bind(mOpaqueWaterImagep); // Automatically generate texture coords for water texture glEnable(GL_TEXTURE_GEN_S); //texture unit 0 glEnable(GL_TEXTURE_GEN_T); //texture unit 0 glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // Use the fact that we know all water faces are the same size // to save some computation // Slowly move texture coordinates over time so the watter appears // to be moving. F32 movement_period_secs = 50.f; F32 offset = fmod(gFrameTimeSeconds, movement_period_secs); if (movement_period_secs != 0) { offset /= movement_period_secs; } else { offset = 0; } F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset }; F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset }; glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); glColor3f(1.f, 1.f, 1.f); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if (voskyp->isReflFace(face)) { continue; } face->renderIndexed(); } stop_glerror(); // Reset the settings back to expected values glDisable(GL_TEXTURE_GEN_S); //texture unit 0 glDisable(GL_TEXTURE_GEN_T); //texture unit 0 gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); }
// static void LLTracker::renderBeacon(LLVector3d pos_global, const LLColor4& color, LLHUDText* hud_textp, const std::string& label ) { sCheesyBeacon = gSavedSettings.getBOOL("CheesyBeacon"); LLVector3d to_vec = pos_global - gAgent.getCameraPositionGlobal(); F32 dist = (F32)to_vec.magVec(); F32 color_frac = 1.f; if (dist > 0.99f * LLViewerCamera::getInstance()->getFar()) { color_frac = 0.4f; // pos_global = gAgent.getCameraPositionGlobal() + 0.99f*(LLViewerCamera::getInstance()->getFar()/dist)*to_vec; } else { color_frac = 1.f - 0.6f*(dist/LLViewerCamera::getInstance()->getFar()); } LLColor4 fogged_color = color_frac * color + (1 - color_frac)*gSky.getFogColor(); F32 FADE_DIST = 3.f; fogged_color.mV[3] = llmax(0.2f, llmin(0.5f,(dist-FADE_DIST)/FADE_DIST)); LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(pos_global); LLGLSTracker gls_tracker; // default - TEXTURE + CULL_FACE + LIGHTING + GL_BLEND + GL_ALPHA_TEST LLGLDisable cull_face(GL_CULL_FACE); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]); draw_shockwave(1024.f, gRenderStartTime.getElapsedTimeF32(), 32, fogged_color); gGL.color4fv(fogged_color.mV); const U32 BEACON_VERTS = 256; const F32 step = 1024.0f/BEACON_VERTS; LLVector3 x_axis = LLViewerCamera::getInstance()->getLeftAxis(); F32 t = gRenderStartTime.getElapsedTimeF32(); F32 dr = dist/LLViewerCamera::getInstance()->getFar(); for (U32 i = 0; i < BEACON_VERTS; i++) { F32 x = x_axis.mV[0]; F32 y = x_axis.mV[1]; F32 z = i * step; F32 z_next = (i+1)*step; F32 a = pulse_func(t, z); F32 an = pulse_func(t, z_next); LLColor4 c_col = fogged_color + LLColor4(a,a,a,a); LLColor4 col_next = fogged_color + LLColor4(an,an,an,an); LLColor4 col_edge = fogged_color * LLColor4(a,a,a,0.0f); LLColor4 col_edge_next = fogged_color * LLColor4(an,an,an,0.0f); a *= 2.f; a += 1.0f+dr; an *= 2.f; an += 1.0f+dr; gGL.begin(LLVertexBuffer::TRIANGLE_STRIP); gGL.color4fv(col_edge.mV); gGL.vertex3f(-x*a, -y*a, z); gGL.color4fv(col_edge_next.mV); gGL.vertex3f(-x*an, -y*an, z_next); gGL.color4fv(c_col.mV); gGL.vertex3f(0, 0, z); gGL.color4fv(col_next.mV); gGL.vertex3f(0, 0, z_next); gGL.color4fv(col_edge.mV); gGL.vertex3f(x*a,y*a,z); gGL.color4fv(col_edge_next.mV); gGL.vertex3f(x*an,y*an,z_next); gGL.end(); } //gCylinder.render(1000); glPopMatrix(); std::string text; text = llformat( "%.0f m", to_vec.magVec()); LLWString wstr; wstr += utf8str_to_wstring(label); wstr += '\n'; wstr += utf8str_to_wstring(text); hud_textp->setFont(LLFontGL::sSansSerif); hud_textp->setZCompare(FALSE); hud_textp->setColor(LLColor4(1.f, 1.f, 1.f, llmax(0.2f, llmin(1.f,(dist-FADE_DIST)/FADE_DIST)))); hud_textp->setString(wstr); hud_textp->setVertAlignment(LLHUDText::ALIGN_VERT_CENTER); hud_textp->setPositionAgent(pos_agent); }
// Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield) { LLFastTimer t(LLFastTimer::FTM_RENDER); LLGLSDefault gls_default; LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); // No clue where this is getting unset, but safe enough to reset it here. LLGLState::resetTextureStates(); #ifndef LL_RELEASE_FOR_DOWNLOAD LLGLState::checkStates(); LLGLState::checkTextureChannels(); #endif gPipeline.disableLights(); // Don't draw if the window is hidden or minimized. // In fact, must explicitly check the minimized state before drawing. // Attempting to draw into a minimized window causes a GL error. JC if ( !gViewerWindow->getActive() || !gViewerWindow->mWindow->getVisible() || gViewerWindow->mWindow->getMinimized() ) { // Clean up memory the pools may have allocated if (rebuild) { gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); } return; } gViewerWindow->checkSettings(); gViewerWindow->performPick(); #ifndef LL_RELEASE_FOR_DOWNLOAD LLGLState::checkStates(); LLGLState::checkTextureChannels(); #endif ////////////////////////////////////////////////////////// // // Logic for forcing window updates if we're in drone mode. // if (gNoRender) { #if LL_WINDOWS static F32 last_update_time = 0.f; if ((gFrameTimeSeconds - last_update_time) > 1.f) { InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); last_update_time = gFrameTimeSeconds; } #elif LL_DARWIN // MBW -- Do something clever here. #endif // Not actually rendering, don't bother. return; } // // Bail out if we're in the startup state and don't want to try to // render the world. // if (LLStartUp::getStartupState() < STATE_STARTED) { display_startup(); return; } //LLGLState::verify(FALSE); ///////////////////////////////////////////////// // // Update GL Texture statistics (used for discard logic?) // gFrameStats.start(LLFrameStats::UPDATE_TEX_STATS); stop_glerror(); LLImageGL::updateStats(gFrameTimeSeconds); LLVOAvatar::sRenderName = gSavedSettings.getS32("RenderName"); LLVOAvatar::sRenderGroupTitles = gSavedSettings.getBOOL("RenderGroupTitleAll"); gPipeline.mBackfaceCull = TRUE; gFrameCount++; if (gFocusMgr.getAppHasFocus()) { gForegroundFrameCount++; } ////////////////////////////////////////////////////////// // // Display start screen if we're teleporting, and skip render // if (gTeleportDisplay) { const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. S32 attach_count = 0; if (gAgent.getAvatarObject()) { attach_count = gAgent.getAvatarObject()->getAttachmentCount(); } 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); if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) { // Give up. Don't keep the UI locked forever. gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); gAgent.setTeleportMessage(""); } const LLString& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(0); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: // Waiting for source simulator to respond gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_MOVING: // Viewer has received destination location from source simulator gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_START_ARRIVAL: // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator gTeleportArrivalTimer.reset(); gViewerWindow->setProgressCancelButtonVisible(FALSE, "Cancel"); gViewerWindow->setProgressPercent(75.f); gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gImageList.mForceResetTextureStats = TRUE; break; case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); if( arrival_fraction > 1.f ) { arrival_fraction = 1.f; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } gViewerWindow->setProgressCancelButtonVisible(FALSE, "Cancel"); gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); gViewerWindow->setProgressString(message); } break; case LLAgent::TELEPORT_NONE: // No teleport in progress gViewerWindow->setShowProgress(FALSE); gTeleportDisplay = FALSE; break; } } else if(LLAppViewer::instance()->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; } gViewerWindow->setProgressPercent( percent_done ); } else if (gRestoreGL) { F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; if( percent_done > 100.f ) { gViewerWindow->setShowProgress(FALSE); gRestoreGL = FALSE; } else { if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } } ////////////////////////// // // Prepare for the next frame // // Hmm... Should this be moved elsewhere? - djs 09/09/02 // do render-to-texture stuff here if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) { // LLFastTimer t(LLFastTimer::FTM_UPDATE_TEXTURES); if (LLDynamicTexture::updateAllInstances()) { glClear(GL_COLOR_BUFFER_BIT); } } ///////////////////////////// // // Update the camera // // gCamera->setZoomParameters(zoom_factor, subfield); gCamera->setNear(MIN_NEAR_PLANE); ////////////////////////// // // clear the next buffer // (must follow dynamic texture writing since that uses the frame buffer) // if (gDisconnected) { glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); render_disconnected_background(); } else if (!gViewerWindow->isPickPending()) { glClear( GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); //DEBUG TEMPORARY glClear(GL_COLOR_BUFFER_BIT); } gViewerWindow->setupViewport(); ////////////////////////// // // Set rendering options // // stop_glerror(); if (gSavedSettings.getBOOL("ShowDepthBuffer")) { pre_show_depth_buffer(); } //MK if ((!RRenabled || !gAgent.mRRInterface.mContainsDetach) && gUseWireframe) //mk { glClearColor(0.5f, 0.5f, 0.5f, 0.f); glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); LLPipeline::sUseOcclusion = FALSE; } else { LLPipeline::sUseOcclusion = gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery && gFeatureManagerp->isFeatureAvailable("UseOcclusion"); } stop_glerror(); /////////////////////////////////////// // // Slam lighting parameters back to our defaults. // Note that these are not the same as GL defaults... stop_glerror(); F32 one[4] = {1.f, 1.f, 1.f, 1.f}; glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one); stop_glerror(); //Increment drawable frame counter LLDrawable::incrementVisible(); ///////////////////////////////////// // // Render // // Actually push all of our triangles to the screen. // if (!gDisconnected) { if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { //don't draw hud objects in this frame gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); } LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE); stop_glerror(); display_update_camera(); stop_glerror(); // *TODO: merge these two methods gHUDManager->updateEffects(); LLHUDObject::updateAll(); stop_glerror(); gFrameStats.start(LLFrameStats::UPDATE_GEOM); const F32 max_geom_update_time = 0.005f; // 5 ms update time gPipeline.updateGeom(max_geom_update_time); stop_glerror(); LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME); part->processImagery(gCamera); display_update_camera(); gFrameStats.start(LLFrameStats::UPDATE_CULL); gPipeline.updateCull(*gCamera); stop_glerror(); /////////////////////////////////// // // 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. // { LLFastTimer t(LLFastTimer::FTM_REBUILD); gFrameStats.start(LLFrameStats::STATE_SORT); gPipeline.stateSort(*gCamera); stop_glerror(); if (rebuild) { ////////////////////////////////////// // // rebuildPools // // gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); stop_glerror(); } } } //// render frontmost floater opaque for occlusion culling purposes //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); //// assumes frontmost floater with focus is opaque //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) //{ // glMatrixMode(GL_MODELVIEW); // glPushMatrix(); // { // LLGLSNoTexture gls_no_texture; // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); // glLoadIdentity(); // LLRect floater_rect = frontmost_floaterp->getScreenRect(); // // deflate by one pixel so rounding errors don't occlude outside of floater extents // floater_rect.stretch(-1); // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidth(), // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeight(), // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidth(), // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeight()); // floater_3d_rect.translate(-0.5f, -0.5f); // glTranslatef(0.f, 0.f, -gCamera->getNear()); // glScalef(gCamera->getNear() * gCamera->getAspect() / sinf(gCamera->getView()), gCamera->getNear() / sinf(gCamera->getView()), 1.f); // glColor4fv(LLColor4::white.mV); // glBegin(GL_QUADS); // { // glVertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); // glVertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); // glVertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); // glVertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); // } // glEnd(); // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // } // glPopMatrix(); //} if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) && !gRestoreGL && !gDisconnected) { gPipeline.renderGeom(*gCamera); stop_glerror(); } //render hud attachments glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE)) { LLCamera hud_cam = *gCamera; glClear(GL_DEPTH_BUFFER_BIT); LLVector3 origin = hud_cam.getOrigin(); hud_cam.setOrigin(-1.f,0,0); hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); //only render hud objects U32 mask = gPipeline.getRenderTypeMask(); gPipeline.setRenderTypeMask(0); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); BOOL has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); if (has_ui) { gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); } BOOL use_occlusion = gSavedSettings.getBOOL("UseOcclusion"); gSavedSettings.setBOOL("UseOcclusion", FALSE); //cull, sort, and render hud objects gPipeline.updateCull(hud_cam); gPipeline.toggleRenderType(LLDrawPool::POOL_ALPHA_POST_WATER); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); { LLFastTimer ftm(LLFastTimer::FTM_REBUILD); gPipeline.stateSort(hud_cam); } gPipeline.renderGeom(hud_cam); //restore type mask gPipeline.setRenderTypeMask(mask); if (has_ui) { gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); } gSavedSettings.setBOOL("UseOcclusion", use_occlusion); } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); gFrameStats.start(LLFrameStats::RENDER_UI); if (gHandleKeysAsync) { process_keystrokes_async(); stop_glerror(); } #ifndef LL_RELEASE_FOR_DOWNLOAD LLGLState::checkStates(); #endif render_ui_and_swap(); #ifndef LL_RELEASE_FOR_DOWNLOAD LLGLState::checkStates(); #endif gFrameStats.start(LLFrameStats::MISC_END); stop_glerror(); }
//----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::render() { static const LLCachedControl<bool> private_look_at("PrivateLookAt",false); static const LLCachedControl<bool> show_look_at("AscentShowLookAt", false); if (private_look_at && (gAgent.getAvatarObject() == ((LLVOAvatar*)(LLViewerObject*)mSourceObject))) return; if (show_look_at && mSourceObject.notNull()) { LLGLDepthTest gls_depth(GL_TRUE,GL_FALSE); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLVector3 target = mTargetPos + ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->mHeadp->getWorldPosition(); glMatrixMode(GL_MODELVIEW); gGL.pushMatrix(); gGL.translatef(target.mV[VX], target.mV[VY], target.mV[VZ]); glScalef(0.3f, 0.3f, 0.3f); gGL.begin(LLRender::LINES); { LLColor3 color = (*mAttentions)[mTargetType].mColor; gGL.color3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]); gGL.vertex3f(-1.f, 0.f, 0.f); gGL.vertex3f(1.f, 0.f, 0.f); gGL.vertex3f(0.f, -1.f, 0.f); gGL.vertex3f(0.f, 1.f, 0.f); gGL.vertex3f(0.f, 0.f, -1.f); gGL.vertex3f(0.f, 0.f, 1.f); } gGL.end(); gGL.popMatrix(); // <edit> const std::string text = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->getFullname(); LLVector3 offset = gAgent.getCameraPositionAgent() - target; offset.normalize(); LLVector3 shadow_offset = offset * 0.49f; offset *= 0.5f; const LLFontGL* font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF); LLGLEnable gl_blend(GL_BLEND); glPushMatrix(); gViewerWindow->setupViewport(); hud_render_utf8text(text, target + shadow_offset, *font, LLFontGL::NORMAL, -0.5f * font->getWidthF32(text) + 2.0f, -2.0f, LLColor4::black, FALSE); hud_render_utf8text(text, target + offset, *font, LLFontGL::NORMAL, -0.5f * font->getWidthF32(text), 0.0f, (*mAttentions)[mTargetType].mColor, FALSE); glPopMatrix(); // </edit> } }
void LLDrawPoolWater::render(S32 pass) { LLFastTimer ftm(FTM_RENDER_WATER); if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) { return; } //do a quick 'n dirty depth sort for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace* facep = *iter; facep->mDistance = -facep->mCenterLocal.mV[2]; } std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); LLGLEnable blend(GL_BLEND); if ((mVertexShaderLevel > 0) && !sSkipScreenCopy) { shade(); return; } LLVOSky *voskyp = gSky.mVOSkyp; stop_glerror(); if (!gGLManager.mHasMultitexture) { // Ack! No multitexture! Bail! return; } LLFace* refl_face = voskyp->getReflFace(); gPipeline.disableLights(); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLDisable cullFace(GL_CULL_FACE); // Set up second pass first mWaterImagep->addTextureStats(1024.f*1024.f); gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->bind(mWaterImagep) ; LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); F32 up_dot = camera_up * LLVector3::z_axis; LLColor4 water_color; if (LLViewerCamera::getInstance()->cameraUnderWater()) { water_color.setVec(1.f, 1.f, 1.f, 0.4f); } else { water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); } glColor4fv(water_color.mV); // Automatically generate texture coords for detail map glEnable(GL_TEXTURE_GEN_S); //texture unit 1 glEnable(GL_TEXTURE_GEN_T); //texture unit 1 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // Slowly move over time. F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); gGL.getTexUnit(0)->activate(); glClearStencil(1); glClear(GL_STENCIL_BUFFER_BIT); LLGLEnable gls_stencil(GL_STENCIL_TEST); glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if (voskyp->isReflFace(face)) { continue; } gGL.getTexUnit(0)->bind(face->getTexture()); face->renderIndexed(); } // Now, disable texture coord generation on texture state 1 gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->disable(); glDisable(GL_TEXTURE_GEN_S); //texture unit 1 glDisable(GL_TEXTURE_GEN_T); //texture unit 1 // Disable texture coordinate and color arrays gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); if (gSky.mVOSkyp->getCubeMap()) { gSky.mVOSkyp->getCubeMap()->enable(0); gSky.mVOSkyp->getCubeMap()->bind(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); LLMatrix4 camera_rot(camera_mat.getMat3()); camera_rot.invert(); glLoadMatrixf((F32 *)camera_rot.mMatrix); glMatrixMode(GL_MODELVIEW); LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *face = *iter; if (voskyp->isReflFace(face)) { //refl_face = face; continue; } if (face->getGeomCount() > 0) { face->renderIndexed(); } } gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); gSky.mVOSkyp->getCubeMap()->disable(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); if (refl_face) { glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); renderReflection(refl_face); } gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); }
//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- BOOL LLImagePreviewAvatar::render() { mNeedsUpdate = FALSE; LLVOAvatar* avatarp = mDummyAvatar; glMatrixMode(GL_PROJECTION); gGL.pushMatrix(); glLoadIdentity(); glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); gGL.pushMatrix(); glLoadIdentity(); LLGLSUIDefault def; gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); gl_rect_2d_simple( mWidth, mHeight ); glMatrixMode(GL_PROJECTION); gGL.popMatrix(); glMatrixMode(GL_MODELVIEW); gGL.popMatrix(); gGL.flush(); LLVector3 target_pos = mTargetJoint->getWorldPosition(); LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * LLQuaternion(mCameraYaw, LLVector3::z_axis); LLQuaternion av_rot = avatarp->mPelvisp->getWorldRotation() * camera_rot; LLViewerCamera::getInstance()->setOriginAndLookAt( target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera LLVector3::z_axis, // up target_pos + (mCameraOffset * av_rot) ); // point of interest stop_glerror(); LLViewerCamera::getInstance()->setAspect((F32)mWidth / mHeight); LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE); LLVertexBuffer::unbind(); avatarp->updateLOD(); if (avatarp->mDrawable.notNull()) { LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); // make sure alpha=0 shows avatar material color LLGLDisable no_blend(GL_BLEND); LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); avatarPoolp->renderAvatars(avatarp); // renders only one avatar } gGL.color4f(1,1,1,1); return TRUE; }
// Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, bool tiling) { LLFastTimer t(FTM_RENDER); if (gWindowResized) { //skip render on frames where window has been resized gGL.flush(); glClear(GL_COLOR_BUFFER_BIT); gViewerWindow->getWindow()->swapBuffers(); LLPipeline::refreshCachedSettings(); gPipeline.resizeScreenTexture(); gResizeScreenTexture = FALSE; gWindowResized = FALSE; return; } //Nope /*if (LLPipeline::sRenderDeferred) { //hack to make sky show up in deferred snapshots for_snapshot = FALSE; }*/ if (LLPipeline::sRenderFrameTest) { send_agent_pause(); } gSnapshot = for_snapshot; LLGLSDefault gls_default; LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); stop_glerror(); gPipeline.disableLights(); //reset vertex buffers if needed gPipeline.doResetVertexBuffers(); stop_glerror(); // Don't draw if the window is hidden or minimized. // In fact, must explicitly check the minimized state before drawing. // Attempting to draw into a minimized window causes a GL error. JC if ( !gViewerWindow->getActive() || !gViewerWindow->getWindow()->getVisible() || gViewerWindow->getWindow()->getMinimized() ) { // Clean up memory the pools may have allocated if (rebuild) { gFrameStats.start(LLFrameStats::REBUILD); stop_glerror(); gPipeline.rebuildPools(); stop_glerror(); } stop_glerror(); gViewerWindow->returnEmptyPicks(); stop_glerror(); return; } gViewerWindow->checkSettings(); if(gWindowResized) //Singu Note: gViewerWindow->checkSettings() can call LLViewerWindow::reshape(). If it has then skip this frame. { return; } { LLFastTimer ftm(FTM_PICK); LLAppViewer::instance()->pingMainloopTimeout("Display:Pick"); gViewerWindow->performPick(); } LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); LLGLState::checkStates(); LLGLState::checkTextureChannels(); ////////////////////////////////////////////////////////// // // Logic for forcing window updates if we're in drone mode. // if (gNoRender) { #if LL_WINDOWS static F32 last_update_time = 0.f; if ((gFrameTimeSeconds - last_update_time) > 1.f) { InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); last_update_time = gFrameTimeSeconds; } #elif LL_DARWIN // MBW -- Do something clever here. #endif // Not actually rendering, don't bother. return; } // // Bail out if we're in the startup state and don't want to try to // render the world. // if (LLStartUp::getStartupState() < STATE_STARTED) { LLAppViewer::instance()->pingMainloopTimeout("Display:Startup"); display_startup(); return; } //LLGLState::verify(FALSE); ///////////////////////////////////////////////// // // Update GL Texture statistics (used for discard logic?) // LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats"); gFrameStats.start(LLFrameStats::UPDATE_TEX_STATS); stop_glerror(); LLImageGL::updateStats(gFrameTimeSeconds); LLVOAvatar::sRenderName = gSavedSettings.getS32("RenderName"); LLVOAvatar::sRenderGroupTitles = !gSavedSettings.getBOOL("RenderHideGroupTitleAll"); gPipeline.mBackfaceCull = TRUE; gFrameCount++; gRecentFrameCount++; if (gFocusMgr.getAppHasFocus()) { gForegroundFrameCount++; } ////////////////////////////////////////////////////////// // // Display start screen if we're teleporting, and skip render // if (gTeleportDisplay) { LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. S32 attach_count = 0; if (isAgentAvatarValid()) { attach_count = gAgentAvatarp->getAttachmentCount(); } 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); if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) { // Give up. Don't keep the UI locked forever. gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); gAgent.setTeleportMessage(std::string()); } static const LLCachedControl<bool> hide_tp_screen("AscentDisableTeleportScreens",false); const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { case LLAgent::TELEPORT_PENDING: gTeleportDisplayTimer.reset(); if(!hide_tp_screen) gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["pending"]); gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["pending"]); break; case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); if(!hide_tp_screen) gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: // Waiting for source simulator to respond gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_MOVING: // Viewer has received destination location from source simulator gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); gViewerWindow->setProgressString(message); break; case LLAgent::TELEPORT_START_ARRIVAL: // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator gTeleportArrivalTimer.reset(); gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); gViewerWindow->setProgressPercent(75.f); gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gTextureList.mForceResetTextureStats = TRUE; if(!hide_tp_screen) gAgentCamera.resetView(TRUE, TRUE); break; case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); if( arrival_fraction > 1.f || hide_tp_screen) { arrival_fraction = 1.f; LLFirstUse::useTeleport(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); gViewerWindow->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) { // <edit> // is this really needed.... I say no. //if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY ) // </edit> { LLFirstUse::useTeleport(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } } break; case LLAgent::TELEPORT_NONE: // No teleport in progress gViewerWindow->setShowProgress(FALSE); gTeleportDisplay = FALSE; gTeleportArrivalTimer.reset(); break; default: break; } } else if(LLAppViewer::instance()->logoutRequestSent()) { LLAppViewer::instance()->pingMainloopTimeout("Display:Logout"); F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; if (percent_done > 100.f) { percent_done = 100.f; } if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } else if (gRestoreGL) { LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL"); F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; if( percent_done > 100.f ) { gViewerWindow->setShowProgress(FALSE); gRestoreGL = FALSE; } else { if( LLApp::isExiting() ) { percent_done = 100.f; } gViewerWindow->setProgressPercent( percent_done ); } } // Progressively increase draw distance after TP when required. if (gSavedDrawDistance > 0.0f && gAgent.getTeleportState() == LLAgent::TELEPORT_NONE) { if (gTeleportArrivalTimer.getElapsedTimeF32() >= (F32)gSavedSettings.getU32("SpeedRezInterval")) { gTeleportArrivalTimer.reset(); F32 current = gSavedSettings.getF32("RenderFarClip"); if (gSavedDrawDistance > current) { current *= 2.0; if (current > gSavedDrawDistance) { current = gSavedDrawDistance; } gSavedSettings.setF32("RenderFarClip", current); } if (current >= gSavedDrawDistance) { gSavedDrawDistance = 0.0f; gSavedSettings.setF32("SavedRenderFarClip", 0.0f); } } } ////////////////////////// // // Prepare for the next frame // ///////////////////////////// // // Update the camera // // LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); ////////////////////////// // // clear the next buffer // (must follow dynamic texture writing since that uses the frame buffer) // if (gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected"); render_ui(); } ////////////////////////// // // Set rendering options // // LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup"); stop_glerror(); /////////////////////////////////////// // // Slam lighting parameters back to our defaults. // Note that these are not the same as GL defaults... stop_glerror(); gGL.setAmbientLightColor(LLColor4::white); stop_glerror(); ///////////////////////////////////// // // 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)) { LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); LLFastTimer t(FTM_UPDATE_TEXTURES); if (LLViewerDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); glClear(GL_DEPTH_BUFFER_BIT); } } gViewerWindow->setup3DViewport(); gPipeline.resetFrameStats(); // Reset per-frame statistics. if (!gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { //don't draw hud objects in this frame gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); } if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES)) { //don't draw hud particles in this frame gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); } //upkeep gl name pools LLGLNamePool::upkeepPools(); stop_glerror(); display_update_camera(tiling); stop_glerror(); // *TODO: merge these two methods LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); stop_glerror(); if(!tiling) { gFrameStats.start(LLFrameStats::UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); gPipeline.processPartitionQ(); gPipeline.updateGeom(max_geom_update_time); stop_glerror(); gPipeline.updateGL(); stop_glerror(); } gFrameStats.start(LLFrameStats::UPDATE_CULL); S32 water_clip = 0; if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER))) { if (LLViewerCamera::getInstance()->cameraUnderWater()) { water_clip = -1; } else { water_clip = 1; } } LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); //Increment drawable frame counter LLDrawable::incrementVisible(); LLSpatialGroup::sNoDelete = TRUE; LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) { //force occlusion on for all render types if doing deferred render LLPipeline::sUseOcclusion = 3; }*/ S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state LLPipeline::sUseOcclusion = llmin(occlusion, 1); } gDepthDirty = FALSE; LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); static LLCullResult result; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); BOOL to_texture = gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); { if (gResizeScreenTexture) { gResizeScreenTexture = FALSE; gPipeline.resizeScreenTexture(); } gGL.setColorMask(true, true); glClearColor(0,0,0,0); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); if (!for_snapshot || LLPipeline::sRenderDeferred) { 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(*LLViewerCamera::getInstance()); } LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); const LLMatrix4a saved_proj = glh_get_current_projection(); const LLMatrix4a saved_mod = glh_get_current_modelview(); glViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; if(!LLPipeline::sMemAllocationThrottled) { LLVOAvatar::updateImpostors(); } glh_set_current_projection(saved_proj); glh_set_current_modelview(saved_mod); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.loadMatrix(saved_proj); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.loadMatrix(saved_mod); gViewerWindow->setup3DViewport(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); } glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } LLGLState::checkStates(); LLGLState::checkClientArrays(); //if (!for_snapshot) { LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); gPipeline.renderPhysicsDisplay(); } LLGLState::checkStates(); LLGLState::checkClientArrays(); ////////////////////////////////////// // // Update images, using the image stats generated during object update/culling // // Can put objects onto the retextured list. // // Doing this here gives hardware occlusion queries extra time to complete LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); LLError::LLCallStacks::clear() ; llpushcallstacks ; gFrameStats.start(LLFrameStats::IMAGE_UPDATE); { LLFastTimer t(FTM_IMAGE_UPDATE); { LLFastTimer t(FTM_IMAGE_UPDATE_CLASS); LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); } { LLFastTimer t(FTM_IMAGE_UPDATE_BUMP); gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. } { LLFastTimer t(FTM_IMAGE_UPDATE_LIST); F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) gTextureList.updateImages(max_image_decode_time); } /*{ LLFastTimer t(FTM_IMAGE_UPDATE_DELETE); //remove dead textures from GL LLImageGL::deleteDeadTextures(); stop_glerror(); }*/ } llpushcallstacks ; LLGLState::checkStates(); LLGLState::checkClientArrays(); /////////////////////////////////// // // 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. // LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); { LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gFrameStats.start(LLFrameStats::STATE_SORT); gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); if (rebuild) { ////////////////////////////////////// // // rebuildPools // // gFrameStats.start(LLFrameStats::REBUILD); gPipeline.rebuildPools(); stop_glerror(); } } LLGLState::checkStates(); LLGLState::checkClientArrays(); LLPipeline::sUseOcclusion = occlusion; { LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); LLFastTimer t(FTM_UPDATE_SKY); gSky.updateSky(); } // if(gUseWireframe) // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b if ( (gUseWireframe) && ((!rlv_handler_t::isEnabled()) || (!gRlvAttachmentLocks.hasLockedHUD())) ) // [/RLVa:KB] { glClearColor(0.5f, 0.5f, 0.5f, 0.f); glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); //// render frontmost floater opaque for occlusion culling purposes //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); //// assumes frontmost floater with focus is opaque //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) //{ // gGL.matrixMode(LLRender::MM_MODELVIEW); // gGL.pushMatrix(); // { // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); // gGL.loadIdentity(); // LLRect floater_rect = frontmost_floaterp->calcScreenRect(); // // deflate by one pixel so rounding errors don't occlude outside of floater extents // floater_rect.stretch(-1); // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(), // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(), // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled()); // floater_3d_rect.translate(-0.5f, -0.5f); // gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear()); // gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f); // gGL.color4fv(LLColor4::white.mV); // gGL.begin(LLVertexBuffer::QUADS); // { // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); // } // gGL.end(); // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // } // gGL.popMatrix(); //} LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; LLGLState::checkStates(); LLGLState::checkClientArrays(); stop_glerror(); if (to_texture) { gGL.setColorMask(true, true); if (LLPipeline::sRenderDeferred) { gPipeline.mDeferredScreen.bindTarget(); glClearColor(1,0,1,1); gPipeline.mDeferredScreen.clear(); } else { gPipeline.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.mScreen.clear(); } gGL.setColorMask(true, false); } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom"); if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) && !gRestoreGL) { LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; static LLCachedControl<bool> render_ui_occlusion("RenderUIOcclusion", false); if(render_ui_occlusion && LLGLSLShader::sNoFixedFunction) { LLFloater* floaterp = gFloaterView->getFrontmost(); if(floaterp && floaterp->getVisible() && floaterp->isBackgroundVisible() && floaterp->isBackgroundOpaque()) { LLGLDepthTest depth(GL_TRUE, GL_TRUE); gGL.setColorMask(false, false); gOcclusionProgram.bind(); LLRect rect = floaterp->calcScreenRect(); rect.stretch(-1); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); gGL.loadIdentity(); gGL.ortho(0.0f, gViewerWindow->getWindowWidth(), 0.0f, gViewerWindow->getWindowHeight(), 0.f, 1.0f); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); gGL.loadIdentity(); gGL.color4fv( LLColor4::white.mV ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin( LLRender::QUADS ); gGL.vertex3f(rect.mLeft, rect.mTop,0.f); gGL.vertex3f(rect.mLeft, rect.mBottom,0.f); gGL.vertex3f(rect.mRight, rect.mBottom,0.f); gGL.vertex3f(rect.mRight, rect.mTop,0.f); gGL.end(); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); gOcclusionProgram.unbind(); } } static LLCachedControl<bool> render_depth_pre_pass("RenderDepthPrePass", false); if (render_depth_pre_pass && LLGLSLShader::sNoFixedFunction) { LLGLDepthTest depth(GL_TRUE, GL_TRUE); LLGLEnable cull_face(GL_CULL_FACE); gGL.setColorMask(false, false); U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; U32 num_types = LL_ARRAY_SIZE(types); gOcclusionProgram.bind(); for (U32 i = 0; i < num_types; i++) { gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); } gOcclusionProgram.unbind(); } gGL.setColorMask(true, false); if (LLPipeline::sRenderDeferred) { gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); } else { gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); } gGL.setColorMask(true, true); //store this frame's modelview matrix for use //when rendering next frame's occlusion queries gGLPreviousModelView = gGLLastModelView; gGLLastModelView = gGLModelView; gGLLastProjection = gGLProjection; stop_glerror(); } //Reversed this. disabling a texunit sets its index as current.. randomly breaking LLRender::matrixMode(U32 mode). Make sure unit0 is the 'current' unit. for (S32 i = gGLManager.mNumTextureImageUnits-1; i >= 0; --i) { //dummy cleanup of any currently bound textures if (gGL.getTexUnit((U32)i)->getCurrType() != LLTexUnit::TT_NONE) { gGL.getTexUnit((U32)i)->unbind(gGL.getTexUnit((U32)i)->getCurrType()); gGL.getTexUnit((U32)i)->disable(); } } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) { if (LLPipeline::sRenderDeferred) { gPipeline.mDeferredScreen.flush(); if(gPipeline.mDeferredScreen.getFBO()) { LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } } else { gPipeline.mScreen.flush(); if(gPipeline.mScreen.getFBO()) { LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(), 0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } } } //gGL.flush(); if (LLPipeline::sRenderDeferred) { gPipeline.renderDeferredLighting(); } LLPipeline::sUnderWaterRender = FALSE; LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); if (!for_snapshot || LLPipeline::sRenderDeferred) { LLFastTimer t(FTM_RENDER_UI); gFrameStats.start(LLFrameStats::RENDER_UI); render_ui(); } LLSpatialGroup::sNoDelete = FALSE; gPipeline.clearReferences(); gPipeline.rebuildGroups(); } LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); gFrameStats.start(LLFrameStats::MISC_END); stop_glerror(); if (LLPipeline::sRenderFrameTest) { send_agent_resume(); LLPipeline::sRenderFrameTest = FALSE; } display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); gShiftFrame = false; }
//----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- BOOL LLVisualParamHint::render() { LLVisualParamReset::sDirty = TRUE; gGL.pushUIMatrix(); gGL.loadUIIdentity(); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); gGL.loadIdentity(); gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); gGL.loadIdentity(); if (LLGLSLShader::sNoFixedFunction) { gUIProgram.bind(); } LLGLSUIDefault gls_ui; //LLGLState::verify(TRUE); mBackgroundp->draw(0, 0, mFullWidth, mFullHeight); gGL.matrixMode(LLRender::MM_PROJECTION); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); mNeedsUpdate = FALSE; mIsVisible = TRUE; LLQuaternion avatar_rotation; LLJoint* root_joint = gAgentAvatarp->getRootJoint(); if( root_joint ) { avatar_rotation = root_joint->getWorldRotation(); } LLVector3 target_joint_pos = mCamTargetJoint->getWorldPosition(); LLVector3 target_offset( 0, 0, mVisualParam->getCameraElevation() ); LLVector3 target_pos = target_joint_pos + (target_offset * avatar_rotation); F32 cam_angle_radians = mVisualParam->getCameraAngle() * DEG_TO_RAD; LLVector3 camera_snapshot_offset( mVisualParam->getCameraDistance() * cosf( cam_angle_radians ), mVisualParam->getCameraDistance() * sinf( cam_angle_radians ), mVisualParam->getCameraElevation() ); LLVector3 camera_pos = target_joint_pos + (camera_snapshot_offset * avatar_rotation); gGL.flush(); LLViewerCamera::getInstance()->setAspect((F32)mFullWidth / (F32)mFullHeight); LLViewerCamera::getInstance()->setOriginAndLookAt( camera_pos, // camera LLVector3::z_axis, // up target_pos ); // point of interest LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); if (gAgentAvatarp->mDrawable.notNull() && gAgentAvatarp->mDrawable->getFace(0)) { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); gGL.setAlphaRejectSettings(LLRender::CF_ALWAYS); gGL.setSceneBlendType(LLRender::BT_REPLACE); avatarPoolp->renderAvatars(gAgentAvatarp); // renders only one avatar gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight); mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight, FALSE); gAgentAvatarp->updateVisualParams(); gGL.color4f(1,1,1,1); mGLTexturep->setGLTextureCreated(true); gGL.popUIMatrix(); return TRUE; }