void convex::gl_render(view& scene) { if (degenerate()) return; long check = checksum(); if (check != last_checksum) { recalc(); last_checksum = check; } glShadeModel(GL_FLAT); gl_enable cull_face( GL_CULL_FACE); color.gl_set(1.0); glBegin(GL_TRIANGLES); for (std::vector<face>::const_iterator f = hull.begin(); f != hull.end(); ++f) { f->normal.gl_normal(); (f->corner[0] * scene.gcf).gl_render(); (f->corner[1] * scene.gcf).gl_render(); (f->corner[2] * scene.gcf).gl_render(); } glEnd(); glShadeModel( GL_SMOOTH); }
void cone::gl_render(view& scene) { if (degenerate()) return; init_model(scene); clear_gl_error(); // See sphere::gl_render() for a description of the level of detail calc. double coverage = scene.pixel_coverage( pos, radius); int lod = 0; if (coverage < 0) lod = 5; else if (coverage < 10) lod = 0; else if (coverage < 30) lod = 1; else if (coverage < 90) lod = 2; else if (coverage < 250) lod = 3; else if (coverage < 450) lod = 4; else lod = 5; lod += scene.lod_adjust; if (lod < 0) lod = 0; else if (lod > 5) lod = 5; gl_matrix_stackguard guard; const double length = axis.mag(); model_world_transform( scene.gcf, vector( length, radius, radius ) ).gl_mult(); color.gl_set(opacity); if (translucent()) { gl_enable cull_face( GL_CULL_FACE); // Render the back half. glCullFace( GL_FRONT); scene.cone_model[lod].gl_render(); // Render the front half. glCullFace( GL_BACK); scene.cone_model[lod].gl_render(); } else { scene.cone_model[lod].gl_render(); } check_gl_error(); }
void sphere::gl_render( view& geometry) { if (degenerate()) return; //init_model(); init_model(geometry); // coverage is the radius of this sphere in pixels: double coverage = geometry.pixel_coverage( pos, radius); int lod = 0; if (coverage < 0) // Behind the camera, but still visible. lod = 4; else if (coverage < 30) lod = 0; else if (coverage < 100) lod = 1; else if (coverage < 500) lod = 2; else if (coverage < 5000) lod = 3; else lod = 4; lod += geometry.lod_adjust; // allow user to reduce level of detail if (lod > 5) lod = 5; else if (lod < 0) lod = 0; gl_matrix_stackguard guard; model_world_transform( geometry.gcf, get_scale() ).gl_mult(); color.gl_set(opacity); if (translucent()) { // Spheres are convex, so we don't need to sort gl_enable cull_face( GL_CULL_FACE); // Render the back half (inside) glCullFace( GL_FRONT ); geometry.sphere_model[lod].gl_render(); // Render the front half (outside) glCullFace( GL_BACK ); geometry.sphere_model[lod].gl_render(); } else { // Render a simple sphere. geometry.sphere_model[lod].gl_render(); } }
//----------------------------------------------------------------------------- // drawShape() //----------------------------------------------------------------------------- U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) { if (LLVOAvatar::sShowAttachmentPoints) { LLGLDisable cull_face(GL_CULL_FACE); gGL.color4f(1.f, 1.f, 1.f, 1.f); gGL.begin(LLRender::QUADS); { gGL.vertex3f(-0.1f, 0.1f, 0.f); gGL.vertex3f(-0.1f, -0.1f, 0.f); gGL.vertex3f(0.1f, -0.1f, 0.f); gGL.vertex3f(0.1f, 0.1f, 0.f); }gGL.end(); } return 0; }
// 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; }
// 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); }
void GLGSRender::begin() { rsx::thread::begin(); if (skip_frame) return; if (conditional_render_enabled && conditional_render_test_failed) return; init_buffers(); if (!framebuffer_status_valid) return; std::chrono::time_point<steady_clock> then = steady_clock::now(); bool color_mask_b = rsx::method_registers.color_mask_b(); bool color_mask_g = rsx::method_registers.color_mask_g(); bool color_mask_r = rsx::method_registers.color_mask_r(); bool color_mask_a = rsx::method_registers.color_mask_a(); gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a); gl_state.depth_mask(rsx::method_registers.depth_write_enabled()); gl_state.stencil_mask(rsx::method_registers.stencil_mask()); if (gl_state.enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST)) { gl_state.depth_func(comparison_op(rsx::method_registers.depth_func())); } if (glDepthBoundsEXT && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT))) { gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max()); } gl_state.depth_range(rsx::method_registers.clip_min(), rsx::method_registers.clip_max()); gl_state.enable(rsx::method_registers.dither_enabled(), GL_DITHER); if (gl_state.enable(rsx::method_registers.blend_enabled(), GL_BLEND)) { glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()), blend_factor(rsx::method_registers.blend_func_dfactor_rgb()), blend_factor(rsx::method_registers.blend_func_sfactor_a()), blend_factor(rsx::method_registers.blend_func_dfactor_a())); auto blend_colors = rsx::get_constant_blend_colors(); glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]); glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()), blend_equation(rsx::method_registers.blend_equation_a())); } if (gl_state.enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST)) { glStencilFunc(comparison_op(rsx::method_registers.stencil_func()), rsx::method_registers.stencil_func_ref(), rsx::method_registers.stencil_func_mask()); glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()), stencil_op(rsx::method_registers.stencil_op_zpass())); if (rsx::method_registers.two_sided_stencil_test_enabled()) { glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask()); glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()), rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask()); glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()), stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass())); } } gl_state.enablei(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1); gl_state.enablei(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2); gl_state.enablei(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3); if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP)) { gl_state.logic_op(logic_op(rsx::method_registers.logic_operation())); } gl_state.line_width(rsx::method_registers.line_width()); gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH); gl_state.enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT); gl_state.enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE); gl_state.enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL); gl_state.polygon_offset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias()); if (gl_state.enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE)) { gl_state.cull_face(cull_face(rsx::method_registers.cull_face_mode())); } gl_state.front_face(front_face(rsx::method_registers.front_face_mode())); //TODO //NV4097_SET_ANISO_SPREAD //NV4097_SET_SPECULAR_ENABLE //NV4097_SET_TWO_SIDE_LIGHT_EN //NV4097_SET_FLAT_SHADE_OP //NV4097_SET_EDGE_FLAG //NV4097_SET_COLOR_KEY_COLOR //NV4097_SET_SHADER_CONTROL //NV4097_SET_ZMIN_MAX_CONTROL //NV4097_SET_ANTI_ALIASING_CONTROL //NV4097_SET_CLIP_ID_TEST_ENABLE std::chrono::time_point<steady_clock> now = steady_clock::now(); m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count(); }
void GLGSRender::begin() { rsx::thread::begin(); init_buffers(); std::chrono::time_point<std::chrono::system_clock> then = std::chrono::system_clock::now(); bool color_mask_b = rsx::method_registers.color_mask_b(); bool color_mask_g = rsx::method_registers.color_mask_g(); bool color_mask_r = rsx::method_registers.color_mask_r(); bool color_mask_a = rsx::method_registers.color_mask_a(); __glcheck glColorMask(color_mask_r, color_mask_g, color_mask_b, color_mask_a); __glcheck glDepthMask(rsx::method_registers.depth_write_enabled()); __glcheck glStencilMask(rsx::method_registers.stencil_mask()); if (__glcheck enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST)) { __glcheck glDepthFunc(comparison_op(rsx::method_registers.depth_func())); __glcheck glDepthMask(rsx::method_registers.depth_write_enabled()); } if (glDepthBoundsEXT && (__glcheck enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT))) { __glcheck glDepthBoundsEXT(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max()); } __glcheck glDepthRange(rsx::method_registers.clip_min(), rsx::method_registers.clip_max()); __glcheck enable(rsx::method_registers.dither_enabled(), GL_DITHER); if (__glcheck enable(rsx::method_registers.blend_enabled(), GL_BLEND)) { __glcheck glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()), blend_factor(rsx::method_registers.blend_func_dfactor_rgb()), blend_factor(rsx::method_registers.blend_func_sfactor_a()), blend_factor(rsx::method_registers.blend_func_dfactor_a())); if (rsx::method_registers.surface_color() == rsx::surface_color_format::w16z16y16x16) //TODO: check another color formats { u16 blend_color_r = rsx::method_registers.blend_color_16b_r(); u16 blend_color_g = rsx::method_registers.blend_color_16b_g(); u16 blend_color_b = rsx::method_registers.blend_color_16b_b(); u16 blend_color_a = rsx::method_registers.blend_color_16b_a(); __glcheck glBlendColor(blend_color_r / 65535.f, blend_color_g / 65535.f, blend_color_b / 65535.f, blend_color_a / 65535.f); } else { u8 blend_color_r = rsx::method_registers.blend_color_8b_r(); u8 blend_color_g = rsx::method_registers.blend_color_8b_g(); u8 blend_color_b = rsx::method_registers.blend_color_8b_b(); u8 blend_color_a = rsx::method_registers.blend_color_8b_a(); __glcheck glBlendColor(blend_color_r / 255.f, blend_color_g / 255.f, blend_color_b / 255.f, blend_color_a / 255.f); } __glcheck glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()), blend_equation(rsx::method_registers.blend_equation_a())); } if (__glcheck enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST)) { __glcheck glStencilFunc(comparison_op(rsx::method_registers.stencil_func()), rsx::method_registers.stencil_func_ref(), rsx::method_registers.stencil_func_mask()); __glcheck glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()), stencil_op(rsx::method_registers.stencil_op_zpass())); if (rsx::method_registers.two_sided_stencil_test_enabled()) { __glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask()); __glcheck glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()), rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask()); __glcheck glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()), stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass())); } } __glcheck enable(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1); __glcheck enable(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2); __glcheck enable(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3); if (__glcheck enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP)) { __glcheck glLogicOp(logic_op(rsx::method_registers.logic_operation())); } __glcheck glLineWidth(rsx::method_registers.line_width()); __glcheck enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH); //TODO //NV4097_SET_ANISO_SPREAD __glcheck enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT); __glcheck enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE); __glcheck enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL); __glcheck glPolygonOffset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias()); //NV4097_SET_SPECULAR_ENABLE //NV4097_SET_TWO_SIDE_LIGHT_EN //NV4097_SET_FLAT_SHADE_OP //NV4097_SET_EDGE_FLAG auto set_clip_plane_control = [&](int index, rsx::user_clip_plane_op control) { int value = 0; int location; if (m_program->uniforms.has_location("uc_m" + std::to_string(index), &location)) { switch (control) { default: LOG_ERROR(RSX, "bad clip plane control (0x%x)", (u8)control); case rsx::user_clip_plane_op::disable: value = 0; break; case rsx::user_clip_plane_op::greater_or_equal: value = 1; break; case rsx::user_clip_plane_op::less_than: value = -1; break; } __glcheck m_program->uniforms[location] = value; } __glcheck enable(value, GL_CLIP_DISTANCE0 + index); }; load_program(); set_clip_plane_control(0, rsx::method_registers.clip_plane_0_enabled()); set_clip_plane_control(1, rsx::method_registers.clip_plane_1_enabled()); set_clip_plane_control(2, rsx::method_registers.clip_plane_2_enabled()); set_clip_plane_control(3, rsx::method_registers.clip_plane_3_enabled()); set_clip_plane_control(4, rsx::method_registers.clip_plane_4_enabled()); set_clip_plane_control(5, rsx::method_registers.clip_plane_5_enabled()); if (__glcheck enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE)) { __glcheck glCullFace(cull_face(rsx::method_registers.cull_face_mode())); } __glcheck glFrontFace(front_face(rsx::method_registers.front_face_mode())); __glcheck enable(rsx::method_registers.poly_smooth_enabled(), GL_POLYGON_SMOOTH); //NV4097_SET_COLOR_KEY_COLOR //NV4097_SET_SHADER_CONTROL //NV4097_SET_ZMIN_MAX_CONTROL //NV4097_SET_ANTI_ALIASING_CONTROL //NV4097_SET_CLIP_ID_TEST_ENABLE std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count(); m_draw_calls++; }