//----------------------------------------------------------------------- void CompositorInstance::createResources() { static size_t dummyCounter = 0; freeResources(); /// Create temporary textures /// In principle, temporary textures could be shared between multiple viewports /// (CompositorChains). This will save a lot of memory in case more viewports /// are composited. CompositionTechnique::TextureDefinitionIterator it = mTechnique->getTextureDefinitionIterator(); while(it.hasMoreElements()) { CompositionTechnique::TextureDefinition *def = it.getNext(); /// Determine width and height int width = def->width.adjust + static_cast<int>(mChain->getViewport()->getActualWidth() * def->width.viewport) + static_cast<int>(mChain->getViewport()->getActualWidth() * def->width.previous); // FIXME int height = def->height.adjust + static_cast<int>(mChain->getViewport()->getActualHeight() * def->height.viewport) + static_cast<int>(mChain->getViewport()->getActualHeight() * def->height.previous); // FIXME if (width <= 0) { // Throw exception? Not that case, because user can't guarantee // provides correct parameters always, since it might related to // viewport dimensions which can't control by user all the way. width = 1; } if (height <= 0) { // Throw exception? Not that case, because user can't guarantee // provides correct parameters always, since it might related to // viewport dimensions which can't control by user all the way. height = 1; } /// Make the tetxure TexturePtr tex = TextureManager::getSingleton().createManual( "CompositorInstanceTexture"+StringConverter::toString(dummyCounter), ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)width, (uint)height, 0, def->format, TU_RENDERTARGET ); ++dummyCounter; mLocalTextures[def->name] = tex; /// Set up viewport over entire texture RenderTexture *rtt = tex->getBuffer()->getRenderTarget(); rtt->setAutoUpdated( false ); Camera* camera = mChain->getViewport()->getCamera(); // Save last viewport and current aspect ratio Viewport* oldViewport = camera->getViewport(); Real aspectRatio = camera->getAspectRatio(); Viewport* v = rtt->addViewport( camera ); v->setClearEveryFrame( false ); v->setOverlaysEnabled( false ); v->setBackgroundColour( ColourValue( 0, 0, 0, 0 ) ); // Should restore aspect ratio, in case of auto aspect ratio // enabled, it'll changed when add new viewport. camera->setAspectRatio(aspectRatio); // Should restore last viewport, i.e. never disturb user code // which might based on that. camera->_notifyViewport(oldViewport); } }
//----------------------------------------------------------------------- void Compositor::createGlobalTextures() { static size_t dummyCounter = 0; if (mSupportedTechniques.empty()) return; //To make sure that we are consistent, it is demanded that all composition //techniques define the same set of global textures. typedef std::set<String> StringSet; StringSet globalTextureNames; //Initialize global textures from first supported technique CompositionTechnique* firstTechnique = mSupportedTechniques[0]; CompositionTechnique::TextureDefinitionIterator texDefIt = firstTechnique->getTextureDefinitionIterator(); while (texDefIt.hasMoreElements()) { CompositionTechnique::TextureDefinition* def = texDefIt.getNext(); if (def->scope == CompositionTechnique::TS_GLOBAL) { //Check that this is a legit global texture if (!def->refCompName.empty()) { OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "Global compositor texture definition can not be a reference", "Compositor::createGlobalTextures"); } if (def->width == 0 || def->height == 0) { OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "Global compositor texture definition must have absolute size", "Compositor::createGlobalTextures"); } if (def->pooled) { LogManager::getSingleton().logMessage( "Pooling global compositor textures has no effect"); } globalTextureNames.insert(def->name); //TODO GSOC : Heavy copy-pasting from CompositorInstance. How to we solve it? /// Make the tetxure RenderTarget* rendTarget; if (def->formatList.size() > 1) { String MRTbaseName = "c" + StringConverter::toString(dummyCounter++) + "/" + mName + "/" + def->name; MultiRenderTarget* mrt = Root::getSingleton().getRenderSystem()->createMultiRenderTarget(MRTbaseName); mGlobalMRTs[def->name] = mrt; // create and bind individual surfaces size_t atch = 0; for (PixelFormatList::iterator p = def->formatList.begin(); p != def->formatList.end(); ++p, ++atch) { String texname = MRTbaseName + "/" + StringConverter::toString(atch); TexturePtr tex; tex = TextureManager::getSingleton().createManual( texname, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)def->width, (uint)def->height, 0, *p, TU_RENDERTARGET, 0, def->hwGammaWrite && !PixelUtil::isFloatingPoint(*p), def->fsaa); RenderTexture* rt = tex->getBuffer()->getRenderTarget(); rt->setAutoUpdated(false); mrt->bindSurface(atch, rt); // Also add to local textures so we can look up String mrtLocalName = getMRTTexLocalName(def->name, atch); mGlobalTextures[mrtLocalName] = tex; } rendTarget = mrt; } else { String texName = "c" + StringConverter::toString(dummyCounter++) + "/" + mName + "/" + def->name; // space in the name mixup the cegui in the compositor demo // this is an auto generated name - so no spaces can't hart us. std::replace( texName.begin(), texName.end(), ' ', '_' ); TexturePtr tex; tex = TextureManager::getSingleton().createManual( texName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)def->width, (uint)def->height, 0, def->formatList[0], TU_RENDERTARGET, 0, def->hwGammaWrite && !PixelUtil::isFloatingPoint(def->formatList[0]), def->fsaa); rendTarget = tex->getBuffer()->getRenderTarget(); mGlobalTextures[def->name] = tex; } //Set DepthBuffer pool for sharing rendTarget->setDepthBufferPool( def->depthBufferId ); } } //Validate that all other supported techniques expose the same set of global textures. for (size_t i=1; i<mSupportedTechniques.size(); i++) { CompositionTechnique* technique = mSupportedTechniques[i]; bool isConsistent = true; size_t numGlobals = 0; texDefIt = technique->getTextureDefinitionIterator(); while (texDefIt.hasMoreElements()) { CompositionTechnique::TextureDefinition* texDef = texDefIt.getNext(); if (texDef->scope == CompositionTechnique::TS_GLOBAL) { if (globalTextureNames.find(texDef->name) == globalTextureNames.end()) { isConsistent = false; break; } numGlobals++; } } if (numGlobals != globalTextureNames.size()) isConsistent = false; if (!isConsistent) { OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "Different composition techniques define different global textures", "Compositor::createGlobalTextures"); } } }
void ImpostorTexture::renderTextures(bool force) { #ifdef IMPOSTOR_FILE_SAVE TexturePtr renderTexture; #else TexturePtr renderTexture(texture); //if we're not using a file image we need to set up a resource loader, so that the texture is regenerated if it's ever unloaded (such as switching between fullscreen and the desktop in win32) loader = std::auto_ptr<ImpostorTextureResourceLoader>(new ImpostorTextureResourceLoader(*this)); #endif RenderTexture *renderTarget; Camera *renderCamera; Viewport *renderViewport; SceneNode *camNode; //Set up RTT texture uint32 textureSize = ImpostorPage::impostorResolution; if (renderTexture.isNull()) { renderTexture = TextureManager::getSingleton().createManual(getUniqueID("ImpostorTexture"), "Impostors", TEX_TYPE_2D, textureSize * IMPOSTOR_YAW_ANGLES, textureSize * IMPOSTOR_PITCH_ANGLES, 0, PF_A8R8G8B8, TU_RENDERTARGET, loader.get()); } renderTexture->setNumMipmaps(MIP_UNLIMITED); //Set up render target renderTarget = renderTexture->getBuffer()->getRenderTarget(); renderTarget->setAutoUpdated(false); //Set up camera camNode = sceneMgr->getSceneNode("ImpostorPage::cameraNode"); renderCamera = sceneMgr->createCamera(getUniqueID("ImpostorCam")); camNode->attachObject(renderCamera); renderCamera->setLodBias(1000.0f); renderViewport = renderTarget->addViewport(renderCamera); renderViewport->setOverlaysEnabled(false); renderViewport->setClearEveryFrame(true); renderViewport->setShadowsEnabled(false); renderViewport->setBackgroundColour(ImpostorPage::impostorBackgroundColor); //Set up scene node SceneNode* node = sceneMgr->getSceneNode("ImpostorPage::renderNode"); Ogre::SceneNode* oldSceneNode = entity->getParentSceneNode(); if (oldSceneNode) { oldSceneNode->detachObject(entity); } node->attachObject(entity); node->setPosition(-entityCenter); //Set up camera FOV const Real objDist = entityRadius * 100; const Real nearDist = objDist - (entityRadius + 1); const Real farDist = objDist + (entityRadius + 1); renderCamera->setAspectRatio(1.0f); renderCamera->setFOVy(Math::ATan(entityDiameter / objDist)); renderCamera->setNearClipDistance(nearDist); renderCamera->setFarClipDistance(farDist); //Disable mipmapping (without this, masked textures look bad) MaterialManager *mm = MaterialManager::getSingletonPtr(); FilterOptions oldMinFilter = mm->getDefaultTextureFiltering(FT_MIN); FilterOptions oldMagFilter = mm->getDefaultTextureFiltering(FT_MAG); FilterOptions oldMipFilter = mm->getDefaultTextureFiltering(FT_MIP); mm->setDefaultTextureFiltering(FO_POINT, FO_LINEAR, FO_NONE); //Disable fog FogMode oldFogMode = sceneMgr->getFogMode(); ColourValue oldFogColor = sceneMgr->getFogColour(); Real oldFogDensity = sceneMgr->getFogDensity(); Real oldFogStart = sceneMgr->getFogStart(); Real oldFogEnd = sceneMgr->getFogEnd(); sceneMgr->setFog(Ogre::FOG_EXP2, Ogre::ColourValue(0,0,0,0), 0.0f, 0.0f, 0.0f); //Ember change //We need to disable all lightning and render it full bright Ogre::ColourValue oldAmbientColour = sceneMgr->getAmbientLight(); sceneMgr->setAmbientLight(ColourValue::White); std::vector<Ogre::MovableObject*> lightStore; Ogre::SceneManager::MovableObjectIterator lightIterator = sceneMgr->getMovableObjectIterator(Ogre::LightFactory::FACTORY_TYPE_NAME); while (lightIterator.hasMoreElements()) { Ogre::MovableObject* light = lightIterator.getNext(); if (light) { if (light->getVisible()) { lightStore.push_back(light); light->setVisible(false); } } } // Get current status of the queue mode Ogre::SceneManager::SpecialCaseRenderQueueMode OldSpecialCaseRenderQueueMode = sceneMgr->getSpecialCaseRenderQueueMode(); //Only render the entity sceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_INCLUDE); sceneMgr->addSpecialCaseRenderQueue(group->geom->getRenderQueue() + 1); uint8 oldRenderQueueGroup = entity->getRenderQueueGroup(); entity->setRenderQueueGroup(group->geom->getRenderQueue() + 1); bool oldVisible = entity->getVisible(); entity->setVisible(true); float oldMaxDistance = entity->getRenderingDistance(); entity->setRenderingDistance(0); bool needsRegen = true; #ifdef IMPOSTOR_FILE_SAVE //Calculate the filename hash used to uniquely identity this render String strKey = entityKey; char key[32] = {0}; uint32 i = 0; for (String::const_iterator it = entityKey.begin(); it != entityKey.end(); ++it) { key[i] ^= *it; i = (i+1) % sizeof(key); } for (i = 0; i < sizeof(key); ++i) key[i] = (key[i] % 26) + 'A'; String tempdir = this->group->geom->getTempdir(); ResourceGroupManager::getSingleton().addResourceLocation(tempdir, "FileSystem", "BinFolder"); String fileNamePNG = "Impostor." + String(key, sizeof(key)) + '.' + StringConverter::toString(textureSize) + ".png"; String fileNameDDS = "Impostor." + String(key, sizeof(key)) + '.' + StringConverter::toString(textureSize) + ".dds"; //Attempt to load the pre-render file if allowed needsRegen = force; if (!needsRegen){ try{ texture = TextureManager::getSingleton().load(fileNameDDS, "BinFolder", TEX_TYPE_2D, MIP_UNLIMITED); } catch (...){ try{ texture = TextureManager::getSingleton().load(fileNamePNG, "BinFolder", TEX_TYPE_2D, MIP_UNLIMITED); } catch (...){ needsRegen = true; } } } #endif if (needsRegen){ //If this has not been pre-rendered, do so now const float xDivFactor = 1.0f / IMPOSTOR_YAW_ANGLES; const float yDivFactor = 1.0f / IMPOSTOR_PITCH_ANGLES; for (int o = 0; o < IMPOSTOR_PITCH_ANGLES; ++o){ //4 pitch angle renders #ifdef IMPOSTOR_RENDER_ABOVE_ONLY Radian pitch = Degree((90.0f * o) * yDivFactor); //0, 22.5, 45, 67.5 #else Radian pitch = Degree((180.0f * o) * yDivFactor - 90.0f); #endif for (int i = 0; i < IMPOSTOR_YAW_ANGLES; ++i){ //8 yaw angle renders Radian yaw = Degree((360.0f * i) * xDivFactor); //0, 45, 90, 135, 180, 225, 270, 315 //Position camera camNode->setPosition(0, 0, 0); camNode->setOrientation(Quaternion(yaw, Vector3::UNIT_Y) * Quaternion(-pitch, Vector3::UNIT_X)); camNode->translate(Vector3(0, 0, objDist), Node::TS_LOCAL); //Render the impostor renderViewport->setDimensions((float)(i) * xDivFactor, (float)(o) * yDivFactor, xDivFactor, yDivFactor); renderTarget->update(); } } #ifdef IMPOSTOR_FILE_SAVE //Save RTT to file with respecting the temp dir renderTarget->writeContentsToFile(tempdir + fileNamePNG); //Load the render into the appropriate texture view texture = TextureManager::getSingleton().load(fileNamePNG, "BinFolder", TEX_TYPE_2D, MIP_UNLIMITED); #else texture = renderTexture; #endif } entity->setVisible(oldVisible); entity->setRenderQueueGroup(oldRenderQueueGroup); entity->setRenderingDistance(oldMaxDistance); sceneMgr->removeSpecialCaseRenderQueue(group->geom->getRenderQueue() + 1); // Restore original state sceneMgr->setSpecialCaseRenderQueueMode(OldSpecialCaseRenderQueueMode); //Re-enable mipmapping mm->setDefaultTextureFiltering(oldMinFilter, oldMagFilter, oldMipFilter); //Re-enable fog sceneMgr->setFog(oldFogMode, oldFogColor, oldFogDensity, oldFogStart, oldFogEnd); //Re-enable both scene lightning and disabled individual lights sceneMgr->setAmbientLight(oldAmbientColour); for (std::vector<Ogre::MovableObject*>::const_iterator I = lightStore.begin(); I != lightStore.end(); ++I) { (*I)->setVisible(true); } //Delete camera renderTarget->removeViewport(0); renderCamera->getSceneManager()->destroyCamera(renderCamera); //Delete scene node node->detachAllObjects(); if (oldSceneNode) { oldSceneNode->attachObject(entity); } #ifdef IMPOSTOR_FILE_SAVE //Delete RTT texture assert(!renderTexture.isNull()); String texName2(renderTexture->getName()); renderTexture.setNull(); if (TextureManager::getSingletonPtr()) TextureManager::getSingleton().remove(texName2); #endif }
//----------------------------------------------------------------------- void CompositorInstance::createResources() { static size_t dummyCounter = 0; freeResources(); /// Create temporary textures /// In principle, temporary textures could be shared between multiple viewports /// (CompositorChains). This will save a lot of memory in case more viewports /// are composited. CompositionTechnique::TextureDefinitionIterator it = mTechnique->getTextureDefinitionIterator(); while(it.hasMoreElements()) { CompositionTechnique::TextureDefinition *def = it.getNext(); /// Determine width and height size_t width = def->width; size_t height = def->height; uint fsaa = 0; bool hwGammaWrite = false; deriveTextureRenderTargetOptions(def->name, &hwGammaWrite, &fsaa); if(width == 0) width = static_cast<size_t>( static_cast<float>(mChain->getViewport()->getActualWidth()) * def->widthFactor); if(height == 0) height = static_cast<size_t>( static_cast<float>(mChain->getViewport()->getActualHeight()) * def->heightFactor); /// Make the tetxure RenderTarget* rendTarget; if (def->formatList.size() > 1) { String MRTbaseName = "c" + StringConverter::toString(dummyCounter++) + "/" + def->name + "/" + mChain->getViewport()->getTarget()->getName(); MultiRenderTarget* mrt = Root::getSingleton().getRenderSystem()->createMultiRenderTarget(MRTbaseName); mLocalMRTs[def->name] = mrt; // create and bind individual surfaces size_t atch = 0; for (PixelFormatList::iterator p = def->formatList.begin(); p != def->formatList.end(); ++p, ++atch) { TexturePtr tex = TextureManager::getSingleton().createManual( MRTbaseName + "/" + StringConverter::toString(atch), ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)width, (uint)height, 0, *p, TU_RENDERTARGET ); RenderTexture* rt = tex->getBuffer()->getRenderTarget(); rt->setAutoUpdated(false); mrt->bindSurface(atch, rt); // Also add to local textures so we can look up String mrtLocalName = getMRTTexLocalName(def->name, atch); mLocalTextures[mrtLocalName] = tex; } rendTarget = mrt; } else { String texName = "c" + StringConverter::toString(dummyCounter++) + "/" + def->name + "/" + mChain->getViewport()->getTarget()->getName(); // space in the name mixup the cegui in the compositor demo // this is an auto generated name - so no spaces can't hart us. std::replace( texName.begin(), texName.end(), ' ', '_' ); TexturePtr tex = TextureManager::getSingleton().createManual( texName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)width, (uint)height, 0, def->formatList[0], TU_RENDERTARGET, 0, hwGammaWrite, fsaa); rendTarget = tex->getBuffer()->getRenderTarget(); mLocalTextures[def->name] = tex; } /// Set up viewport over entire texture rendTarget->setAutoUpdated( false ); Camera* camera = mChain->getViewport()->getCamera(); // Save last viewport and current aspect ratio Viewport* oldViewport = camera->getViewport(); Real aspectRatio = camera->getAspectRatio(); Viewport* v = rendTarget->addViewport( camera ); v->setClearEveryFrame( false ); v->setOverlaysEnabled( false ); v->setBackgroundColour( ColourValue( 0, 0, 0, 0 ) ); // Should restore aspect ratio, in case of auto aspect ratio // enabled, it'll changed when add new viewport. camera->setAspectRatio(aspectRatio); // Should restore last viewport, i.e. never disturb user code // which might based on that. camera->_notifyViewport(oldViewport); } }