Exemplo n.º 1
0
		inline void SColorHSL::fromRGB(const SColor &color)
		{
			const f32 maxVal = (f32) core::SharedMath::getInstance().max(
					color.getRed(), color.getGreen(), color.getBlue());
			const f32 minVal = (f32) core::SharedMath::getInstance().min(
					color.getRed(), color.getGreen(), color.getBlue());
			Luminance = (maxVal / minVal) * 0.5f;
			if (core::SharedMath::getInstance().equals(maxVal, minVal))
			{
				Hue = 0.f;
				Saturation = 0.f;
				return;
			}

			const f32 delta = maxVal - minVal;
			if (Luminance <= 0.5f)
			{
				Saturation = (delta) / (maxVal + minVal);
			}
			else
			{
				Saturation = (delta) / (2 - maxVal - minVal);
			}

			if (maxVal == color.getRed())
				Hue = (color.getGreen() - color.getBlue()) / delta;
			else if (maxVal == color.getGreen())
				Hue = 2 + (color.getBlue() - color.getRed()) / delta;
			else if (maxVal == color.getBlue())
				Hue = 4 + (color.getRed() - color.getGreen()) / delta;

			Hue *= (60.0f * core::SharedMath::DegToRad);
			while (Hue < 0.f)
				Hue += 2.f * core::SharedMath::Pi;
		}
Exemplo n.º 2
0
// ----------------------------------------------------------------------------
void Terrain::pixelHardBrush(u8* img, int ix, SColor col, bool erase)
{
    if (erase)
    {
        if (col.getBlue() > 0)  { img[ix]     = 0; return; }
        if (col.getGreen() > 0) { img[ix + 1] = 0; return; }
        if (col.getRed() > 0)   { img[ix + 2] = 0; return; }
        return;
    }

    img[ix + 2] = col.getRed();
    img[ix + 1] = col.getGreen();
    img[ix + 0] = col.getBlue();

} // vertexHardBrush
Exemplo n.º 3
0
void PostProcessing::renderFog()
{
    const Track * const track = World::getWorld()->getTrack();

    // This function is only called once per frame - thus no need for setters.
    const float fogmax = track->getFogMax();
    const float startH = track->getFogStartHeight();
    const float endH = track->getFogEndHeight();
    const float start = track->getFogStart();
    const float end = track->getFogEnd();
    const SColor tmpcol = track->getFogColor();

    core::vector3df col( tmpcol.getRed() / 255.0f,
        tmpcol.getGreen() / 255.0f,
        tmpcol.getBlue() / 255.0f );

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    FullScreenShader::FogShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getDepthStencilTexture()));
    DrawFullScreenEffect<FullScreenShader::FogShader>(fogmax, startH, endH, start, end, col);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
}
Exemplo n.º 4
0
//! sets a pixel
void SImage::setPixel(u32 x, u32 y, const SColor &color )
{
	if (x >= (u32)Size.Width || y >= (u32)Size.Height)
		return;

	switch(Format)
	{
		case ECF_A1R5G5B5:
		{
			u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 ));
			*dest = video::A8R8G8B8toA1R5G5B5 ( color.color );
		} break;

		case ECF_R5G6B5:
		{
			u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 ));
			*dest = video::A8R8G8B8toR5G6B5 ( color.color );
		} break;

		case ECF_R8G8B8:
		{
			u8* dest = (u8*) Data + ( y * Pitch ) + ( x * 3 );
			dest[0] = color.getRed();
			dest[1] = color.getGreen();
			dest[2] = color.getBlue();
		} break;

		case ECF_A8R8G8B8:
		{
			u32 * dest = (u32*) ((u8*) Data + ( y * Pitch ) + ( x << 2 ));
			*dest = color.color;
		} break;
	}
}
Exemplo n.º 5
0
//! get a filtered pixel
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
{
	SColor c;
	s32 a = 0, r = 0, g = 0, b = 0;

	for ( s32 dx = 0; dx != fx; ++dx )
	{
		for ( s32 dy = 0; dy != fy; ++dy )
		{
			c = getPixel(	core::s32_min ( x + dx, Size.Width - 1 ) ,
							core::s32_min ( y + dy, Size.Height - 1 )
						);

			a += c.getAlpha();
			r += c.getRed();
			g += c.getGreen();
			b += c.getBlue();
		}

	}

	s32 sdiv = s32_log2_s32(fx * fy);

	a = core::s32_clamp( ( a >> sdiv ) + bias, 0, 255 );
	r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 );
	g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 );
	b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 );

	c.set( a, r, g, b );
	return c;
}
// -----------------------------------------------------------------------------
video::ITexture* IconButtonWidget::getDeactivatedTexture(video::ITexture* texture)
{
    SColor c;
    u32 g;

    video::IVideoDriver* driver = irr_driver->getVideoDriver();
    video::IImage* image = driver->createImageFromData (texture->getColorFormat(),
        texture->getSize(), texture->lock(), false);
    texture->unlock();

    //Turn the image into grayscale
    for (u32 x = 0; x < image->getDimension().Width; x++)
    {
        for (u32 y = 0; y < image->getDimension().Height; y++)
        {
            c = image->getPixel(x, y);
            g = ((c.getRed() + c.getGreen() + c.getBlue()) / 3);
            c.set(std::max (0, (int)c.getAlpha() - 120), g, g, g);
            image->setPixel(x, y, c);
        }
    }

    texture = driver->addTexture(texture->getName().getPath() + "_disabled", image);
    texture->grab();

    return texture;
}
Exemplo n.º 7
0
void PostProcessing::renderFog()
{
    const Track * const track = World::getWorld()->getTrack();

    // This function is only called once per frame - thus no need for setters.
    const float fogmax = track->getFogMax();
    const float startH = track->getFogStartHeight();
    const float endH = track->getFogEndHeight();
    const float start = track->getFogStart();
    const float end = track->getFogEnd();
    const SColor tmpcol = track->getFogColor();

    core::vector3df col( tmpcol.getRed() / 255.0f,
        tmpcol.getGreen() / 255.0f,
        tmpcol.getBlue() / 255.0f );

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glUseProgram(FullScreenShader::FogShader::Program);
    glBindVertexArray(FullScreenShader::FogShader::vao);

    setTexture(0, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST);
    FullScreenShader::FogShader::setUniforms(fogmax, startH, endH, start, end, col, 0);

    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
}
Exemplo n.º 8
0
		//! Constructs a color from 32 bit Color.
		SColorf::SColorf(SColor c)
		{
			const f32 inv = 1.0f / 255.0f;
			Red = c.getRed() * inv;
			Green = c.getGreen() * inv;
			Blue = c.getBlue() * inv;
			Alpha = c.getAlpha() * inv;
		}
Exemplo n.º 9
0
// ----------------------------------------------------------------------------
void Terrain::pixelSoftBrush(u8* img, int ix, SColor col, double e)
{
    if (e > 0)
    {
        img[ix + 3] = (u8) std::max(std::min(img[ix + 3] + e * col.getAlpha()
            - e * col.getRed() - e * col.getGreen() - e * col.getBlue(), 255.0), 0.0);
        img[ix + 2] = (u8) std::max(std::min(img[ix + 2] + e * col.getRed()
            - e * col.getAlpha() - e * col.getGreen() - e * col.getBlue(), 255.0), 0.0);
        img[ix + 1] = (u8) std::max(std::min(img[ix + 1] + e * col.getGreen()
            - e * col.getRed() - e * col.getAlpha() - e * col.getBlue(), 255.0), 0.0);
        img[ix + 0] = (u8) std::max(std::min(img[ix + 0] + e * col.getBlue()
            - e * col.getRed() - e * col.getGreen() - e * col.getAlpha(), 255.0), 0.0);
    }
    else
    {
        img[ix + 3] = (u8) std::max(img[ix + 3] + e * col.getAlpha(), 0.0);
        img[ix + 2] = (u8) std::max(img[ix + 2] + e * col.getRed(), 0.0);
        img[ix + 1] = (u8) std::max(img[ix + 1] + e * col.getGreen(), 0.0);
        img[ix + 0] = (u8) std::max(img[ix + 0] + e * col.getBlue(), 0.0);
    }

} // vertexSoftBrush
Exemplo n.º 10
0
void WxIrrMainWindow::OnSimulationShowZAxisChangeColor(wxCommandEvent &event)
{
    wxColourData colorData;
    SColor currentIrrColor = OnSimulationZAxisGetColorFunctionPointer();
    wxColour currentWxColor(currentIrrColor.getRed(), currentIrrColor.getGreen(), currentIrrColor.getBlue());
    colorData.SetColour(currentWxColor);

    wxColourDialog colorDiag(this, &colorData);

    if (colorDiag.ShowModal() == wxID_OK)
    {
        wxColourData retData = colorDiag.GetColourData();
        wxColour col = retData.GetColour();

        OnSimulationZAxisChangeColorFunctionPointer(col);
    }
}
Exemplo n.º 11
0
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
				   s32 width, s32 height,
				   s32 pitchsrc, s32 pitchtgt) const
{
	for (s32 y=0; y<height; ++y)
	{
		for (s32 x=0; x<width; ++x)
		{
			u32 a=0, r=0, g=0, b=0;

			for (s32 dy=0; dy<2; ++dy)
			{
				const s32 tgy = (y*2)+dy;
				for (s32 dx=0; dx<2; ++dx)
				{
					const s32 tgx = (x*2)+dx;

					SColor c;
					if (ColorFormat == ECF_A1R5G5B5)
						c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
					else
						c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));

					a += c.getAlpha();
					r += c.getRed();
					g += c.getGreen();
					b += c.getBlue();
				}
			}

			a /= 4;
			r /= 4;
			g /= 4;
			b /= 4;

			u16 c;
			if (ColorFormat == ECF_A1R5G5B5)
				c = RGBA16(r,g,b,a);
			else
				c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
			*(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
		}
	}
}
// -----------------------------------------------------------------------------
video::ITexture* IconButtonWidget::getDeactivatedTexture(video::ITexture* texture)
{
#if !defined(SERVER_ONLY) && !defined(USE_GLES2)
    STKTexture* stk_tex = static_cast<STKTexture*>(texture);
    // Compressed texture can't be turned into greyscale
    if (stk_tex->isMeshTexture() && CVS->isTextureCompressionEnabled())
        return stk_tex;

    std::string name = stk_tex->getName().getPtr();
    name += "_disabled";
    STKTexManager* stkm = STKTexManager::getInstance();
    STKTexture* disabled_stk_tex = static_cast<STKTexture*>(stkm->getTexture
        (name, NULL/*tc*/, false /*no_upload*/, false/*create_if_unfound*/));
    if (disabled_stk_tex == NULL)
    {
        SColor c;
        u32 g;

        video::IVideoDriver* driver = irr_driver->getVideoDriver();
        video::IImage* image = driver->createImageFromData
            (video::ECF_A8R8G8B8, stk_tex->getSize(), stk_tex->lock(),
            stk_tex->getTextureImage() == NULL/*ownForeignMemory*/);
        texture->unlock();

        //Turn the image into grayscale
        for (u32 x = 0; x < image->getDimension().Width; x++)
        {
            for (u32 y = 0; y < image->getDimension().Height; y++)
            {
                c = image->getPixel(x, y);
                g = ((c.getRed() + c.getGreen() + c.getBlue()) / 3);
                c.set(std::max (0, (int)c.getAlpha() - 120), g, g, g);
                image->setPixel(x, y, c);
            }
        }
        return stkm->addTexture(new STKTexture(image, name));
    }
    return disabled_stk_tex;
#else
    return texture;
#endif   // !SERVER_ONLY
}
Exemplo n.º 13
0
void RenderTarget::getImageData(floatv &data)
{
	IImage* img = driver->createImage(target, position2d<s32>(0,0), target->getSize());

	uint y = img->getDimension().Height;
	uint x = img->getDimension().Width;

	for(uint i = 0; i < y; i++)
	{
		for(uint j = 0; j < x; j++)
		{
			SColor color = img->getPixel(j,i);
			data.push_back((float)(color.getRed()/255.0));
			data.push_back((float)(color.getGreen()/255.0));
			data.push_back((float)(color.getBlue()/255.0));
		}
	}

	img->drop();
	//delete img;
}
Exemplo n.º 14
0
// -----------------------------------------------------------------------------
video::ITexture* IconButtonWidget::getDeactivatedTexture(video::ITexture* texture)
{
#ifdef DO_NOT_USE_IT_CAUSES_BUG_1780_FONT_CORRUPTION
    video::ITexture* t;

    std::string name = texture->getName().getPath().c_str();
    name += "_disabled";
    t = irr_driver->getTexture(name, /*premul*/false, /*prediv*/false,
                                     /*compain_if_not_found*/false);
    if (t == NULL)
    {
        SColor c;
        u32 g;

        video::IVideoDriver* driver = irr_driver->getVideoDriver();
        std::unique_ptr<video::IImage> image (driver->createImageFromData (texture->getColorFormat(),
            texture->getSize(), texture->lock(), false));
        texture->unlock();

        //Turn the image into grayscale
        for (u32 x = 0; x < image->getDimension().Width; x++)
        {
            for (u32 y = 0; y < image->getDimension().Height; y++)
            {
                c = image->getPixel(x, y);
                g = ((c.getRed() + c.getGreen() + c.getBlue()) / 3);
                c.set(std::max (0, (int)c.getAlpha() - 120), g, g, g);
                image->setPixel(x, y, c);
            }
        }

        t = driver->addTexture(name.c_str(), image.get ());
    }

    return t;
#endif
    return texture;
}
Exemplo n.º 15
0
void CD3D8Texture::copy32BitMipMap(char* src, char* tgt,
				   s32 width, s32 height,
				   s32 pitchsrc, s32 pitchtgt) const
{
	SColor c;

	for (int x=0; x<width; ++x)
	{
		for (int y=0; y<height; ++y)
		{
			s32 a=0, r=0, g=0, b=0;

			for (int dx=0; dx<2; ++dx)
			{
				for (int dy=0; dy<2; ++dy)
				{
					int tgx = (x*2)+dx;
					int tgy = (y*2)+dy;

					c = *(u32*)((void*)&src[(tgx<<2)+(tgy*pitchsrc)]);

					a += c.getAlpha();
					r += c.getRed();
					g += c.getGreen();
					b += c.getBlue();
				}
			}

			a >>= 2;
			r >>= 2;
			g >>= 2;
			b >>= 2;

			c = ((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff);
			*(u32*)((void*)&tgt[(x*4)+(y*pitchtgt)]) = c.color;
		}
	}
}
Exemplo n.º 16
0
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
				   s32 width, s32 height,
				   s32 pitchsrc, s32 pitchtgt) const
{
	for (s32 y=0; y<height; ++y)
	{
		for (s32 x=0; x<width; ++x)
		{
			u32 a=0, r=0, g=0, b=0;
			SColor c;

			for (s32 dy=0; dy<2; ++dy)
			{
				const s32 tgy = (y*2)+dy;
				for (s32 dx=0; dx<2; ++dx)
				{
					const s32 tgx = (x*2)+dx;

					c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);

					a += c.getAlpha();
					r += c.getRed();
					g += c.getGreen();
					b += c.getBlue();
				}
			}

			a /= 4;
			r /= 4;
			g /= 4;
			b /= 4;

			c.set(a, r, g, b);
			*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
		}
	}
}
Exemplo n.º 17
0
void PostProcessing::renderFog()
{
    const Track * const track = World::getWorld()->getTrack();

    // This function is only called once per frame - thus no need for setters.
    const float start = track->getFogStart();
    const SColor tmpcol = track->getFogColor();

    core::vector3df col( tmpcol.getRed() / 255.0f,
        tmpcol.getGreen() / 255.0f,
        tmpcol.getBlue() / 255.0f );

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_ONE, GL_ONE);


    FullScreenShader::FogShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture());
    DrawFullScreenEffect<FullScreenShader::FogShader>(1.f / (40.f * start), col);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
}
Exemplo n.º 18
0
SColor Scene::getDiffuse(const vector3df& point, const vector3df& normal, const Material* mat)
{
	SColor ret = mat->getColor();

	SColorf light(0,0,0);
	core::list<Light*>::Iterator it;
	for (it = lights.begin(); it != lights.end(); it++)
	{
		float dot = ((*it)->Position - point).normalize().dotProduct(normal);
		if (dot < 0)
			continue;
		SColorf& lightcol = (*it)->Color;
		float coef = dot * (*it)->getIntensity(point);
		light.r += lightcol.r * coef;
		light.g += lightcol.g * coef;
		light.b += lightcol.b * coef;
	}

	ret.set(255,
		(u32)(ret.getRed() * light.r),
		(u32)(ret.getGreen() * light.g),
		(u32)(ret.getBlue() * light.b));
	return ret;
}
Exemplo n.º 19
0
		bool CImageWriterPCX::writeImage(io::IWriteFile * file, IImage * image, u32 param) const
		{
			if (!file || !image)
			{ return false; }

			u8 d1;
			u16 d2;
			u32 i;

			d1 = 10; // Manufacturer
			file->write(&d1, 1);
			d1 = 5; // Version
			file->write(&d1, 1);
			d1 = 1; // Encoding
			file->write(&d1, 1);
			d1 = 8; // Bits per Pixel
			file->write(&d1, 1);
			d2 = 0; // pixel origin
			file->write(&d2, 2);
			file->write(&d2, 2);
			d2 = image->getDimension().Width - 1; // width
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			d2 = image->getDimension().Height - 1; // height
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			d2 = 300; // dpi
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			file->write(&d2, 2);
			d2 = 0; // palette (not used)
			for (i = 0; i < 24; ++i)
			{
				file->write(&d2, 2);
			}
			d1 = 0; // reserved
			file->write(&d1, 1);
			d1 = 3; // planes
			file->write(&d1, 1);
			d2 = image->getDimension().Width; // pitch
			if (d2 & 0x0001) // must be even
			{ ++d2; }
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			d2 = 1; // color mode
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			d2 = 800; // screen width
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			d2 = 600; // screen height
			#ifdef __BIG_ENDIAN__
			d2 = os::Byteswap::byteswap(d2);
			#endif
			file->write(&d2, 2);
			d2 = 0; // filler (not used)
			for (i = 0; i < 27; ++i)
			{
				file->write(&d2, 2);
			}

			u8 cnt, value;
			for (i = 0; i < image->getDimension().Height; ++i)
			{
				cnt = 0;
				value = 0;
				for (u32 j = 0; j < 3; ++j) // color planes
				{
					for (u32 k = 0; k < image->getDimension().Width; ++k)
					{
						const SColor pix = image->getPixel(k, i);
						if ((cnt != 0) && (cnt < 63) &&
						    (((j == 0) && (value == pix.getRed())) ||
						     ((j == 1) && (value == pix.getGreen())) ||
						     ((j == 2) && (value == pix.getBlue()))))
						{
							++cnt;
						}
						else
						{
							if (cnt != 0)
							{
								if ((cnt > 1) || ((value & 0xc0) == 0xc0))
								{
									cnt |= 0xc0;
									file->write(&cnt, 1);
								}
								file->write(&value, 1);
							}
							cnt = 1;
							if (j == 0)
							{ value = (u8)pix.getRed(); }
							else if (j == 1)
							{ value = (u8)pix.getGreen(); }
							else if (j == 2)
							{ value = (u8)pix.getBlue(); }
						}
					}
				}
				if ((cnt > 1) || ((value & 0xc0) == 0xc0))
				{
					cnt |= 0xc0;
					file->write(&cnt, 1);
				}
				file->write(&value, 1);
			}

			return true;
		}
void IWeatherManagerAtmosphere::update()
{
        updateTimer();
        SColor sp;
        J=J+(((double)dayspeed/86400)/1000.0f)*dTime;

        //if interpolation is finished then start again
        if(time_int_step==0.0f)
        {
            //calculate sun interpolation positions
            prep_interpolation(J,sun_interpolation_speed*J1minute);
        JulianToDate(J);
        counter_time=0.0f;
        }//1440

        //printf("%8.4f %4.8f\n",J,time_int_step);
        //---move sun billboard to sun place
        counter_time+=J-J1;//1440
        time_int_step=counter_time/(sun_interpolation_speed*J1minute);//(1.0f/(sun_interpolation_speed*(1.0f/1440.0f)))*dTime;
        vector3df sun_place=getInterpolated3df(sun_pos_from,sun_pos_to, time_int_step);
        J1=J;
        ICameraSceneNode *cam=smgr->getActiveCamera();
        core::vector3df cameraPos = cam->getAbsolutePosition();
        core::vector3df vt;//billboard position
        vt.X=sun_place.X+cameraPos.X;
        vt.Y=sun_place.Y+cameraPos.Y;
        vt.Z=sun_place.Z+cameraPos.Z;
        bill->setPosition(vt);

        vt.X=-sun_place.X+cameraPos.X;
        vt.Y=-sun_place.Y+cameraPos.Y;
        vt.Z=-sun_place.Z+cameraPos.Z;
        bill->setMoonPosition(vt);

        // sunlight->setPosition(vt);
        //---sun movement end
        f32 inv = 1.0f - time_int_step;
        uvX=((sun_angle_from *inv + sun_angle_to*time_int_step)+90.0f)/180;

        if(time_int_step>=1.0f)
            time_int_step=0.0f;

        sp=skyimage->getPixel((int)round(128*uvX),117); // Y = 123
        //driver->setAmbientLight(SColor(255,sp.getRed(),sp.getGreen(),sp.getBlue()));
        //printf("vt %3.4f",getSunYAngle());

        ClearColor = SColor(255,sp.getRed(),sp.getGreen(),sp.getBlue());

        if(UpdateFog)
        {
            SColor fogColor; E_FOG_TYPE fogType; f32 fogStart;
            f32 fogEnd; f32 fogDensity; bool pixelFog; bool rangeFog;

            driver->getFog(fogColor,fogType,fogStart,fogEnd,fogDensity,pixelFog,rangeFog);
            driver->setFog(ClearColor,fogType,fogStart,fogEnd,fogDensity,pixelFog,rangeFog);
        }

        if (getSunYAngle()<0.0042)
        {//isjungti lenpa kai naktis
            sunlight->setVisible(false);
            setAmbientLight2(SColor(255,sp.getRed(),sp.getGreen(),sp.getBlue()));
        }

        else
        {
            sunlight->setVisible(true);
            setAmbientLight2(SColor(255,sp.getRed(),sp.getGreen(),sp.getBlue()));//bug fix
        }
        // smgr->setShadowColor(SColor(50,sp.getRed(),sp.getGreen(),sp.getBlue()));
        //sunlight->getLightData().DiffuseColor=SColor(255,sp.getRed(),sp.getGreen(),sp.getBlue());
        Sky->setuvX(uvX);

        startTime = currentTime;
}
Exemplo n.º 21
0
/** Render the post-processed scene */
void PostProcessing::render()
{
    if (!irr_driver->isGLSL()) return;

    IVideoDriver * const drv = irr_driver->getVideoDriver();
    drv->setTransform(ETS_WORLD, core::IdentityMatrix);
    drv->setTransform(ETS_VIEW, core::IdentityMatrix);
    drv->setTransform(ETS_PROJECTION, core::IdentityMatrix);

    MotionBlurProvider * const mocb = (MotionBlurProvider *) irr_driver->
                                                           getCallback(ES_MOTIONBLUR);
    GaussianBlurProvider * const gacb = (GaussianBlurProvider *) irr_driver->
                                                                 getCallback(ES_GAUSSIAN3H);

    const u32 cams = Camera::getNumCameras();
    for(u32 cam = 0; cam < cams; cam++)
    {
        scene::ICameraSceneNode * const camnode =
            Camera::getCamera(cam)->getCameraSceneNode();
        mocb->setCurrentCamera(cam);
        ITexture *in = irr_driver->getRTT(RTT_COLOR);
        ITexture *out = irr_driver->getRTT(RTT_TMP1);
	// Each effect uses these as named, and sets them up for the next effect.
	// This allows chaining effects where some may be disabled.

	// As the original color shouldn't be touched, the first effect can't be disabled.

        PROFILER_PUSH_CPU_MARKER("- Bloom", 0xFF, 0x00, 0x00);
        if (1) // bloom
        {
			// Blit the base to tmp1
			drv->setRenderTarget(out, true, false);
			renderPassThrough(in);

            const bool globalbloom = World::getWorld()->getTrack()->getBloom();

            if (globalbloom)
            {
				drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
				renderBloom(in);
            }


            if (globalbloom)
            {
                // Clear the alpha to a suitable value, stencil
                glClearColor(0, 0, 0, 0.1f);
                glColorMask(0, 0, 0, 1);

                glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

                glClearColor(0, 0, 0, 0);
                glColorMask(1, 1, 1, 1);

                // To half
                drv->setRenderTarget(irr_driver->getRTT(RTT_HALF1), true, false);
				renderPassThrough(irr_driver->getRTT(RTT_TMP3));


                // To quarter
				drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), true, false);
				renderPassThrough(irr_driver->getRTT(RTT_HALF1));
                
                // To eighth
				drv->setRenderTarget(irr_driver->getRTT(RTT_EIGHTH1), true, false);
				renderPassThrough(irr_driver->getRTT(RTT_QUARTER1));

                // Blur it for distribution.
				renderGaussian6Blur(irr_driver->getRTT(RTT_EIGHTH1), irr_driver->getRTT(RTT_EIGHTH2), 8.f / UserConfigParams::m_width, 8.f / UserConfigParams::m_height);

                // Additively blend on top of tmp1
				drv->setRenderTarget(out, false, false);
				renderBloomBlend(irr_driver->getRTT(RTT_EIGHTH1));
            } // end if bloom

            in = irr_driver->getRTT(RTT_TMP1);
            out = irr_driver->getRTT(RTT_TMP2);
        }
        PROFILER_POP_CPU_MARKER();

        PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00);
        if (m_sunpixels > 30)//World::getWorld()->getTrack()->hasGodRays() && ) // god rays
        {
            // Grab the sky
            drv->setRenderTarget(out, true, false);
//            irr_driver->getSceneManager()->drawAll(ESNRP_SKY_BOX);
            irr_driver->renderSkybox();

            // Set the sun's color
            const SColor col = World::getWorld()->getTrack()->getSunColor();
            ColorizeProvider * const colcb = (ColorizeProvider *) irr_driver->getCallback(ES_COLORIZE);
                colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f);

            // The sun interposer
            STKMeshSceneNode *sun = irr_driver->getSunInterposer();
/*            sun->getMaterial(0).ColorMask = ECP_ALL;
            irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_SOLID);*/
            irr_driver->getSceneManager()->drawAll(ESNRP_CAMERA);
            irr_driver->setPhase(GLOW_PASS);
            sun->render();

            //sun->getMaterial(0).ColorMask = ECP_NONE;

            // Fade to quarter

            drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), false, false);
            renderGodFade(getTextureGLuint(out), col);


            // Blur
			renderGaussian3Blur(irr_driver->getRTT(RTT_QUARTER1),
                                irr_driver->getRTT(RTT_QUARTER2),
                                4.f / UserConfigParams::m_width,
                                4.f / UserConfigParams::m_height);



            // Calculate the sun's position in texcoords
            const core::vector3df pos = sun->getPosition();
            float ndc[4];
            core::matrix4 trans = camnode->getProjectionMatrix();
            trans *= camnode->getViewMatrix();

            trans.transformVect(ndc, pos);

            const float texh = m_vertices[cam].v1.TCoords.Y - m_vertices[cam].v0.TCoords.Y;
            const float texw = m_vertices[cam].v3.TCoords.X - m_vertices[cam].v0.TCoords.X;

            const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw;
            const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh;

//            ((GodRayProvider *) irr_driver->getCallback(ES_GODRAY))->
//                setSunPosition(sunx, suny);

            // Rays please
            drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER2), true, false);
            renderGodRay(getTextureGLuint(irr_driver->getRTT(RTT_QUARTER1)), core::vector2df(sunx, suny));

            // Blur
            renderGaussian3Blur(irr_driver->getRTT(RTT_QUARTER2),
                irr_driver->getRTT(RTT_QUARTER1),
                4.f / UserConfigParams::m_width,
                4.f / UserConfigParams::m_height);

            // Blend
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE);
            glBlendEquation(GL_FUNC_ADD);

            drv->setRenderTarget(in, false, false);
            renderPassThrough(irr_driver->getRTT(RTT_QUARTER2));
        }
        PROFILER_POP_CPU_MARKER();

        if (UserConfigParams::m_motionblur && m_any_boost) // motion blur
        {
            PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
            renderMotionBlur(cam, in, out);
            ITexture *tmp = in;
            in = out;
            out = tmp;
            PROFILER_POP_CPU_MARKER();
        }

        if (irr_driver->getDisplacingNodes().size()) // Displacement
        {
            PROFILER_PUSH_CPU_MARKER("- Displacement", 0xFF, 0x00, 0x00);
			drv->setRenderTarget(out, true, false);
			renderPPDisplace(in);

            ITexture *tmp = in;
            in = out;
            out = tmp;
            PROFILER_POP_CPU_MARKER();
        }

/*        m_material.MaterialType = irr_driver->getShader(ES_RAIN);
        drv->setMaterial(m_material);
        static_cast<irr::video::COpenGLDriver*>(drv)->setRenderStates3DMode();*/

        if (UserConfigParams::m_mlaa) // MLAA. Must be the last pp filter.
        {
            PROFILER_PUSH_CPU_MARKER("- MLAA", 0xFF, 0x00, 0x00);
            drv->setRenderTarget(out, false, false);

            glEnable(GL_STENCIL_TEST);
            glClearColor(0.0, 0.0, 0.0, 1.0);
            glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
            glStencilFunc(GL_ALWAYS, 1, ~0);
            glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

            // Pass 1: color edge detection
            m_material.setFlag(EMF_BILINEAR_FILTER, false);
            m_material.setFlag(EMF_TRILINEAR_FILTER, false);
            m_material.MaterialType = irr_driver->getShader(ES_MLAA_COLOR1);
            m_material.setTexture(0, in);

            drawQuad(cam, m_material);
            m_material.setFlag(EMF_BILINEAR_FILTER, true);
            m_material.setFlag(EMF_TRILINEAR_FILTER, true);

            glStencilFunc(GL_EQUAL, 1, ~0);
            glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

            // Pass 2: blend weights
            drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);

            m_material.MaterialType = irr_driver->getShader(ES_MLAA_BLEND2);
            m_material.setTexture(0, out);
            m_material.setTexture(1, m_areamap);
            m_material.TextureLayer[1].BilinearFilter = false;
            m_material.TextureLayer[1].TrilinearFilter = false;

            drawQuad(cam, m_material);

            m_material.TextureLayer[1].BilinearFilter = true;
            m_material.TextureLayer[1].TrilinearFilter = true;
            m_material.setTexture(1, 0);

            // Pass 3: gather
            drv->setRenderTarget(in, false, false);

            m_material.setFlag(EMF_BILINEAR_FILTER, false);
            m_material.setFlag(EMF_TRILINEAR_FILTER, false);
            m_material.MaterialType = irr_driver->getShader(ES_MLAA_NEIGH3);
            m_material.setTexture(0, irr_driver->getRTT(RTT_TMP3));
            m_material.setTexture(1, irr_driver->getRTT(RTT_COLOR));

            drawQuad(cam, m_material);

            m_material.setFlag(EMF_BILINEAR_FILTER, true);
            m_material.setFlag(EMF_TRILINEAR_FILTER, true);
            m_material.setTexture(1, 0);

            // Done.
            glDisable(GL_STENCIL_TEST);
            PROFILER_POP_CPU_MARKER();
        }

        // Final blit
		// TODO : Use glBlitFramebuffer
		drv->setRenderTarget(ERT_FRAME_BUFFER, false, false);
        if (irr_driver->getNormals())
			renderPassThrough(irr_driver->getRTT(RTT_NORMAL_AND_DEPTH));
        else if (irr_driver->getSSAOViz())
			renderPassThrough(irr_driver->getRTT(RTT_SSAO));
        else
			renderColorLevel(in);
    }
}   // render
Exemplo n.º 22
0
void SerializeOutSColor(ostream& os, SColor& color)
{
	os << color.getAlpha()<< endl << color.getRed() << endl << color.getGreen() << endl << color.getBlue() << endl;
}
Exemplo n.º 23
0
/** Render the post-processed scene */
FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, bool isRace)
{
    FrameBuffer *in_fbo = &irr_driver->getFBO(FBO_COLORS);
    FrameBuffer *out_fbo = &irr_driver->getFBO(FBO_TMP1_WITH_DS);
    // Each effect uses these as named, and sets them up for the next effect.
    // This allows chaining effects where some may be disabled.

    // As the original color shouldn't be touched, the first effect can't be disabled.
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);

    if (isRace && UserConfigParams::m_dof)
    {
        PROFILER_PUSH_CPU_MARKER("- DoF", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_DOF));
        renderDoF(*out_fbo, in_fbo->getRTT()[0]);
        std::swap(in_fbo, out_fbo);
        PROFILER_POP_CPU_MARKER();
    }

    {
        PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_GODRAYS));
        bool hasgodrays = false;
        if (World::getWorld() != NULL)
            hasgodrays = World::getWorld()->getTrack()->hasGodRays();

        if (isRace && UserConfigParams::m_light_shaft && hasgodrays)
        {
            Track* track = World::getWorld()->getTrack();

            glEnable(GL_DEPTH_TEST);
            // Grab the sky
            out_fbo->Bind();
            glClear(GL_COLOR_BUFFER_BIT);
//            irr_driver->renderSkybox(camnode);

            // Set the sun's color
            const SColor col = track->getGodRaysColor();
            ColorizeProvider * const colcb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
            colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f);

            // The sun interposer
            STKMeshSceneNode *sun = irr_driver->getSunInterposer();
            sun->setGlowColors(col);
            sun->setPosition(track->getGodRaysPosition());
            sun->updateAbsolutePosition();
            irr_driver->setPhase(GLOW_PASS);
            sun->render();
            glDisable(GL_DEPTH_TEST);

            // Fade to quarter
            irr_driver->getFBO(FBO_QUARTER1).Bind();
            glViewport(0, 0, UserConfigParams::m_width / 4, UserConfigParams::m_height / 4);
            renderGodFade(out_fbo->getRTT()[0], col);

            // Blur
            renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER1), irr_driver->getFBO(FBO_QUARTER2));

            // Calculate the sun's position in texcoords
            const core::vector3df pos = track->getGodRaysPosition();
            float ndc[4];
            core::matrix4 trans = camnode->getProjectionMatrix();
            trans *= camnode->getViewMatrix();

            trans.transformVect(ndc, pos);

            const float texh = m_vertices[0].v1.TCoords.Y - m_vertices[0].v0.TCoords.Y;
            const float texw = m_vertices[0].v3.TCoords.X - m_vertices[0].v0.TCoords.X;

            const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw;
            const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh;

            // Rays please
            irr_driver->getFBO(FBO_QUARTER2).Bind();
            renderGodRay(irr_driver->getRenderTargetTexture(RTT_QUARTER1), core::vector2df(sunx, suny));

            // Blur
            renderGaussian3Blur(irr_driver->getFBO(FBO_QUARTER2), irr_driver->getFBO(FBO_QUARTER1));

            // Blend
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE);
            glBlendEquation(GL_FUNC_ADD);

            in_fbo->Bind();
            renderPassThrough(irr_driver->getRenderTargetTexture(RTT_QUARTER2));
            glDisable(GL_BLEND);
        }
        PROFILER_POP_CPU_MARKER();
    }

    // Simulate camera defects from there

    {
        PROFILER_PUSH_CPU_MARKER("- Bloom", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_BLOOM));
        if (isRace && UserConfigParams::m_bloom)
        {
            glClear(GL_STENCIL_BUFFER_BIT);
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

            FrameBuffer::Blit(*in_fbo, irr_driver->getFBO(FBO_BLOOM_1024), GL_COLOR_BUFFER_BIT, GL_LINEAR);

            irr_driver->getFBO(FBO_BLOOM_512).Bind();
            renderBloom(irr_driver->getRenderTargetTexture(RTT_BLOOM_1024));

            // Downsample
            FrameBuffer::Blit(irr_driver->getFBO(FBO_BLOOM_512), irr_driver->getFBO(FBO_BLOOM_256), GL_COLOR_BUFFER_BIT, GL_LINEAR);
            FrameBuffer::Blit(irr_driver->getFBO(FBO_BLOOM_256), irr_driver->getFBO(FBO_BLOOM_128), GL_COLOR_BUFFER_BIT, GL_LINEAR);

            // Blur
            renderGaussian6Blur(irr_driver->getFBO(FBO_BLOOM_512), irr_driver->getFBO(FBO_TMP_512));

            renderGaussian6Blur(irr_driver->getFBO(FBO_BLOOM_256), irr_driver->getFBO(FBO_TMP_256));

            renderGaussian6Blur(irr_driver->getFBO(FBO_BLOOM_128), irr_driver->getFBO(FBO_TMP_128));

            // Additively blend on top of tmp1
            in_fbo->Bind();
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE);
            glBlendEquation(GL_FUNC_ADD);
            FullScreenShader::BloomBlendShader::getInstance()->SetTextureUnits(createVector<GLuint>(
                irr_driver->getRenderTargetTexture(RTT_BLOOM_128), irr_driver->getRenderTargetTexture(RTT_BLOOM_256), irr_driver->getRenderTargetTexture(RTT_BLOOM_512) ));
            DrawFullScreenEffect<FullScreenShader::BloomBlendShader>();

            glDisable(GL_BLEND);
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        } // end if bloom
        PROFILER_POP_CPU_MARKER();
    }

    //computeLogLuminance(in_rtt);
    {
        PROFILER_PUSH_CPU_MARKER("- Tonemap", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TONEMAP));
        toneMap(*out_fbo, in_fbo->getRTT()[0]);
        std::swap(in_fbo, out_fbo);
        PROFILER_POP_CPU_MARKER();
    }

    {
        PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MOTIONBLUR));
        if (isRace && UserConfigParams::m_motionblur && World::getWorld() != NULL) // motion blur
        {
            renderMotionBlur(0, *in_fbo, *out_fbo);
            std::swap(in_fbo, out_fbo);
        }
        PROFILER_POP_CPU_MARKER();
    }

    // Workaround a bug with srgb fbo on sandy bridge windows
    if (irr_driver->needUBOWorkaround())
        return in_fbo;

    glEnable(GL_FRAMEBUFFER_SRGB);
    irr_driver->getFBO(FBO_MLAA_COLORS).Bind();
    renderPassThrough(in_fbo->getRTT()[0]);
    out_fbo = &irr_driver->getFBO(FBO_MLAA_COLORS);

    if (UserConfigParams::m_mlaa) // MLAA. Must be the last pp filter.
    {
        PROFILER_PUSH_CPU_MARKER("- MLAA", 0xFF, 0x00, 0x00);
        ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MLAA));
        applyMLAA();
        PROFILER_POP_CPU_MARKER();
    }
    glDisable(GL_FRAMEBUFFER_SRGB);

    return out_fbo;
}   // render
Exemplo n.º 24
0
//! @brief render big software image of any size using either screen to render or offscreen texture ( can flicker )
bool renderToImage( IrrlichtDevice* device, IImage* dst, s32 nSamples, const SColor& clearColor, bool renderGUI, bool debugLog)
{
	// print call params
	if (debugLog)
		printf(	"renderToImage( nSamples=%i, clearColor(%i,%i,%i,%i)\n", nSamples,
			clearColor.getAlpha(), clearColor.getRed(), clearColor.getGreen(), clearColor.getBlue() );

	// abort
    if (!device)
	{
		printf("No Irrlicht-Device found.\n");
        return false;
	}

	// abort
    if (!dst)
	{
		printf("No destination image found.\n");
        return false;
	}

	// local pointers
	IVideoDriver* driver = device->getVideoDriver();
	gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
	scene::ISceneManager* smgr = device->getSceneManager();
	scene::ICameraSceneNode* camera = smgr->getActiveCamera();

	// abort
	if (!camera)
	{
		printf("No active camera found.\n");
		return false;
	}

	//! decompose camera's projection-matrix in d3d semantics

	core::matrix4 projMat = camera->getProjectionMatrix();

	bool IsOrthogonal = true;

	if ( core::equals( projMat(3,3), 0.f ) )
		IsOrthogonal = false;

	if ( !core::equals( projMat(2,3), 0.f ) )
		IsOrthogonal = false;

    f32 Left;
    f32 Right;
    f32 Bottom;
    f32 Top;
    f32 Near;
    f32 Far;

	if (IsOrthogonal)
	{
		Near = -projMat(3,2)/projMat(2,2);
		Far = -(projMat(3,2)-1.f)/projMat(2,2);
		Left = -(projMat(3,0)+1.f)/projMat(0,0);
		Right = -(projMat(3,0)-1.f)/projMat(0,0);
		Top = -(projMat(3,1)-1.f)/projMat(1,1);
		Bottom = -(projMat(3,1)+1.f)/projMat(1,1);
	}
	else
	{
		Near = -projMat(3,2)/projMat(2,2);
		Far = -projMat(3,2)/(projMat(2,2)-1.f);
		Left = -Near*(projMat(2,0)+1.f)/projMat(0,0);
		Right = -Near*(projMat(2,0)-1.f)/projMat(0,0);
		Top = -Near*(projMat(2,1)-1.f)/projMat(1,1);
		Bottom = -Near*(projMat(2,1)+1.f)/projMat(1,1);
	}
	Near = camera->getNearValue();	// take the values directly from Camera
	Far = camera->getFarValue();	// due to f32 rounding errors

	//! ----------------------------------------------------------------------
	//! calculate Border / get max thickness used by all registered materials
	//! ----------------------------------------------------------------------

	s32 Border = 0;
	f32 thickness = 0.0f;

    const core::list<scene::ISceneNode*>& children = smgr->getRootSceneNode()->getChildren();
    core::list<scene::ISceneNode*>::ConstIterator it = children.begin();

    while (it != children.end())
	{
		scene::ISceneNode* node = (*it);
		if (node)
		{
			u32 matCount = node->getMaterialCount();
			for (u32 m = 0; m < matCount; ++m)
			{
				if (thickness < node->getMaterial(m).Thickness)
					thickness = node->getMaterial(m).Thickness;
			}
		}
		it++;
	}

	Border = core::ceil32( thickness );

	//! ------------------------------------------------------------------------------------------
	//! choose render-mode: offscreen or onscreen depending on AA, nSamples and RTT capabilities
	//! ------------------------------------------------------------------------------------------

	//! @var nSamples - AntiAliasing depth > 1 make bigger rtts or downscale render-result by factor nSamples while having filter-methods enabled
	//! the framebuffer will always be downscaled by fast software bilinear filtering using colorkey/transparency to blend better into final image
	//! hardware-scaling: bilinear, trilinear or anisotropic texture-filtering available with irrlicht-engine
	//! software scaling: nearest, bilinear, bicubic downscaling available:
	//!  				  bilinear has best compromise for downscaling ( there is much more information-loss due to resize than interpolation)
	//! default: 1 (<2) - no AA/downscaling done

	//! @var clearColor - argb32 color, the final image will filled with
	//! before writing into it and be used as colorkey for AA/software bilinear downscaling operation

	//! @var DoOffscreen - default=false, onscreen (framebuffer)
	//! false -	onscreen-rendering using framebuffer/display.
	//! 		doublebuffer is possible, but will not prevent the showing of each rendered tile-texture
	//! true - 	offscreen-rendering using render-target-textures

	bool DoOffscreen = false;

	//! ----------------------------------------------------------------
	//! collect video-driver infos
	//! ----------------------------------------------------------------

	const core::dimension2du ScreenSize = driver->getScreenSize();
	const ECOLOR_FORMAT ScreenFormat = driver->getColorFormat();
	const u32 ScreenBits = IImage::getBitsPerPixelFromFormat( ScreenFormat );
    const io::IAttributes& info = driver->getDriverAttributes();
    const core::dimension2du MaxRTTSize = driver->getMaxTextureSize();
    const u32 MaxAA = info.getAttributeAsInt( "AntiAlias" );
    const u32 MaxAF = info.getAttributeAsInt( "MaxAnisotropy" );
    const bool HasNPOT = driver->queryFeature( EVDF_TEXTURE_NPOT );
    const bool HasNSQR = driver->queryFeature( EVDF_TEXTURE_NSQUARE );
	const bool HasRTT = driver->queryFeature( EVDF_RENDER_TO_TARGET);
	const bool HasMTT = driver->queryFeature( EVDF_MULTITEXTURE);
	const bool HasMRT = driver->queryFeature( EVDF_MULTIPLE_RENDER_TARGETS);
	const bool HasATC = driver->queryFeature( EVDF_ALPHA_TO_COVERAGE);
	const bool HasBTF = driver->queryFeature( EVDF_BILINEAR_FILTER);
	const bool HasCMK = driver->queryFeature( EVDF_COLOR_MASK);
	const bool HasMMP = driver->queryFeature( EVDF_MIP_MAP);
	const bool HasMMA = driver->queryFeature( EVDF_MIP_MAP_AUTO_UPDATE);
	const bool HasOCC = driver->queryFeature( EVDF_OCCLUSION_QUERY);
	const bool HasPOF = driver->queryFeature( EVDF_POLYGON_OFFSET);

	if (debugLog)
	{
		printf("ScreenSize = %i x %i x %i\n", ScreenSize.Width, ScreenSize.Height, ScreenBits);
		printf("MaxRTTSize = %i x %i\n", MaxRTTSize.Width, MaxRTTSize.Height);
		printf("MaxAA = %i\n", MaxAA);
		printf("MaxAF = %i\n", MaxAF);
		printf("HasNPOT = %s\n", HasNPOT?"true":"false");
		printf("HasNSQR = %s\n", HasNSQR?"true":"false");
		printf("HasRTT = %s\n", HasRTT?"true":"false");
		printf("HasMTT = %s\n", HasMTT?"true":"false");
		printf("HasMRT = %s\n", HasMRT?"true":"false");
		printf("HasATC = %s\n", HasATC?"true":"false");
		printf("HasBTF = %s\n", HasBTF?"true":"false");
		printf("HasCMK = %s\n", HasCMK?"true":"false");
		printf("HasMMP = %s\n", HasMMP?"true":"false");
		printf("HasMMA = %s\n", HasMMA?"true":"false");
		printf("HasOCC = %s\n", HasOCC?"true":"false");
		printf("HasPOF = %s\n", HasPOF?"true":"false");
	}

    s32 RTTWidth = ScreenSize.Width;				// equals the actual rtt size before down scaling factor nSamples AA and writing to final Image
    s32 RTTHeight = ScreenSize.Height;				// the render-target is always a texture (offscreen) or the framebuffer (onscreen)
    s32 RTTWidthNB = RTTWidth - 2*Border;			// the border equals the overlapping during rendering due to material-thickness > 0
    s32 RTTHeightNB = RTTHeight - 2*Border;			// the area that gets written to unique places, while the border regions can overlapp ( same pos, but writing/adding different image-content )

	// so the position increment for the final writing is always RTTWidthNB or RTTHeightNB

    const s32 ImageWidth = (s32)dst->getDimension().Width;		// width of the final image
    const s32 ImageHeight = (s32)dst->getDimension().Height;	// height of the final image
    const ECOLOR_FORMAT ImageFormat = dst->getColorFormat();			// color-format of the final image, i.e. ECF_A8R8G8B8, ECF_R8G8B8, ECF_R16 for heightmaps ( bilinear, anisotropic )
	const s32 CountX = core::ceil32( (f32)ImageWidth / (f32)RTTWidthNB );
	const s32 CountY = core::ceil32( (f32)ImageHeight / (f32)RTTHeightNB );

	//! ------------------------------------------------------------------------------------------
	//! start render loop
	//! ------------------------------------------------------------------------------------------

    s32 IndexX = 0;
    s32 IndexY = 0;
	s32 dstX = -Border;
	s32 dstY = -Border;

	for ( IndexY = 0; IndexY < CountY; ++IndexY)
	{
		// reset row
		dstX = -Border;

		for ( IndexX = 0; IndexX < CountX; ++IndexX)
		{
			const f32 fLeft = Left + (Right - Left) * (f32)( IndexX * RTTWidthNB - Border )/(f32)ImageWidth;
			const f32 fRight = fLeft + (Right - Left) * (f32)RTTWidth / (f32)ImageWidth;
			const f32 fTop = Top - (Top - Bottom) * (f32)( IndexY * RTTHeightNB - Border )/(f32)ImageHeight;
			const f32 fBottom = fTop - (Top - Bottom) * (f32)RTTHeight / (f32)ImageHeight;
			const f32 fNear = Near;
			const f32 fFar = Far;

			//! ------------------------------------------------------------------------------------------
			//! build and set current projection-matrix
			//! ------------------------------------------------------------------------------------------

			core::matrix4 tmpProj = core::IdentityMatrix;
			if (IsOrthogonal)
			{
				tmpProj(0,0) = 2.f / (fRight - fLeft);
				tmpProj(1,1) = 2.f / (fTop - fBottom);
				tmpProj(2,2) = 1.f / (fFar - fNear);
				tmpProj(3,3) = 1.f;
				tmpProj(3,0) = (fLeft + fRight) / (fLeft - fRight);
				tmpProj(3,1) = (fTop + fBottom) / (fBottom - fTop);
				tmpProj(3,2) = fNear / (fNear - fFar);
			}
			else
			{
				tmpProj(0,0) = 2.f*fNear / (fRight - fLeft);
				tmpProj(1,1) = 2.f*fNear / (fTop - fBottom);
				tmpProj(2,0) = (fLeft + fRight) / (fLeft - fRight);
				tmpProj(2,1) = (fTop + fBottom) / (fBottom - fTop);
				tmpProj(2,2) = fFar / (fFar - fNear);
				tmpProj(2,3) = 1.f;
				tmpProj(3,2) = fNear*fFar / (fNear - fFar);
				tmpProj(3,3) = 0.f;
			}
			camera->setProjectionMatrix(tmpProj);

			//! ------------------------------------------------------------------------------------------
			//! now render all to current render-target
			//! ------------------------------------------------------------------------------------------

			driver->beginScene( true, true, clearColor ); // SColor(255,200,200,255)

				smgr->drawAll();
				if (renderGUI)
					guienv->drawAll();

			driver->endScene();

			//! ------------------------------------------------------------------------------------------
			//! write current render-target to final image
			//! ------------------------------------------------------------------------------------------

			IImage* src = driver->createScreenShot( ImageFormat, ERT_FRAME_BUFFER);
			if (src)
			{
				s32 x2 = src->getDimension().Width;
				s32 y2 = src->getDimension().Height;

				blitImageToImage( dst, core::position2di(dstX, dstY), src, core::recti(Border, Border, x2-Border, y2-Border), debugLog );

				src->drop();
			}
			dstX += RTTWidthNB;
		}
		dstY += RTTHeightNB;
	}

	//! ------------------------------------------------------------------------------------------
	//! reset camera's projection-matrix
	//! ------------------------------------------------------------------------------------------

	camera->setProjectionMatrix( projMat, IsOrthogonal);
    return true;
}