// ----------------------------------------------------------------------------- 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; }
//! 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; }
//! 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; }
// ---------------------------------------------------------------------------- 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
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 }
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; } } }
// ----------------------------------------------------------------------------- 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; }
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; } } }
int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed Device = createDevice(driverType, core::dimension2d<u32>(640, 480)); if(Device == NULL) return 1; IVideoDriver *Driver = Device->getVideoDriver(); IGUIEnvironment* env = Device->getGUIEnvironment(); ISceneManager *Scene = Device->getSceneManager(); Scene->addCameraSceneNode(0, vector3df(0,10,-40), vector3df(0,0,0)); MyEventReceiver receiver; Device->setEventReceiver(&receiver); // Load fonts fonts[0] = env->getFont(FONTPATH1, SIZE_FONT_NORMAL); fonts[1] = env->getFont(FONTPATH1, SIZE_FONT_BIG); fonts[2] = env->getFont(FONTPATH2, SIZE_FONT_NORMAL); fonts[3] = env->getFont(FONTPATH2, SIZE_FONT_BIG); fonts[4] = env->getFont(FONTPATH3, SIZE_FONT_NORMAL); fonts[5] = env->getFont(FONTPATH3, SIZE_FONT_BIG); for( int i = 0; i < 6; ++i ) { fonts[i]->setBatchLoadSize(1); fonts[i]->setMaxPageTextureSize( dimension2du(512, 512) ); } font = fonts[0]; font2 = fonts[1]; skin = env->getSkin(); skin->setFont(font); txtTrans = env->addStaticText(L"Transparency:", rect<s32>(50,20,250,40), true); IGUIScrollBar* scrollbar = env->addScrollBar(true, rect<s32>(50, 45, 250, 60), 0, 104); scrollbar->setMax(255); SColor col = env->getSkin()->getColor((EGUI_DEFAULT_COLOR)0); scrollbar->setPos(col.getAlpha()); txtLog = env->addStaticText(L"Logging ListBox:", rect<s32>(50,80,250,100), true); listbox = env->addListBox(rect<s32>(50, 110, 250, 180)); btnQuit = env->addButton(rect<s32>(10,210,100,240), 0, 101, L"Quit"); btnNew = env->addButton(rect<s32>(10,250,100,290), 0, 102, L"New Window"); btnFile = env->addButton(rect<s32>(10,300,100,340), 0, 103, L"Open File"); edtName = env->addEditBox(L"",rect<s32>(300,60,580,80)); edtName->setMax(40); edtMemo = env->addEditBox(L"",rect<s32>(300,100,580,450)); edtMemo->setMultiLine(true); edtMemo->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); lstLang = env->addListBox(rect<s32>(10, 400, 250, 470),0,120); lstLang->addItem(L"Arial"); lstLang->addItem(L"Times Roman"); lstLang->addItem(L"MS-Gothic(Japanese)"); lstLang->setSelected(0); int lastFPS = -1; while(Device->run()) { Driver->beginScene(true, true, SColor(0,64,64,128)); Scene->drawAll(); env->drawAll(); if (!lang){ font2->draw(L"Hello TrueType",rect<s32>(250,20,640,100),SColor(255,255,64,64),true); } else { //font2->draw(jtxtHello,rect<s32>(250,20,640,100),SColor(255,255,64,64),true); font2->draw(zhtwHello,rect<s32>(100,100,640,100),SColor(255,255,64,64),false); } Driver->endScene(); int fps = Driver->getFPS(); if (lastFPS != fps) { wchar_t tmp[1024]; swprintf(tmp, L"Irrlicht TrueType Demo (fps:%d)", fps); Device->setWindowCaption(tmp); lastFPS = fps; } } Device->drop(); return 0; }
// Methods for Software drivers, non-virtual and not necessary to copy into other image classes //! draws a rectangle void CImage::drawRectangle(const core::rect<s32>& rect, const SColor &color) { Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, this, 0, &rect.UpperLeftCorner, 0, &rect, color.color); }
void SerializeOutSColor(ostream& os, SColor& color) { os << color.getAlpha()<< endl << color.getRed() << endl << color.getGreen() << endl << color.getBlue() << endl; }
//! @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; }