//! constructor CSoftwareTexture::CSoftwareTexture(IImage* image, const char* name) : ITexture(name), Texture(0) { #ifdef _DEBUG setDebugName("CSoftwareTexture"); #endif if (image) { core::dimension2d<s32> optSize; core::dimension2d<s32> origSize = image->getDimension(); OrigSize = origSize; optSize.Width = getTextureSizeFromSurfaceSize(origSize.Width); optSize.Height = getTextureSizeFromSurfaceSize(origSize.Height); Image = new CImage(ECF_A1R5G5B5, image); if (optSize == origSize) { Texture = Image; Texture->grab(); } else { Texture = new CImage(ECF_A1R5G5B5, optSize); Image->copyToScaling(Texture); } } }
void CD3D8Texture::createRenderTarget() { TextureSize.Width = getTextureSizeFromSurfaceSize(TextureSize.Width); TextureSize.Height = getTextureSizeFromSurfaceSize(TextureSize.Height); // get backbuffer format to create the render target in the // same format IDirect3DSurface8* bb; D3DFORMAT d3DFormat = D3DFMT_A8R8G8B8; if (!FAILED(Device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &bb))) { D3DSURFACE_DESC desc; bb->GetDesc(&desc); d3DFormat = desc.Format; if (d3DFormat == D3DFMT_X8R8G8B8) d3DFormat = D3DFMT_A8R8G8B8; bb->Release(); } else { os::Printer::log("Could not create RenderTarget texture: could not get BackBuffer.", ELL_WARNING); return; } // create texture HRESULT hr; hr = Device->CreateTexture( TextureSize.Width, TextureSize.Height, 1, // mip map level count, we don't want mipmaps here D3DUSAGE_RENDERTARGET, d3DFormat, D3DPOOL_DEFAULT, &Texture); // get irrlicht format from D3D format ColorFormat = getColorFormatFromD3DFormat(d3DFormat); if (FAILED(hr)) os::Printer::log("Could not create render target texture"); }
void CImpostorSceneNode::setTarget(SNodeLink& Imp) { s32 realsize = getTextureSizeFromSurfaceSize( core::max_<s32>(Imp.ScreenPos.getWidth(), Imp.ScreenPos.getHeight())); bool newTex = false; if (Imp.BufferID == -1) { getSlot(Imp, realsize); } else if (Buffers[Imp.BufferID].SlotSize != realsize) { getSlot(Imp, realsize); } //printf("setting texture at address %x size=%d\n", Textures[Impostors[i].BufferID].Texture, realsize); LocalManager->getVideoDriver()->setRenderTarget(WorkTexture, true, true); //LocalManager->getVideoDriver()->setViewPort(core::rect<s32>(0,0,realsize, realsize)); }
void CImpostorSceneNode::OnRegisterSceneNode() { if (!IsVisible) return; RenderCount++; // in here we: // decide which nodes need updates, add them to the queue // process the render queue // allocate textures and mesh buffers if required // perform clean up tasks: // garbage collection- free up spaces // reorganise // get collision manager ISceneCollisionManager* colmgr = SceneManager->getSceneCollisionManager(); // and the active camera ICameraSceneNode* cam = SceneManager->getActiveCamera(); core::aabbox3df camBB = cam->getViewFrustum()->getBoundingBox(); u32 now = Timer->getRealTime(); // loop through all impostor nodes u32 i; for (i=0; i < Impostors.size(); ++i) { SNodeLink &Imp = Impostors[i]; ISceneNode *n = Imp.Node; // skip invisible and culled nodes if (!n->isVisible() || !camBB.intersectsWithBox(n->getTransformedBoundingBox())) { //Culled++; Imp.IsActive = false; continue; } updatePosAndVector(Imp); // now we have the screen position... core::rect<s32> r = SceneManager->getVideoDriver()->getViewPort(); if (!Imp.NewPos.isValid() || !r.isRectCollided(Imp.NewPos) ) { // culled // Culled++; continue; } core::dimension2di newSize = Imp.NewPos.getSize(); // Change in rotation: a.length >= a.dotProduct(b) <= -a.length f32 diff = 0; // far plane = never update, near plane = always update f32 far = cam->getFarValue(); far *= far; f32 dist = Imp.Node->getAbsolutePosition().getDistanceFromSQ(cam->getAbsolutePosition()); dist = 1.0 - (far/dist); // value between 0 and 1 diff = dist; Imp.Score = dist; //s32 a = core::max_<s32>(Imp.NewPos.getWidth(), Imp.NewPos.getHeight()); //diff *= f32(a); bool reRender = diff > Threshold; //reRender =true; reRender = reRender || ( !Imp.IsQueued && Imp.BufferID != -1 && Buffers[Imp.BufferID].SlotSize < getTextureSizeFromSurfaceSize(core::max_<s32>(newSize.Width, newSize.Height))); // so small that we don't care about it if (newSize.Width < 4 || newSize.Height < 4) { Imp.IsActive = false; // object was culled //Culled++; continue; } // too large to fit in a texture slot if (newSize.Width > MaxSize || newSize.Height > MaxSize) { // get rid releaseSlot(Imp); Imp.IsActive = false; } else { Imp.IsActive = true; } if (Imp.IsActive && Imp.BufferID == -1 && !Imp.IsQueued ) reRender = true; if (Imp.IsActive) { // impostor replaces the node if (reRender && now > Imp.Time + MinTime) { if (!Imp.IsQueued) { CacheMisses++; Imp.IsQueued = true; SRenderQueueItem q; q.Node = &Imp; //q.Value = val; RenderQueue.push_back(q); } else { //QueueHits++; } } else { // don't re-render the impostor texture, only draw it CacheHits++; } } if (!Imp.IsActive) // || ( Imp.BufferID == -1 && Imp.IsQueued)) { // original node is visible n->OnRegisterSceneNode(); // cache miss CacheMisses++; } } SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); }