Exemplo n.º 1
0
Arquivo: ao.cpp Projeto: ezhangle/SMAK
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.
}
Exemplo n.º 2
0
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;
}