void CAOGenerator::GenerateShadowMaps() { double flProcessSceneRead = 0; double flProgress = 0; size_t iShadowMapSize = 1024; // A frame buffer for holding the depth buffer shadow render CFrameBuffer oDepthFB = SMAKRenderer()->CreateFrameBuffer(iShadowMapSize, iShadowMapSize, (fb_options_e)(FB_DEPTH_TEXTURE|FB_RENDERBUFFER)); // RB unused // A frame buffer for holding the UV layout once it is rendered flat with the shadow CFrameBuffer oUVFB = SMAKRenderer()->CreateFrameBuffer(m_iWidth, m_iHeight, (fb_options_e)(FB_TEXTURE|FB_LINEAR|FB_DEPTH)); // Depth unused // A frame buffer for holding the completed AO map m_oAOFB = SMAKRenderer()->CreateFrameBuffer(m_iWidth, m_iHeight, (fb_options_e)(FB_TEXTURE|FB_TEXTURE_HALF_FLOAT|FB_LINEAR|FB_DEPTH)); // Depth unused CRenderingContext c(SMAKRenderer()); c.UseFrameBuffer(&m_oAOFB); c.ClearColor(Color(0, 0, 0, 0)); c.SetDepthFunction(DF_LEQUAL); c.SetDepthTest(true); c.SetBackCulling(false); Matrix4x4 mBias( 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f); // Bias from [-1, 1] to [0, 1] AABB oBox = m_pScene->m_oExtends; Vector vecCenter = oBox.Center(); float flSize = oBox.Size().Length(); // Length of the box's diagonal Matrix4x4 mLightProjection = Matrix4x4::ProjectOrthographic(-flSize/2, flSize/2, -flSize/2, flSize/2, 1, flSize*2); size_t iSamples = (size_t)sqrt((float)m_iSamples); m_pWorkListener->SetAction("Taking exposures", m_iSamples); for (size_t x = 0; x <= iSamples; x++) { float flPitch = -asin(RemapVal((float)x, 0, (float)iSamples, -1, 1)) * 90 / (M_PI/2); for (size_t y = 0; y < iSamples; y++) { if (x == 0 || x == iSamples) { // Don't do a bunch of samples from the same spot on the poles. if (y != 0) continue; } float flYaw = RemapVal((float)y, 0, (float)iSamples, -180, 180); // Randomize the direction a tad to help fight moire Vector vecDir = AngleVector(EAngle(flPitch+RandomFloat(-1, 1)/2, flYaw+RandomFloat(-1, 1)/2, 0)); Vector vecLightPosition = vecDir*flSize + vecCenter; // Puts us twice as far from the closest vertex if (ao_debug.GetInt() > 1) SMAKWindow()->AddDebugLine(vecLightPosition, vecLightPosition-vecDir); Matrix4x4 mLightView = Matrix4x4::ConstructCameraView(vecLightPosition, (vecCenter-vecLightPosition).Normalized(), Vector(0, 1, 0)); c.SetProjection(mLightProjection); c.SetView(mLightView); // If we're looking from below and ground occlusion is on, don't bother with this render. if (!(flPitch < -10 && m_bGroundOcclusion)) { c.UseProgram("model"); c.UseFrameBuffer(&oDepthFB); c.SetViewport(Rect(0, 0, iShadowMapSize, iShadowMapSize)); c.SetBackCulling(false); c.ClearDepth(); c.BeginRenderVertexArray(m_iSceneDepth); c.SetPositionBuffer((size_t)0, 8*sizeof(float)); c.SetNormalsBuffer((size_t)3*sizeof(float), 8*sizeof(float)); c.SetTexCoordBuffer((size_t)6*sizeof(float), 8*sizeof(float)); c.EndRenderVertexArray(m_iSceneDepthVerts); c.UseFrameBuffer(nullptr); if (ao_debug.GetBool()) { CRenderingContext c(SMAKRenderer()); c.SetViewport(Rect(0, 0, iShadowMapSize/2, iShadowMapSize/2)); DrawTexture(oDepthFB.m_iDepthTexture, 1, c); } } Matrix4x4 mTextureMatrix = mBias*mLightProjection*mLightView; { CRenderingContext c(SMAKRenderer(), true); c.UseFrameBuffer(&oUVFB); c.SetViewport(Rect(0, 0, m_iWidth, m_iHeight)); c.ClearColor(Color(0, 0, 0, 0)); c.ClearDepth(); c.UseProgram("flat_shadow"); c.SetUniform("mBiasedLightMatrix", mTextureMatrix); c.SetUniform("iShadowMap", 0); c.SetUniform("vecLightNormal", -vecDir); c.SetUniform("bOccludeAll", (flPitch < -10 && m_bGroundOcclusion)); c.SetUniform("flTime", (float)Application()->GetTime()); c.BindTexture(oDepthFB.m_iDepthTexture); c.BeginRenderVertexArray(m_iScene); c.SetPositionBuffer((size_t)0, 8*sizeof(float)); c.SetNormalsBuffer((size_t)3*sizeof(float), 8*sizeof(float)); c.SetTexCoordBuffer((size_t)6*sizeof(float), 8*sizeof(float)); c.EndRenderVertexArray(m_iSceneVerts); } if (ao_debug.GetBool()) { CRenderingContext c(SMAKRenderer()); c.SetViewport(Rect(iShadowMapSize/2, 0, m_iWidth, m_iHeight)); DrawTexture(oUVFB.m_iMap, 1, c); } double flTimeBefore = SMAKWindow()->GetTime(); c.SetViewport(Rect(0, 0, m_iWidth, m_iHeight)); c.UseFrameBuffer(&m_oAOFB); AccumulateTexture(oUVFB.m_iMap); c.UseFrameBuffer(nullptr); if (ao_debug.GetBool()) { CRenderingContext c(SMAKRenderer()); c.UseProgram("ao"); c.SetViewport(Rect(iShadowMapSize/2+m_iWidth, 0, m_iWidth, m_iHeight)); c.SetUniform("iAOMap", 0); c.SetBlend(BLEND_ALPHA); DrawTexture(m_oAOFB.m_iMap, 1, c); } flProcessSceneRead += (SMAKWindow()->GetTime() - flTimeBefore); flTimeBefore = SMAKWindow()->GetTime(); m_pWorkListener->WorkProgress(x*iSamples + y); flProgress += (SMAKWindow()->GetTime() - flTimeBefore); if (m_bStopGenerating) break; } if (m_bStopGenerating) break; } c.UseFrameBuffer(&m_oAOFB); c.ReadPixels(0, 0, m_iWidth, m_iHeight, m_pvecPixels); c.UseFrameBuffer(nullptr); if (!m_bStopGenerating) { size_t iBufferSize = m_iWidth*m_iHeight; m_pWorkListener->SetAction("Reading pixels", iBufferSize); for (size_t p = 0; p < iBufferSize; p++) { Vector4D& vecPixel = m_pvecPixels[p]; if (vecPixel.w == 0.0f) continue; m_avecShadowValues[p].x = vecPixel.x; m_aiShadowReads[p] = (size_t)vecPixel.w; m_bPixelMask[p] = true; m_pWorkListener->WorkProgress(p); } } oDepthFB.Destroy(); oUVFB.Destroy(); // Don't destroy m_oAOFB yet, we need it in a bit. It gets destroyed later. }
int paintButtons( const button_label_ext * const content, const int &count, const int &x, const int &y, const int &footerwidth, const int &footerheight, const int &maxwidth, bool show, int *wantedwidth, int *wantedheight) { CFrameBuffer *frameBuffer = CFrameBuffer::getInstance(); Font * font = g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL]; int cnt = count; int x_footer = x; int y_footer = y; int w_footer = footerwidth; int h_footer = 0; int w_space = 10; //minimal space between buttons int h_space = 4; //minimal space between caption and/or icon and border int x_icon = x_footer + w_space; int x_caption = 0; int x_button = x_icon; int h_button = 0; //calculate max of h + w //icon int h_max_icon = 0; int w_icons = 0; //text int w_text = 0; int h_max_text = font->getHeight(); int count_icons = 0; int count_labels = 0; /* more than 16 buttons? noooooo*/ int iconw[16]; int iconh[16]; int fwidth[16]; const char *buttontext[16]; /* sanity check... */ if (count > 16 || count == 0) { fprintf(stderr, "paintButtons does only support max 16 buttons yet (%d)\n", count); // print_stacktrace(); return 0; } if (maxwidth < 200 && show) { fprintf(stderr, "paintButtons: maxwidth very small\n"); fprintf(stderr, " x: %d y: %d footw: %d count: %d maxw: %d footh: %d\n ", x, y, footerwidth, count, maxwidth, footerheight); // print_stacktrace(); } bool maximize = false; for (int i = 0; i < cnt; i++) maximize |= content[i].maximize; for (int i = 0; i < cnt; i++) { //icon int w = 0; int h = 0; frameBuffer->getIconSize(content[i].button, &w, &h); iconw[i] = w; iconh[i] = h; h_max_icon = std::max(h_max_icon, h); w_icons += w; if (w) count_icons++; if (content[i].text) { buttontext[i] = content[i].text; fwidth[i] = std::max(content[i].width, font->getRenderWidth(buttontext[i])); w_text += fwidth[i]; count_labels++; } else if (content[i].locale) { buttontext[i] = g_Locale->getText(content[i].locale); fwidth[i] = std::max(content[i].width, font->getRenderWidth(buttontext[i])); w_text += fwidth[i]; count_labels++; } else { buttontext[i] = ""; fwidth[i] = 0; } if (maximize && i < cnt - 1) fwidth[i] += w, w_text += w; } //calculate button heigth h_button = std::max(h_max_icon, h_max_text); //calculate optimal button height //calculate footer heigth h_footer = footerheight == 0 ? (h_button + 2*h_space) : footerheight; if (!show) { if (wantedheight) *wantedheight = h_button + 2*h_space; if (wantedwidth) *wantedwidth = w_space * 2 + w_text + w_icons + (count_icons + count_labels - 1) * h_space; return h_footer; } //paint footer if (w_footer > 0) frameBuffer->paintBoxRel(x_footer, y_footer, w_footer, h_footer, COL_INFOBAR_SHADOW_PLUS_1, RADIUS_LARGE, CORNER_BOTTOM); //round //baseline int y_base = y_footer + h_footer/2; int spacing = maxwidth - w_space * 2 - w_text - w_icons - (count_icons + count_labels - 1) * h_space; #if 0 /* debug */ fprintf(stderr, "PB: sp %d mw %d w_t %d w_i %d w_s %d c_i %d\n", spacing, maxwidth, w_text, w_icons, w_space, count_items); #endif if (fwidth[cnt - 1] == 0) /* divisor needs to be labels+1 unless rightmost icon has a label */ count_labels++; /* side effect: we don't try to divide by 0 :-) */ if (maximize) { while (spacing > 0) { for (int i = 0; i < cnt && spacing > 0; i++) { if (content[i].maximize) { fwidth[i]++; spacing--; } } } } if (spacing >= 0) { int tmp = count_labels ? count_labels : 1;//avoid division by zero /* add half of the inter-object space to the */ spacing /= tmp; /* left and right (this might break vertical */ x_button += spacing / 2; /* alignment, but nobody is using this (yet) */ } /* and I'm don't know how it should work. */ else { w_text = w_text ? w_text : 1; /* shorten captions relative to their length */ for (int i = 0; i < cnt; i++) fwidth[i] = (fwidth[i] * (w_text + spacing)) / w_text; /* spacing is negative...*/ spacing = 0; } for (int j = 0; j < cnt; j++) { const char * caption = NULL; //set caption... caption = buttontext[j]; const char * icon = content[j].button ? content[j].button : ""; // calculate baseline startposition of icon and text in y int y_caption = y_base + h_max_text/2+1; // paint icon and text frameBuffer->paintIcon(icon, x_button , y_base - iconh[j]/2); x_caption = x_button + iconw[j] + h_space; font->RenderString(x_caption, y_caption, fwidth[j], caption, COL_INFOBAR_SHADOW_TEXT); /* set next startposition x, if text is length=0 then offset is =renderwidth of icon, * for generating buttons without captions, */ /* increase x position */ x_button = x_caption; if (fwidth[j]) x_button += fwidth[j] + spacing + h_space; } return h_footer; }
int CImageInfo::exec(CMenuTarget* parent, const std::string &) { int res = menu_return::RETURN_REPAINT; if (parent) parent->hide(); //clean up before, because we could have a current instance with already initialized contents Clean(); //init window object, add cc-items and paint all ShowWindow(); CFrameBuffer *frameBuffer = CFrameBuffer::getInstance(); neutrino_msg_t msg; while (1) { frameBuffer->blit(); neutrino_msg_data_t data; uint64_t timeoutEnd = CRCInput::calcTimeoutEnd_MS(100); g_RCInput->getMsgAbsoluteTimeout( &msg, &data, &timeoutEnd ); if(msg == CRCInput::RC_setup) { res = menu_return::RETURN_EXIT_ALL; break; } else if (msg == CRCInput::RC_red){ // init temporarly vars neutrino_locale_t info_cap , new_btn_cap; info_cap = new_btn_cap = NONEXISTANT_LOCALE; string info_txt = ""; neutrino_locale_t btn_cap = btn_red->getCaptionLocale(); //toggle caption and info contents if (btn_cap == LOCALE_BUILDINFO_MENU){ info_cap = LOCALE_BUILDINFO_MENU; for (uint i=0; i<CBuildInfo::BI_TYPE_IDS; i++){ info_txt += g_Locale->getText(b_info->getInfo(i).caption); info_txt += "\n"; info_txt += b_info->getInfo(i).info_text + "\n\n"; } new_btn_cap = LOCALE_IMAGEINFO_LICENSE; } if (btn_cap == LOCALE_IMAGEINFO_LICENSE){ info_cap = LOCALE_IMAGEINFO_LICENSE; info_txt = getLicenseText(); new_btn_cap = LOCALE_BUILDINFO_MENU; } //assign new caption and info contents cc_sub_caption->setText(info_cap, CTextBox::AUTO_WIDTH, item_font); InitInfoText(info_txt); btn_red->setCaption(new_btn_cap); //paint items cc_sub_caption->paint(false); cc_lic->paint(false); btn_red->kill(); btn_red->paint(false); } else if((msg == CRCInput::RC_sat) || (msg == CRCInput::RC_favorites)) { g_RCInput->postMsg (msg, 0); res = menu_return::RETURN_EXIT_ALL; break; } else if ((msg == CRCInput::RC_up) || (msg == CRCInput::RC_page_up)) { ScrollLic(false); } else if ((msg == CRCInput::RC_down) || (msg == CRCInput::RC_page_down)) { ScrollLic(true); } else if (msg <= CRCInput::RC_MaxRC){ break; } if ( msg > CRCInput::RC_MaxRC && msg != CRCInput::RC_timeout){ CNeutrinoApp::getInstance()->handleMsg( msg, data ); } } hide(); frameBuffer->blit(); return res; }