virtual void execute(SceneManager *sm, RenderSystem *rs) { // Fire listener instance->_fireNotifyMaterialRender(pass_id, mat); Rectangle2D * mRectangle=static_cast<Rectangle2D *>(CompositorManager::getSingleton()._getTexturedRectangle2D()); if (mQuadCornerModified) { // insure positions are using peculiar render system offsets RenderSystem* rs = Root::getSingleton().getRenderSystem(); Viewport* vp = rs->_getViewport(); Real hOffset = rs->getHorizontalTexelOffset() / (0.5 * vp->getActualWidth()); Real vOffset = rs->getVerticalTexelOffset() / (0.5 * vp->getActualHeight()); mRectangle->setCorners(mQuadLeft + hOffset, mQuadTop - vOffset, mQuadRight + hOffset, mQuadBottom - vOffset); } // Queue passes from mat Technique::PassIterator i = technique->getPassIterator(); while(i.hasMoreElements()) { sm->_injectRenderWithPass( i.getNext(), mRectangle, false // don't allow replacement of shadow passes ); } }
//----------------------------------------------------------------------- Renderable *CompositorManager::_getTexturedRectangle2D() { if(!mRectangle) { /// 2D rectangle, to use for render_quad passes mRectangle = OGRE_NEW Rectangle2D(true, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); } RenderSystem* rs = Root::getSingleton().getRenderSystem(); Viewport* vp = rs->_getViewport(); Real hOffset = rs->getHorizontalTexelOffset() / (0.5f * vp->getActualWidth()); Real vOffset = rs->getVerticalTexelOffset() / (0.5f * vp->getActualHeight()); mRectangle->setCorners(-1 + hOffset, 1 - vOffset, 1 + hOffset, -1 - vOffset); return mRectangle; }
//----------------------------------------------------------------------- Renderable *CompositorManager::_getTexturedRectangle2D() { if(!mRectangle) { /// 2D rectangle, to use for render_quad passes mRectangle = new Rectangle2D(true); } RenderSystem* rs = Root::getSingleton().getRenderSystem(); Viewport* vp = rs->_getViewport(); Real hOffset = rs->getHorizontalTexelOffset() / (0.5 * vp->getActualWidth()); Real vOffset = rs->getVerticalTexelOffset() / (0.5 * vp->getActualHeight()); mRectangle->setCorners(-1 + hOffset, 1 - vOffset, 1 + hOffset, -1 - vOffset); return mRectangle; }
//--------------------------------------------------------------------- void OverlayElement::_updateFromParent(void) { Real parentLeft = 0, parentTop = 0, parentBottom = 0, parentRight = 0; if (mParent) { parentLeft = mParent->_getDerivedLeft(); parentTop = mParent->_getDerivedTop(); if (mHorzAlign == GHA_CENTER || mHorzAlign == GHA_RIGHT) { parentRight = parentLeft + mParent->_getRelativeWidth(); } if (mVertAlign == GVA_CENTER || mVertAlign == GVA_BOTTOM) { parentBottom = parentTop + mParent->_getRelativeHeight(); } } else { RenderSystem* rSys = Root::getSingleton().getRenderSystem(); OverlayManager& oMgr = OverlayManager::getSingleton(); // Calculate offsets required for mapping texel origins to pixel origins in the // current rendersystem Real hOffset = rSys->getHorizontalTexelOffset() / oMgr.getViewportWidth(); Real vOffset = rSys->getVerticalTexelOffset() / oMgr.getViewportHeight(); parentLeft = 0.0f + hOffset; parentTop = 0.0f + vOffset; parentRight = 1.0f + hOffset; parentBottom = 1.0f + vOffset; } // Sort out position based on alignment // NB all we do is derived the origin, we don't automatically sort out the position // This is more flexible than forcing absolute right & middle switch(mHorzAlign) { case GHA_CENTER: mDerivedLeft = ((parentLeft + parentRight) * 0.5f) + mLeft; break; case GHA_LEFT: mDerivedLeft = parentLeft + mLeft; break; case GHA_RIGHT: mDerivedLeft = parentRight + mLeft; break; }; switch(mVertAlign) { case GVA_CENTER: mDerivedTop = ((parentTop + parentBottom) * 0.5f) + mTop; break; case GVA_TOP: mDerivedTop = parentTop + mTop; break; case GVA_BOTTOM: mDerivedTop = parentBottom + mTop; break; }; mDerivedOutOfDate = false; if (mParent != 0) { Rectangle parent; Rectangle child; mParent->_getClippingRegion(parent); child.left = mDerivedLeft; child.top = mDerivedTop; child.right = mDerivedLeft + mWidth; child.bottom = mDerivedTop + mHeight; mClippingRegion = intersect(parent, child); } else { mClippingRegion.left = mDerivedLeft; mClippingRegion.top = mDerivedTop; mClippingRegion.right = mDerivedLeft + mWidth; mClippingRegion.bottom = mDerivedTop + mHeight; } }
//--------------------------------------------------------------------- void TerrainMaterialGenerator::_renderCompositeMap(size_t size, const Rect& rect, const MaterialPtr& mat, const TexturePtr& destCompositeMap) { if (!mCompositeMapSM) { // dedicated SceneManager mCompositeMapSM = Root::getSingleton().createSceneManager(DefaultSceneManagerFactory::FACTORY_TYPE_NAME); float camDist = 100; float halfCamDist = camDist * 0.5f; mCompositeMapCam = mCompositeMapSM->createCamera("cam"); mCompositeMapCam->setPosition(0, 0, camDist); mCompositeMapCam->lookAt(Vector3::ZERO); mCompositeMapCam->setProjectionType(PT_ORTHOGRAPHIC); mCompositeMapCam->setNearClipDistance(10); mCompositeMapCam->setFarClipDistance(500); mCompositeMapCam->setOrthoWindow(camDist, camDist); // Just in case material relies on light auto params mCompositeMapLight = mCompositeMapSM->createLight(); mCompositeMapLight->setType(Light::LT_DIRECTIONAL); RenderSystem* rSys = Root::getSingleton().getRenderSystem(); Real hOffset = rSys->getHorizontalTexelOffset() / (Real)size; Real vOffset = rSys->getVerticalTexelOffset() / (Real)size; // set up scene mCompositeMapPlane = mCompositeMapSM->createManualObject(); mCompositeMapPlane->begin(mat->getName()); mCompositeMapPlane->position(-halfCamDist, halfCamDist, 0); mCompositeMapPlane->textureCoord(0 - hOffset, 0 - vOffset); mCompositeMapPlane->position(-halfCamDist, -halfCamDist, 0); mCompositeMapPlane->textureCoord(0 - hOffset, 1 - vOffset); mCompositeMapPlane->position(halfCamDist, -halfCamDist, 0); mCompositeMapPlane->textureCoord(1 - hOffset, 1 - vOffset); mCompositeMapPlane->position(halfCamDist, halfCamDist, 0); mCompositeMapPlane->textureCoord(1 - hOffset, 0 - vOffset); mCompositeMapPlane->quad(0, 1, 2, 3); mCompositeMapPlane->end(); mCompositeMapSM->getRootSceneNode()->attachObject(mCompositeMapPlane); } // update mCompositeMapPlane->setMaterialName(0, mat->getName()); TerrainGlobalOptions& globalopts = TerrainGlobalOptions::getSingleton(); mCompositeMapLight->setDirection(globalopts.getLightMapDirection()); mCompositeMapLight->setDiffuseColour(globalopts.getCompositeMapDiffuse()); mCompositeMapSM->setAmbientLight(globalopts.getCompositeMapAmbient()); // check for size change (allow smaller to be reused) if (mCompositeMapRTT && size != mCompositeMapRTT->getWidth()) { TextureManager::getSingleton().remove(mCompositeMapRTT->getHandle()); mCompositeMapRTT = 0; } if (!mCompositeMapRTT) { mCompositeMapRTT = TextureManager::getSingleton().createManual( mCompositeMapSM->getName() + "/compRTT", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, size, size, 0, PF_BYTE_RGBA, TU_RENDERTARGET).get(); RenderTarget* rtt = mCompositeMapRTT->getBuffer()->getRenderTarget(); // don't render all the time, only on demand rtt->setAutoUpdated(false); Viewport* vp = rtt->addViewport(mCompositeMapCam); // don't render overlays vp->setOverlaysEnabled(false); } // calculate the area we need to update Real vpleft = (Real)rect.left / (Real)size; Real vptop = (Real)rect.top / (Real)size; Real vpright = (Real)rect.right / (Real)size; Real vpbottom = (Real)rect.bottom / (Real)size; RenderTarget* rtt = mCompositeMapRTT->getBuffer()->getRenderTarget(); mCompositeMapCam->setWindow(vpleft, vptop, vpright, vpbottom); rtt->update(); // We have an RTT, we want to copy the results into a regular texture // That's because in non-update scenarios we don't want to keep an RTT // around. We use a single RTT to serve all terrain pages which is more // efficient. Image::Box box(rect.left, rect.top, rect.right, rect.bottom); destCompositeMap->getBuffer()->blit(mCompositeMapRTT->getBuffer(), box, box); }