diff --git a/source/gameengine/Ketsji/KX_CubeMapManager.cpp b/source/gameengine/Ketsji/KX_CubeMapManager.cpp index c181e2c55962..f8192f48b6a6 100644 --- a/source/gameengine/Ketsji/KX_CubeMapManager.cpp +++ b/source/gameengine/Ketsji/KX_CubeMapManager.cpp @@ -149,7 +149,8 @@ void KX_CubeMapManager::RenderCubeMap(RAS_IRasterizer *rasty, KX_CubeMap *cubeMa // Now the objects are culled and we can render the scene. m_scene->GetWorldInfo()->RenderBackground(rasty); - m_scene->RenderBuckets(trans, rasty); + // Send a NULL off screen because we use a set of FBO with shared textures, not an off screen. + m_scene->RenderBuckets(trans, rasty, NULL); } cubeMap->EndRender(); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index f8808240c036..ee7db968906f 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -51,6 +51,7 @@ #include "RAS_Rect.h" #include "RAS_IRasterizer.h" #include "RAS_ICanvas.h" +#include "RAS_OffScreen.h" #include "RAS_ILightObject.h" #include "MT_Vector3.h" #include "MT_Transform.h" @@ -540,8 +541,18 @@ void KX_KetsjiEngine::Render() // Update all off screen to the current canvas size. m_rasterizer->UpdateOffScreens(m_canvas); + + // The current bound off screen types. + RAS_IRasterizer::OffScreenType ofsTypes[] = { + RAS_IRasterizer::RAS_OFFSCREEN_EYE_LEFT0, + RAS_IRasterizer::RAS_OFFSCREEN_EYE_RIGHT0, + RAS_IRasterizer::RAS_OFFSCREEN_RENDER + }; + + // Current off screen used for bucket rendering. + RAS_OffScreen *offScreen = m_rasterizer->GetOffScreen(ofsTypes[2]); // Bind render off screen as default. - m_rasterizer->BindOffScreen(RAS_IRasterizer::RAS_OFFSCREEN_RENDER); + offScreen->Bind(); // clear the entire game screen with the border color // only once per frame @@ -564,9 +575,6 @@ void KX_KetsjiEngine::Render() const unsigned short numeyepass = (stereomode != RAS_IRasterizer::RAS_STEREO_NOSTEREO) ? 2 : 1; - // The current bound eye off screen if we are using per eye stereo. - int eyefboindex[2] = {RAS_IRasterizer::RAS_OFFSCREEN_EYE_LEFT0, RAS_IRasterizer::RAS_OFFSCREEN_EYE_RIGHT0}; - // Used to detect when a camera is the first rendered an then doesn't request a depth clear. unsigned short pass = 0; @@ -591,7 +599,8 @@ void KX_KetsjiEngine::Render() // Choose unique off screen per eyes in case of stereo. if (renderpereye) { - m_rasterizer->BindOffScreen(eyefboindex[eyepass]); + offScreen = m_rasterizer->GetOffScreen(ofsTypes[eyepass]); + offScreen->Bind(); // Clear eye off screen only before the first scene render. if (firstscene) { m_rasterizer->Clear(RAS_IRasterizer::RAS_COLOR_BUFFER_BIT | RAS_IRasterizer::RAS_DEPTH_BUFFER_BIT); @@ -601,7 +610,7 @@ void KX_KetsjiEngine::Render() // Avoid drawing the scene with the active camera twice when its viewport is enabled if (activecam && !activecam->GetViewport()) { // do the rendering - RenderFrame(scene, activecam, pass++); + RenderFrame(scene, activecam, offScreen, pass++); } // Draw the scene once for each camera with an enabled viewport @@ -609,33 +618,33 @@ void KX_KetsjiEngine::Render() KX_Camera *cam = *it; if (cam->GetViewport()) { // do the rendering - RenderFrame(scene, cam, pass++); + RenderFrame(scene, cam, offScreen, pass++); } } // Process filters per eye off screen. if (renderpereye) { - int target; - if (m_rasterizer->GetOffScreenSamples(eyefboindex[eyepass]) > 0) { + RAS_IRasterizer::OffScreenType target; + if (offScreen->GetSamples() > 0) { /* Only RAS_OFFSCREEN_EYE_[LEFT/RIGHT]0 has possible multisamples so we target * RAS_OFFSCREEN_EYE_[LEFT/RIGHT]1 if it's the last scene. */ if (lastscene) { - target = RAS_IRasterizer::NextEyeOffScreen(eyefboindex[eyepass]); + target = RAS_IRasterizer::NextEyeOffScreen(ofsTypes[eyepass]); } /* In case of multisamples and filters we're sure that a blit to RAS_OFFSCREEN_FILTER0 - * will be done so we can target the same off screen than in input of the filter prossesing. */ + * will be done so we can target the same off screen than in input of the filter processing. */ else { - target = eyefboindex[eyepass]; + target = ofsTypes[eyepass]; } } else { - target = RAS_IRasterizer::NextEyeOffScreen(eyefboindex[eyepass]); + target = RAS_IRasterizer::NextEyeOffScreen(ofsTypes[eyepass]); } - PostRenderScene(scene, target); - + // Render filters and get output off screen. + offScreen = PostRenderScene(scene, offScreen, m_rasterizer->GetOffScreen(target)); // If no filter was rendered the current used off screen can be unchanged. - eyefboindex[eyepass] = m_rasterizer->GetCurrentOffScreenIndex(); + ofsTypes[eyepass] = offScreen->GetType(); } } @@ -644,26 +653,27 @@ void KX_KetsjiEngine::Render() /* Choose final render off screen target. If the current off screen is using multisamples we * are sure that it will be copied to a non-multisamples off screen before render the filters. * In this case the targeted off screen is the same as the current off screen. */ - int target; - const short fboindex = m_rasterizer->GetCurrentOffScreenIndex(); - if (m_rasterizer->GetOffScreenSamples(fboindex) > 0) { + RAS_IRasterizer::OffScreenType target; + if (offScreen->GetSamples() > 0) { /* If the last scene is rendered it's useless to specify a multisamples off screen, we use then * RAS_OFFSCREEN_FINAL and avoid an extra off screen blit. */ if (lastscene) { - // Equivalent to RAS_IRasterizer::NextRenderOffScreen(fboindex). + // Equivalent to RAS_IRasterizer::NextRenderOffScreen(ofsTypes[2]). target = RAS_IRasterizer::RAS_OFFSCREEN_FINAL; } else { - target = fboindex; + target = ofsTypes[2]; } } /* In case of non-multisamples a ping pong per scene render is made between RAS_OFFSCREEN_RENDER * and RAS_OFFSCREEN_FINAL. */ else { - target = RAS_IRasterizer::NextRenderOffScreen(fboindex); + target = RAS_IRasterizer::NextRenderOffScreen(ofsTypes[2]); } - PostRenderScene(scene, target); + // Render filters and get output off screen. + offScreen = PostRenderScene(scene, offScreen, m_rasterizer->GetOffScreen(target)); + ofsTypes[2] = offScreen->GetType(); } } @@ -671,12 +681,13 @@ void KX_KetsjiEngine::Render() // Compositing per eye off screens to screen. if (renderpereye) { - m_rasterizer->DrawStereoOffScreen(m_canvas, eyefboindex[RAS_IRasterizer::RAS_STEREO_LEFTEYE], eyefboindex[RAS_IRasterizer::RAS_STEREO_RIGHTEYE]); + RAS_OffScreen *leftofs = m_rasterizer->GetOffScreen(ofsTypes[RAS_IRasterizer::RAS_STEREO_LEFTEYE]); + RAS_OffScreen *rightofs = m_rasterizer->GetOffScreen(ofsTypes[RAS_IRasterizer::RAS_STEREO_RIGHTEYE]); + m_rasterizer->DrawStereoOffScreen(m_canvas, leftofs, rightofs); } // Else simply draw the off screen to screen. else { - const short fboindex = m_rasterizer->GetCurrentOffScreenIndex(); - m_rasterizer->DrawOffScreen(m_canvas, fboindex); + m_rasterizer->DrawOffScreen(m_canvas, m_rasterizer->GetOffScreen(ofsTypes[2])); } EndFrame(); @@ -838,7 +849,8 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) /* render */ m_rasterizer->Clear(RAS_IRasterizer::RAS_DEPTH_BUFFER_BIT | RAS_IRasterizer::RAS_COLOR_BUFFER_BIT); - scene->RenderBuckets(camtrans, m_rasterizer); + // Send a NULL off screen because the viewport is binding it's using its own private one. + scene->RenderBuckets(camtrans, m_rasterizer, NULL); /* unbind framebuffer object, restore drawmode, free camera */ raslight->UnbindShadowBuffer(); @@ -931,7 +943,7 @@ const MT_Matrix4x4& KX_KetsjiEngine::GetCameraProjectionMatrix(KX_Scene *scene, } // update graphics -void KX_KetsjiEngine::RenderFrame(KX_Scene *scene, KX_Camera *cam, unsigned short pass) +void KX_KetsjiEngine::RenderFrame(KX_Scene *scene, KX_Camera *cam, RAS_OffScreen *offScreen, unsigned short pass) { RAS_Rect viewport, area; @@ -1013,7 +1025,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene *scene, KX_Camera *cam, unsigned shor scene->RunDrawingCallbacks(KX_Scene::PRE_DRAW, cam); #endif - scene->RenderBuckets(camtrans, m_rasterizer); + scene->RenderBuckets(camtrans, m_rasterizer, offScreen); if (scene->GetPhysicsEnvironment()) scene->GetPhysicsEnvironment()->DebugDrawWorld(); @@ -1022,7 +1034,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene *scene, KX_Camera *cam, unsigned shor /* * To run once per scene */ -void KX_KetsjiEngine::PostRenderScene(KX_Scene *scene, unsigned short target) +RAS_OffScreen *KX_KetsjiEngine::PostRenderScene(KX_Scene *scene, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs) { KX_SetActiveScene(scene); @@ -1034,7 +1046,7 @@ void KX_KetsjiEngine::PostRenderScene(KX_Scene *scene, unsigned short target) m_rasterizer->SetViewport(0, 0, width + 1, height + 1); m_rasterizer->SetScissor(0, 0, width + 1, height + 1); - scene->Render2DFilters(m_rasterizer, m_canvas, target); + RAS_OffScreen *offScreen = scene->Render2DFilters(m_rasterizer, m_canvas, inputofs, targetofs); #ifdef WITH_PYTHON PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); @@ -1046,6 +1058,8 @@ void KX_KetsjiEngine::PostRenderScene(KX_Scene *scene, unsigned short target) // Python draw callback can also call debug draw functions, so we have to clear debug shapes. m_rasterizer->FlushDebugShapes(scene); #endif + + return offScreen; } void KX_KetsjiEngine::StopEngine() diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 283764f31f75..616cae9e6525 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -50,6 +50,7 @@ class KX_ISceneConverter; class KX_NetworkMessageManager; class CListValue; class RAS_ICanvas; +class RAS_OffScreen; class RAS_IRasterizer; class SCA_IInputDevice; @@ -227,8 +228,8 @@ class KX_KetsjiEngine /// Update and return the projection matrix of a camera depending on the viewport. const MT_Matrix4x4& GetCameraProjectionMatrix(KX_Scene *scene, KX_Camera *cam, const RAS_Rect& viewport, const RAS_Rect& area); - void RenderFrame(KX_Scene *scene, KX_Camera *cam, unsigned short pass); - void PostRenderScene(KX_Scene *scene, unsigned short target); + void RenderFrame(KX_Scene *scene, KX_Camera *cam, RAS_OffScreen *offScreen, unsigned short pass); + RAS_OffScreen *PostRenderScene(KX_Scene *scene, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs); void RenderDebugProperties(); /// Debug draw cameras frustum of a scene. void DrawDebugCameraFrustum(KX_Scene *scene, const RAS_Rect& viewport, const RAS_Rect& area); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 2c23ddbb0142..a8def2cb90f9 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1701,8 +1701,7 @@ RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool -void KX_Scene::RenderBuckets(const MT_Transform & cameratransform, - class RAS_IRasterizer* rasty) +void KX_Scene::RenderBuckets(const MT_Transform& cameratransform, RAS_IRasterizer *rasty, RAS_OffScreen *offScreen) { for (CListValue::iterator it = m_objectlist->GetBegin(), end = m_objectlist->GetEnd(); it != end; ++it) { /* This function update all mesh slot info (e.g culling, color, matrix) from the game object. @@ -1710,7 +1709,7 @@ void KX_Scene::RenderBuckets(const MT_Transform & cameratransform, (*it)->UpdateBuckets(); } - m_bucketmanager->Renderbuckets(cameratransform,rasty); + m_bucketmanager->Renderbuckets(cameratransform, rasty, offScreen); KX_BlenderMaterial::EndFrame(rasty); } @@ -2083,9 +2082,9 @@ RAS_2DFilterManager *KX_Scene::Get2DFilterManager() const return m_filterManager; } -void KX_Scene::Render2DFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned short target) +RAS_OffScreen *KX_Scene::Render2DFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs) { - m_filterManager->RenderFilters(rasty, canvas, target); + return m_filterManager->RenderFilters(rasty, canvas, inputofs, targetofs); } #ifdef WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 597fafbd521f..608def61ffe7 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -79,7 +79,7 @@ class RAS_BucketManager; class RAS_MaterialBucket; class RAS_IPolyMaterial; class RAS_IRasterizer; -class RAS_IRenderTools; +class RAS_OffScreen; class RAS_2DFilterManager; class KX_2DFilterManager; class SCA_JoystickManager; @@ -318,8 +318,7 @@ class KX_Scene : public CValue, public SCA_IScene KX_CubeMapManager *GetCubeMapManager(); RAS_BoundingBoxManager *GetBoundingBoxManager(); RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial* polymat, bool &bucketCreated); - void RenderBuckets(const MT_Transform& cameratransform, - RAS_IRasterizer* rasty); + void RenderBuckets(const MT_Transform& cameratransform, RAS_IRasterizer *rasty, RAS_OffScreen *offScreen); void RenderCubeMaps(RAS_IRasterizer *rasty); /** @@ -544,7 +543,7 @@ class KX_Scene : public CValue, public SCA_IScene * 2D Filters */ RAS_2DFilterManager *Get2DFilterManager() const; - void Render2DFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned short target); + RAS_OffScreen *Render2DFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs); KX_ObstacleSimulation* GetObstacleSimulation() { return m_obstacleSimulation; } diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt index cc16c1db1f12..f8c6d5ebc086 100644 --- a/source/gameengine/Rasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/CMakeLists.txt @@ -53,6 +53,8 @@ set(SRC RAS_2DFilterData.cpp RAS_2DFilterManager.cpp RAS_BatchGroup.cpp + RAS_BoundingBox.cpp + RAS_BoundingBoxManager.cpp RAS_BucketManager.cpp RAS_CubeMap.cpp RAS_DisplayArrayBucket.cpp @@ -64,11 +66,10 @@ set(SRC RAS_IPolygonMaterial.cpp RAS_ITexVert.cpp RAS_MaterialBucket.cpp - RAS_BoundingBox.cpp - RAS_BoundingBoxManager.cpp RAS_MeshObject.cpp RAS_MeshSlot.cpp RAS_MeshUser.cpp + RAS_OffScreen.cpp RAS_Polygon.cpp RAS_Shader.cpp RAS_Texture.cpp @@ -77,13 +78,15 @@ set(SRC RAS_2DFilterData.h RAS_2DFilter.h RAS_2DFilterManager.h + RAS_BatchDisplayArray.h RAS_BatchGroup.h + RAS_BoundingBox.h + RAS_BoundingBoxManager.h RAS_BucketManager.h RAS_CameraData.h RAS_CubeMap.h RAS_Deformer.h RAS_DisplayArray.h - RAS_BatchDisplayArray.h RAS_DisplayArrayBucket.h RAS_FramingManager.h RAS_ICanvas.h @@ -97,12 +100,11 @@ set(SRC RAS_ISync.h RAS_ITexVert.h RAS_MaterialBucket.h - RAS_BoundingBox.h - RAS_BoundingBoxManager.h RAS_MeshMaterial.h RAS_MeshObject.h RAS_MeshSlot.h RAS_MeshUser.h + RAS_OffScreen.h RAS_Polygon.h RAS_Rect.h RAS_Shader.h diff --git a/source/gameengine/Rasterizer/RAS_2DFilter.cpp b/source/gameengine/Rasterizer/RAS_2DFilter.cpp index 78b263291efa..203266ba049c 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilter.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilter.cpp @@ -24,6 +24,7 @@ #include "RAS_2DFilterManager.h" #include "RAS_IRasterizer.h" #include "RAS_ICanvas.h" +#include "RAS_OffScreen.h" #include "RAS_Rect.h" #include "BLI_utildefines.h" // for STRINGIFY @@ -93,20 +94,20 @@ void RAS_2DFilter::Initialize(RAS_ICanvas *canvas) } } -void RAS_2DFilter::Start(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned short depthfbo, - unsigned short colorfbo, unsigned short outputfbo) +void RAS_2DFilter::Start(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, RAS_OffScreen *depthofs, + RAS_OffScreen *colorofs, RAS_OffScreen *outputofs) { // The output fbo must be not the color input fbo, it can be the same as depth input fbo because depth is unchanged. - BLI_assert(outputfbo != colorfbo); + BLI_assert(outputofs != colorofs); - rasty->BindOffScreen(outputfbo); + outputofs->Bind(); if (Ok()) { Initialize(canvas); SetProg(true); - BindTextures(rasty, depthfbo, colorfbo); + BindTextures(depthofs, colorofs); BindUniforms(canvas); Update(rasty, MT_Matrix4x4::Identity()); @@ -115,12 +116,12 @@ void RAS_2DFilter::Start(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned s rasty->DrawOverlayPlane(); - UnbindTextures(rasty, depthfbo, colorfbo); + UnbindTextures(depthofs, colorofs); } else { /* If the filter shader is invalid we simply draw the color off screen to * the output off screen. */ - rasty->DrawOffScreen(colorfbo, outputfbo); + rasty->DrawOffScreen(colorofs, outputofs); } } @@ -180,16 +181,16 @@ void RAS_2DFilter::ComputeTextureOffsets(RAS_ICanvas *canvas) } } -void RAS_2DFilter::BindTextures(RAS_IRasterizer *rasty, unsigned short depthfbo, unsigned short colorfbo) +void RAS_2DFilter::BindTextures(RAS_OffScreen *depthofs, RAS_OffScreen *colorofs) { if (m_predefinedUniforms[RENDERED_TEXTURE_UNIFORM] != -1) { - rasty->BindOffScreenTexture(colorfbo, 8, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + colorofs->BindColorTexture(8); if (m_mipmap) { - rasty->MipmapOffScreenTexture(colorfbo, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + colorofs->MipmapTexture(); } } if (m_predefinedUniforms[DEPTH_TEXTURE_UNIFORM] != -1) { - rasty->BindOffScreenTexture(depthfbo, 9, RAS_IRasterizer::RAS_OFFSCREEN_DEPTH); + depthofs->BindDepthTexture(9); } // Bind custom textures. @@ -201,16 +202,16 @@ void RAS_2DFilter::BindTextures(RAS_IRasterizer *rasty, unsigned short depthfbo, } } -void RAS_2DFilter::UnbindTextures(RAS_IRasterizer *rasty, unsigned short depthfbo, unsigned short colorfbo) +void RAS_2DFilter::UnbindTextures(RAS_OffScreen *depthofs, RAS_OffScreen *colorofs) { if (m_predefinedUniforms[RENDERED_TEXTURE_UNIFORM] != -1) { - rasty->UnbindOffScreenTexture(colorfbo, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + colorofs->UnbindColorTexture(); if (m_mipmap) { - rasty->UnmipmapOffScreenTexture(colorfbo, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + colorofs->UnmipmapTexture(); } } if (m_predefinedUniforms[DEPTH_TEXTURE_UNIFORM] != -1) { - rasty->UnbindOffScreenTexture(depthfbo, RAS_IRasterizer::RAS_OFFSCREEN_DEPTH); + depthofs->UnbindDepthTexture(); } // Bind custom textures. diff --git a/source/gameengine/Rasterizer/RAS_2DFilter.h b/source/gameengine/Rasterizer/RAS_2DFilter.h index 6110e802a907..0793b315e2ac 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilter.h +++ b/source/gameengine/Rasterizer/RAS_2DFilter.h @@ -29,6 +29,7 @@ class RAS_2DFilterManager; class RAS_IRasterizer; class RAS_ICanvas; +class RAS_OffScreen; class CValue; class RAS_2DFilter : public virtual RAS_Shader @@ -65,8 +66,8 @@ class RAS_2DFilter : public virtual RAS_Shader virtual bool LinkProgram(); void ParseShaderProgram(); void BindUniforms(RAS_ICanvas *canvas); - void BindTextures(RAS_IRasterizer *rasty, unsigned short depthfbo, unsigned short colorfbo); - void UnbindTextures(RAS_IRasterizer *rasty, unsigned short depthfbo, unsigned short colorfbo); + void BindTextures(RAS_OffScreen *detphofs, RAS_OffScreen *colorofs); + void UnbindTextures(RAS_OffScreen *detphofs, RAS_OffScreen *colorofs); void ComputeTextureOffsets(RAS_ICanvas *canvas); public: @@ -82,13 +83,13 @@ class RAS_2DFilter : public virtual RAS_Shader /** Starts executing the filter. * \param rasty The used rasterizer to call draw commands. * \param canvas The canvas containing screen viewport. - * \param depthfbo The off screen used only for the depth texture input, + * \param detphofs The off screen used only for the depth texture input, * the same for all filters of a scene. - * \param colorfbo The off screen used only for the color texture input, unique per filters. - * \param outputfbo The off screen used to draw the filter to. + * \param colorofs The off screen used only for the color texture input, unique per filters. + * \param outputofs The off screen used to draw the filter to. */ - void Start(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned short depthfbo, - unsigned short colorfbo, unsigned short outputfbo); + void Start(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, RAS_OffScreen *detphofs, + RAS_OffScreen *colorofs, RAS_OffScreen *outputofs); /// Finalizes the execution stage of the filter. void End(); diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 536e5a74ccf5..3d9af12a4a83 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -26,6 +26,7 @@ #include "RAS_ICanvas.h" #include "RAS_IRasterizer.h" +#include "RAS_OffScreen.h" #include "RAS_2DFilterManager.h" #include "RAS_2DFilter.h" @@ -80,15 +81,19 @@ RAS_2DFilter *RAS_2DFilterManager::GetFilterPass(unsigned int passIndex) return (it != m_filters.end()) ? it->second : NULL; } -void RAS_2DFilterManager::RenderFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned short target) +RAS_OffScreen *RAS_2DFilterManager::RenderFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs) { + /* The output off screen is set to the inputs off screen in case none filters will be rendered. + * Its value is changed later when rendering the filters. */ + RAS_OffScreen *outputofs = inputofs; + if (m_filters.size() == 0) { // No filters, discard. - return; + return outputofs; } - unsigned short colorfbo = rasty->GetCurrentOffScreenIndex(); - unsigned short depthfbo = colorfbo; + RAS_OffScreen *colorofs = inputofs; + RAS_OffScreen *depthofs = colorofs; rasty->Disable(RAS_IRasterizer::RAS_CULL_FACE); rasty->SetDepthFunc(RAS_IRasterizer::RAS_ALWAYS); @@ -98,45 +103,41 @@ void RAS_2DFilterManager::RenderFilters(RAS_IRasterizer *rasty, RAS_ICanvas *can rasty->SetLines(false); // Used to know if a filter is the last of the container. - RAS_PassTo2DFilter::const_iterator pend = m_filters.end(); - --pend; + RAS_PassTo2DFilter::const_iterator pend = std::prev(m_filters.end()); for (RAS_PassTo2DFilter::iterator begin = m_filters.begin(), it = begin, end = m_filters.end(); it != end; ++it) { RAS_2DFilter *filter = it->second; - unsigned short outputfbo; - // Computing the depth and color input off screens. if (it == begin) { - /* Set source FBO to RAS_OFFSCREEN_FILTER0 in case of multisample and blit, - * else keep the original source FBO. */ - if (rasty->GetOffScreenSamples(colorfbo)) { - rasty->BindOffScreen(RAS_IRasterizer::RAS_OFFSCREEN_FILTER0); - rasty->DrawOffScreen(colorfbo, RAS_IRasterizer::RAS_OFFSCREEN_FILTER0); - - colorfbo = RAS_IRasterizer::RAS_OFFSCREEN_FILTER0; - depthfbo = colorfbo; + /* Set source off screen to RAS_OFFSCREEN_FILTER0 in case of multisample and blit, + * else keep the original source off screen. */ + if (inputofs->GetSamples()) { + colorofs = depthofs = rasty->GetOffScreen(RAS_IRasterizer::RAS_OFFSCREEN_FILTER0); + rasty->DrawOffScreen(inputofs, colorofs); } } else { - colorfbo = RAS_IRasterizer::NextFilterOffScreen(colorfbo); + colorofs = rasty->GetOffScreen(RAS_IRasterizer::NextFilterOffScreen(colorofs->GetType())); } // Computing the output off screen. if (it == pend) { // Render to the targeted FBO for the last filter. - outputfbo = target; + outputofs = targetofs; } else { - outputfbo = RAS_IRasterizer::NextFilterOffScreen(colorfbo); + outputofs = rasty->GetOffScreen(RAS_IRasterizer::NextFilterOffScreen(colorofs->GetType())); } - filter->Start(rasty, canvas, depthfbo, colorfbo, outputfbo); + filter->Start(rasty, canvas, depthofs, colorofs, outputofs); filter->End(); } rasty->SetDepthFunc(RAS_IRasterizer::RAS_LEQUAL); rasty->Enable(RAS_IRasterizer::RAS_CULL_FACE); + + return outputofs; } RAS_2DFilter *RAS_2DFilterManager::CreateFilter(RAS_2DFilterData& filterData) diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.h b/source/gameengine/Rasterizer/RAS_2DFilterManager.h index 599aa0adf51a..36c3c532d831 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.h +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.h @@ -32,6 +32,7 @@ class RAS_ICanvas; class RAS_IRasterizer; +class RAS_OffScreen; class RAS_2DFilter; typedef std::map RAS_PassTo2DFilter; @@ -64,9 +65,12 @@ class RAS_2DFilterManager /** Applies the filters to the scene. * \param rasty The rasterizer used for draw commands. * \param canvas The canvas containing the screen viewport. - * \param target The off screen used as output of the last filters. + * \param inputofs The off screen used as input of the first filter. + * \param targetofs The off screen used as output of the last filter. + * \return The last used off screen, if none filters were rendered it's the + * same off screen than inputofs. */ - void RenderFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, unsigned short target); + RAS_OffScreen *RenderFilters(RAS_IRasterizer *rasty, RAS_ICanvas *canvas, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs); /// Add a filter to the stack of filters managed by this object. RAS_2DFilter *AddFilter(RAS_2DFilterData& filterData); diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 175da162e2dc..74468d84fcc9 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -136,7 +136,7 @@ void RAS_BucketManager::RenderBasicBuckets(const MT_Transform& cameratrans, RAS_ } } -void RAS_BucketManager::Renderbuckets(const MT_Transform& cameratrans, RAS_IRasterizer *rasty) +void RAS_BucketManager::Renderbuckets(const MT_Transform& cameratrans, RAS_IRasterizer *rasty, RAS_OffScreen *offScreen) { switch (rasty->GetDrawingMode()) { case RAS_IRasterizer::RAS_SHADOW: @@ -264,7 +264,7 @@ void RAS_BucketManager::Renderbuckets(const MT_Transform& cameratrans, RAS_IRast // Render soft particles after all other materials. if ((m_buckets[ALPHA_DEPTH_BUCKET].size() + m_buckets[ALPHA_DEPTH_INSTANCING_BUCKET].size()) > 0) { - rasty->UpdateGlobalDepthTexture(); + rasty->UpdateGlobalDepthTexture(offScreen); RenderBasicBuckets(cameratrans, rasty, ALPHA_DEPTH_INSTANCING_BUCKET); RenderSortedBuckets(cameratrans, rasty, ALPHA_DEPTH_BUCKET); diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 94b62a25553b..166d5ca8bc56 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -37,6 +37,7 @@ #include +class RAS_OffScreen; class SCA_IScene; class RAS_BucketManager @@ -94,7 +95,7 @@ class RAS_BucketManager RAS_BucketManager(); virtual ~RAS_BucketManager(); - void Renderbuckets(const MT_Transform & cameratrans, RAS_IRasterizer *rasty); + void Renderbuckets(const MT_Transform & cameratrans, RAS_IRasterizer *rasty, RAS_OffScreen *offScreen); RAS_MaterialBucket *FindBucket(RAS_IPolyMaterial *material, bool &bucketCreated); diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index b9e958ef00c2..09432aa21b94 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -49,6 +49,7 @@ #include class RAS_ICanvas; +class RAS_OffScreen; class RAS_IPolyMaterial; class RAS_MeshSlot; class RAS_DisplayArrayBucket; @@ -229,10 +230,7 @@ class RAS_IRasterizer RAS_STENCIL_BUFFER_BIT = 0x8 }; - enum OffScreen { - RAS_OFFSCREEN_COLOR = 0, - RAS_OFFSCREEN_DEPTH = 1, - + enum OffScreenType { RAS_OFFSCREEN_RENDER = 0, RAS_OFFSCREEN_FILTER0, RAS_OFFSCREEN_FILTER1, @@ -242,6 +240,9 @@ class RAS_IRasterizer RAS_OFFSCREEN_EYE_RIGHT1, RAS_OFFSCREEN_FINAL, RAS_OFFSCREEN_BLIT_DEPTH, + + RAS_OFFSCREEN_CUSTOM, + RAS_OFFSCREEN_MAX, }; @@ -256,7 +257,7 @@ class RAS_IRasterizer * \param index The input frame buffer, can be a non-filter frame buffer. * \return The output filter frame buffer. */ - static unsigned short NextFilterOffScreen(unsigned short index); + static OffScreenType NextFilterOffScreen(OffScreenType index); /** Return the output frame buffer normally used for the input frame buffer @@ -264,14 +265,14 @@ class RAS_IRasterizer * \param index The input eye frame buffer, can NOT be a non-eye frame buffer. * \return The output eye frame buffer. */ - static unsigned short NextEyeOffScreen(unsigned short index); + static OffScreenType NextEyeOffScreen(OffScreenType index); /** Return the output frame buffer normally used for the input frame buffer * index in case of simple render. * \param index The input render frame buffer, can NOT be a non-render frame buffer. * \return The output render frame buffer. */ - static unsigned short NextRenderOffScreen(unsigned short index); + static OffScreenType NextRenderOffScreen(OffScreenType index); /** * Enable capability @@ -356,49 +357,31 @@ class RAS_IRasterizer /// Update dimensions of all off screens. virtual void UpdateOffScreens(RAS_ICanvas *canvas) = 0; - /// Bind the off screen at the given index. - virtual void BindOffScreen(unsigned short index) = 0; + + /** Return the corresponding off screen to off screen type. + * \param type The off screen type to return. + */ + virtual RAS_OffScreen *GetOffScreen(OffScreenType type) = 0; /** Draw off screen without set viewport. * Used to copy the frame buffer object to another. * \param srcindex The input off screen index. * \param dstindex The output off screen index. */ - virtual void DrawOffScreen(unsigned short srcindex, unsigned short dstindex) = 0; + virtual void DrawOffScreen(RAS_OffScreen *srcOffScreen, RAS_OffScreen *dstOffScreen) = 0; /** Draw off screen at the given index to screen. * \param canvas The canvas containing the screen viewport. * \param index The off screen index to read from. */ - virtual void DrawOffScreen(RAS_ICanvas *canvas, unsigned short index) = 0; + virtual void DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen) = 0; /** Draw each stereo off screen to screen. * \param canvas The canvas containing the screen viewport. * \param lefteyeindex The left off screen index. * \param righteyeindex The right off screen index. */ - virtual void DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned short lefteyeindex, unsigned short righteyeindex) = 0; - - /** Bind the off screen texture at the given index and slot. - * \param index The off screen index. - * \param slot The texture slot to bind the texture. - * \param type The texture type: RAS_OFFSCREEN_COLOR or RAS_OFFSCREEN_DEPTH. - */ - virtual void BindOffScreenTexture(unsigned short index, unsigned short slot, OffScreen type) = 0; - - /** Unbind the off screen texture at the given index and slot. - * \param index The off screen index. - * \param type The texture type: RAS_OFFSCREEN_COLOR or RAS_OFFSCREEN_DEPTH. - */ - virtual void UnbindOffScreenTexture(unsigned short index, OffScreen type) = 0; - - virtual void MipmapOffScreenTexture(unsigned short index, OffScreen type) = 0; - virtual void UnmipmapOffScreenTexture(unsigned short index, OffScreen type) = 0; - - /// Return current off screen index. - virtual short GetCurrentOffScreenIndex() const = 0; - /// Return the off screenn samples numbers at the given index. - virtual int GetOffScreenSamples(unsigned short index) = 0; + virtual void DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen) = 0; /** * SetRenderArea sets the render area from the 2d canvas. @@ -720,7 +703,7 @@ class RAS_IRasterizer /** Set the current off screen depth to the global depth texture used by materials. * In case of mutlisample off screen a blit to RAS_OFFSCREEN_BLIT_DEPTH is procceed. */ - virtual void UpdateGlobalDepthTexture() = 0; + virtual void UpdateGlobalDepthTexture(RAS_OffScreen *offScreen) = 0; /// Set the global depth texture to an empty texture. virtual void ResetGlobalDepthTexture() = 0; diff --git a/source/gameengine/Rasterizer/RAS_OffScreen.cpp b/source/gameengine/Rasterizer/RAS_OffScreen.cpp new file mode 100644 index 000000000000..1d0f12855516 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OffScreen.cpp @@ -0,0 +1,132 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Tristan Porteries. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gameengine/Rasterizer/RAS_OffScreen.cpp + * \ingroup bgerast + */ + +#include "RAS_OffScreen.h" + +RAS_OffScreen *RAS_OffScreen::lastOffScreen = NULL; + +RAS_OffScreen::RAS_OffScreen(unsigned int width, unsigned int height, int samples, GPUHDRType hdrType, GPUOffScreenMode mode, char errOut[256], + RAS_IRasterizer::OffScreenType type) + :m_offScreen(GPU_offscreen_create(width, height, samples, hdrType, mode, errOut)), + m_type(type) +{ +} + +RAS_OffScreen::~RAS_OffScreen() +{ + GPU_offscreen_free(m_offScreen); +} + +bool RAS_OffScreen::GetValid() const +{ + return (m_offScreen != NULL); +} + +void RAS_OffScreen::Bind() +{ + GPU_offscreen_bind_simple(m_offScreen); + lastOffScreen = this; +} + +RAS_OffScreen *RAS_OffScreen::Blit(RAS_OffScreen *dstOffScreen, bool color, bool depth) +{ + GPU_offscreen_blit(m_offScreen, dstOffScreen->m_offScreen, color, depth); + + return dstOffScreen; +} + +void RAS_OffScreen::BindColorTexture(unsigned short slot) +{ + GPU_texture_bind(GPU_offscreen_texture(m_offScreen), slot); +} + +void RAS_OffScreen::BindDepthTexture(unsigned short slot) +{ + GPU_texture_bind(GPU_offscreen_depth_texture(m_offScreen), slot); +} + +void RAS_OffScreen::UnbindColorTexture() +{ + GPU_texture_unbind(GPU_offscreen_texture(m_offScreen)); +} + +void RAS_OffScreen::UnbindDepthTexture() +{ + GPU_texture_unbind(GPU_offscreen_depth_texture(m_offScreen)); +} + +void RAS_OffScreen::MipmapTexture() +{ + GPUTexture *tex = GPU_offscreen_texture(m_offScreen); + GPU_texture_filter_mode(tex, false, true, true); + GPU_texture_generate_mipmap(tex); +} + +void RAS_OffScreen::UnmipmapTexture() +{ + GPU_texture_filter_mode(GPU_offscreen_texture(m_offScreen), false, true, false); +} + +int RAS_OffScreen::GetColorBindCode() const +{ + return GPU_offscreen_color_texture(m_offScreen); +} + +int RAS_OffScreen::GetSamples() const +{ + return GPU_offscreen_samples(m_offScreen); +} + +unsigned int RAS_OffScreen::GetWidth() const +{ + return GPU_offscreen_width(m_offScreen); +} + +unsigned int RAS_OffScreen::GetHeight() const +{ + return GPU_offscreen_height(m_offScreen); +} + +RAS_IRasterizer::OffScreenType RAS_OffScreen::GetType() const +{ + return m_type; +} + +GPUTexture *RAS_OffScreen::GetDepthTexture() +{ + return GPU_offscreen_depth_texture(m_offScreen); +} + +RAS_OffScreen *RAS_OffScreen::GetLastOffScreen() +{ + return lastOffScreen; +} + +void RAS_OffScreen::RestoreScreen() +{ + GPU_framebuffer_restore(); + lastOffScreen = NULL; +} diff --git a/source/gameengine/Rasterizer/RAS_OffScreen.h b/source/gameengine/Rasterizer/RAS_OffScreen.h new file mode 100644 index 000000000000..c9eb6f9111cb --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OffScreen.h @@ -0,0 +1,80 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Tristan Porteries. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file RAS_OffScreen.h + * \ingroup bgerast + */ + +#ifndef __RAS_OFFSCREEN_H__ +#define __RAS_OFFSCREEN_H__ + +#include "RAS_IRasterizer.h" + +#include "GPU_framebuffer.h" + +struct GPUOffScreen; +struct GPUTexture; + +class RAS_OffScreen +{ +private: + /// All the off screens used. + GPUOffScreen *m_offScreen; + /// The off screen type, render, final, filter ect... + RAS_IRasterizer::OffScreenType m_type; + + /// The last bound off screen, set to NULL in RestoreScreen(). + static RAS_OffScreen *lastOffScreen; + +public: + RAS_OffScreen(unsigned int width, unsigned int height, int samples, GPUHDRType hdrType, GPUOffScreenMode mode, char errOut[256], + RAS_IRasterizer::OffScreenType type); + ~RAS_OffScreen(); + + bool GetValid() const; + + void Bind(); + /// NOTE: This function has the side effect to leave the destination off screen bound. + RAS_OffScreen *Blit(RAS_OffScreen *dstOffScreen, bool color, bool depth); + + void BindColorTexture(unsigned short slot); + void BindDepthTexture(unsigned short slot); + void UnbindColorTexture(); + void UnbindDepthTexture(); + + void MipmapTexture(); + void UnmipmapTexture(); + + int GetColorBindCode() const; + + int GetSamples() const; + unsigned GetWidth() const; + unsigned GetHeight() const; + RAS_IRasterizer::OffScreenType GetType() const; + + GPUTexture *GetDepthTexture(); + + static RAS_OffScreen *GetLastOffScreen(); + static void RestoreScreen(); +}; + +#endif // __RAS_OFFSCREEN_H__ diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index e80a0f0f8226..3fac805cfef4 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -37,6 +37,7 @@ #include "glew-mx.h" #include "RAS_ICanvas.h" +#include "RAS_OffScreen.h" #include "RAS_Rect.h" #include "RAS_ITexVert.h" #include "RAS_MeshObject.h" @@ -198,68 +199,15 @@ inline void RAS_OpenGLRasterizer::ScreenPlane::Render() } RAS_OpenGLRasterizer::OffScreens::OffScreens() - :m_currentIndex(-1), - m_width(0), + :m_width(0), m_height(0), - m_samples(-1), + m_samples(0), m_hdr(RAS_HDR_NONE) { - for (unsigned short i = 0; i < RAS_IRasterizer::RAS_OFFSCREEN_MAX; ++i) { - m_offScreens[i] = NULL; - } } RAS_OpenGLRasterizer::OffScreens::~OffScreens() { - for (unsigned short i = 0; i < RAS_IRasterizer::RAS_OFFSCREEN_MAX; ++i) { - if (m_offScreens[i]) { - GPU_offscreen_free(m_offScreens[i]); - } - } -} - -GPUOffScreen *RAS_OpenGLRasterizer::OffScreens::GetOffScreen(unsigned short index) -{ - const short lastIndex = m_currentIndex; - - if (!m_offScreens[index]) { - // The offscreen need to be created now. - - // Check if the off screen index can support samples. - const bool sampleofs = index == RAS_OFFSCREEN_RENDER || - index == RAS_OFFSCREEN_EYE_LEFT0 || - index == RAS_OFFSCREEN_EYE_RIGHT0; - - /* Some GPUs doesn't support high multisample value with GL_RGBA16F or GL_RGBA32F. - * To avoid crashing we check if the off screen was created and if not decremente - * the multisample value and try to create the off screen to find a supported value. - */ - for (int samples = m_samples; samples >= 0; --samples) { - // Get off screen mode : render buffer support for multisampled off screen. - int mode = GPU_OFFSCREEN_MODE_NONE; - if (sampleofs && (samples > 0)) { - mode = GPU_OFFSCREEN_RENDERBUFFER_COLOR | GPU_OFFSCREEN_RENDERBUFFER_DEPTH; - } - - char errout[256]; - GPUOffScreen *ofs = GPU_offscreen_create(m_width, m_height, sampleofs ? samples : 0, (GPUHDRType)m_hdr, mode, errout); - if (ofs) { - m_offScreens[index] = ofs; - m_samples = samples; - break; - } - } - - /* Creating an off screen restore the default frame buffer object. - * We have to rebind the last off screen. */ - if (lastIndex != -1) { - Bind(lastIndex); - } - } - - BLI_assert(lastIndex == m_currentIndex); - - return m_offScreens[index]; } inline void RAS_OpenGLRasterizer::OffScreens::Update(RAS_ICanvas *canvas) @@ -274,110 +222,66 @@ inline void RAS_OpenGLRasterizer::OffScreens::Update(RAS_ICanvas *canvas) m_width = width; m_height = height; - - // The samples value was not yet set. - if (m_samples == -1) { - m_samples = canvas->GetSamples(); - } - - // WARNING: Always respect the order from RAS_IRasterizer::HdrType. - static const int hdrEnums[] = { - GPU_HDR_NONE, // RAS_HDR_NONE - GPU_HDR_HALF_FLOAT, // RAS_HDR_HALF_FLOAT - GPU_HDR_FULL_FLOAT // RAS_HDR_FULL_FLOAT - }; - - m_hdr = hdrEnums[canvas->GetHdrType()]; + m_samples = canvas->GetSamples(); + m_hdr = canvas->GetHdrType(); // Destruct all off screens. for (unsigned short i = 0; i < RAS_IRasterizer::RAS_OFFSCREEN_MAX; ++i) { - if (m_offScreens[i]) { - GPU_offscreen_free(m_offScreens[i]); - m_offScreens[i] = NULL; - } + m_offScreens[i].reset(NULL); } } -inline void RAS_OpenGLRasterizer::OffScreens::Bind(unsigned short index) +inline RAS_OffScreen *RAS_OpenGLRasterizer::OffScreens::GetOffScreen(OffScreenType type) { - GPU_offscreen_bind_simple(GetOffScreen(index)); - - m_currentIndex = index; -} - -inline void RAS_OpenGLRasterizer::OffScreens::RestoreScreen() -{ - GPU_framebuffer_restore(); + if (!m_offScreens[type]) { + // The offscreen need to be created now. - m_currentIndex = -1; -} + // Check if the off screen type can support samples. + const bool sampleofs = type == RAS_OFFSCREEN_RENDER || + type == RAS_OFFSCREEN_EYE_LEFT0 || + type == RAS_OFFSCREEN_EYE_RIGHT0; -inline void RAS_OpenGLRasterizer::OffScreens::Blit(unsigned short srcindex, unsigned short dstindex, bool color, bool depth) -{ - GPU_offscreen_blit(GetOffScreen(srcindex), GetOffScreen(dstindex), color, depth); -} - -inline void RAS_OpenGLRasterizer::OffScreens::BindTexture(unsigned short index, unsigned short slot, OffScreen type) -{ - GPUTexture *tex = NULL; - GPUOffScreen *ofs = GetOffScreen(index); - if (type == RAS_IRasterizer::RAS_OFFSCREEN_COLOR) { - tex = GPU_offscreen_texture(ofs); - } - else if (type == RAS_IRasterizer::RAS_OFFSCREEN_DEPTH) { - tex = GPU_offscreen_depth_texture(ofs); - } - GPU_texture_bind(tex, slot); -} + /* Some GPUs doesn't support high multisample value with GL_RGBA16F or GL_RGBA32F. + * To avoid crashing we check if the off screen was created and if not decremente + * the multisample value and try to create the off screen to find a supported value. + */ + for (int samples = m_samples; samples >= 0; --samples) { + // Get off screen mode : render buffer support for multisampled off screen. + GPUOffScreenMode mode = GPU_OFFSCREEN_MODE_NONE; + if (sampleofs && (samples > 0)) { + mode = (GPUOffScreenMode)(GPU_OFFSCREEN_RENDERBUFFER_COLOR | GPU_OFFSCREEN_RENDERBUFFER_DEPTH); + } -inline void RAS_OpenGLRasterizer::OffScreens::UnbindTexture(unsigned short index, OffScreen type) -{ - GPUTexture *tex = NULL; - GPUOffScreen *ofs = GetOffScreen(index); - if (type == RAS_IRasterizer::RAS_OFFSCREEN_COLOR) { - tex = GPU_offscreen_texture(ofs); - } - else if (type == RAS_IRasterizer::RAS_OFFSCREEN_DEPTH) { - tex = GPU_offscreen_depth_texture(ofs); - } - GPU_texture_unbind(tex); -} + // WARNING: Always respect the order from RAS_IRasterizer::HdrType. + static const GPUHDRType hdrEnums[] = { + GPU_HDR_NONE, // RAS_HDR_NONE + GPU_HDR_HALF_FLOAT, // RAS_HDR_HALF_FLOAT + GPU_HDR_FULL_FLOAT // RAS_HDR_FULL_FLOAT + }; + + RAS_OffScreen *ofs = new RAS_OffScreen(m_width, m_height, sampleofs ? samples : 0, hdrEnums[m_hdr], mode, NULL, type); + if (!ofs->GetValid()) { + delete ofs; + continue; + } -inline void RAS_OpenGLRasterizer::OffScreens::MipmapTexture(unsigned short index, OffScreen type) -{ - GPUOffScreen *ofs = GetOffScreen(index); - if (type == RAS_IRasterizer::RAS_OFFSCREEN_COLOR) { - GPUTexture *tex = GPU_offscreen_texture(ofs); - GPU_texture_filter_mode(tex, false, true, true); - GPU_texture_generate_mipmap(tex); - } -} + m_offScreens[type].reset(ofs); + m_samples = samples; + break; + } -inline void RAS_OpenGLRasterizer::OffScreens::UnmipmapTexture(unsigned short index, OffScreen type) -{ - GPUOffScreen *ofs = GetOffScreen(index); - if (type == RAS_IRasterizer::RAS_OFFSCREEN_COLOR) { - GPUTexture *tex = GPU_offscreen_texture(ofs); - GPU_texture_filter_mode(tex, false, true, false); + /* Creating an off screen restore the default frame buffer object. + * We have to rebind the last off screen. */ + RAS_OffScreen *lastOffScreen = RAS_OffScreen::GetLastOffScreen(); + if (lastOffScreen) { + lastOffScreen->Bind(); + } } -} -inline short RAS_OpenGLRasterizer::OffScreens::GetCurrentIndex() const -{ - return m_currentIndex; -} - -inline int RAS_OpenGLRasterizer::OffScreens::GetSamples(unsigned short index) -{ - return GPU_offscreen_samples(GetOffScreen(index)); -} - -inline GPUTexture *RAS_OpenGLRasterizer::OffScreens::GetDepthTexture(unsigned short index) -{ - return GPU_offscreen_depth_texture(GetOffScreen(index)); + return m_offScreens[type].get(); } -unsigned short RAS_IRasterizer::NextFilterOffScreen(unsigned short index) +RAS_IRasterizer::OffScreenType RAS_IRasterizer::NextFilterOffScreen(RAS_IRasterizer::OffScreenType index) { switch (index) { case RAS_OFFSCREEN_FILTER0: @@ -385,16 +289,15 @@ unsigned short RAS_IRasterizer::NextFilterOffScreen(unsigned short index) return RAS_OFFSCREEN_FILTER1; } case RAS_OFFSCREEN_FILTER1: + // Passing a non-filter frame buffer is allowed. + default: { return RAS_OFFSCREEN_FILTER0; } } - - // Passing a non-filter frame buffer is allowed. - return RAS_OFFSCREEN_FILTER0; } -unsigned short RAS_IRasterizer::NextEyeOffScreen(unsigned short index) +RAS_IRasterizer::OffScreenType RAS_IRasterizer::NextEyeOffScreen(RAS_IRasterizer::OffScreenType index) { switch (index) { case RAS_OFFSCREEN_EYE_LEFT0: @@ -413,15 +316,16 @@ unsigned short RAS_IRasterizer::NextEyeOffScreen(unsigned short index) { return RAS_OFFSCREEN_EYE_RIGHT0; } + // Passing a non-eye frame buffer is disallowed. + default: + { + BLI_assert(false); + return RAS_OFFSCREEN_EYE_LEFT0; + } } - - // Passing a non-eye frame buffer is disallowed. - BLI_assert(false); - - return RAS_OFFSCREEN_EYE_LEFT0; } -unsigned short RAS_IRasterizer::NextRenderOffScreen(unsigned short index) +RAS_IRasterizer::OffScreenType RAS_IRasterizer::NextRenderOffScreen(RAS_IRasterizer::OffScreenType index) { switch (index) { case RAS_OFFSCREEN_FINAL: @@ -432,12 +336,13 @@ unsigned short RAS_IRasterizer::NextRenderOffScreen(unsigned short index) { return RAS_OFFSCREEN_FINAL; } + // Passing a non-render frame buffer is disallowed. + default: + { + BLI_assert(false); + return RAS_OFFSCREEN_RENDER; + } } - - // Passing a non-render frame buffer is disallowed. - BLI_assert(false); - - return RAS_OFFSCREEN_RENDER; } RAS_OpenGLRasterizer::RAS_OpenGLRasterizer() @@ -946,15 +851,18 @@ void RAS_OpenGLRasterizer::UpdateOffScreens(RAS_ICanvas *canvas) m_offScreens.Update(canvas); } -void RAS_OpenGLRasterizer::BindOffScreen(unsigned short index) +RAS_OffScreen *RAS_OpenGLRasterizer::GetOffScreen(OffScreenType type) { - m_offScreens.Bind(index); + return m_offScreens.GetOffScreen(type); } -void RAS_OpenGLRasterizer::DrawOffScreen(unsigned short srcindex, unsigned short dstindex) +void RAS_OpenGLRasterizer::DrawOffScreen(RAS_OffScreen *srcOffScreen, RAS_OffScreen *dstOffScreen) { - if (m_offScreens.GetSamples(srcindex) == 0) { - m_offScreens.BindTexture(srcindex, 0, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + if (srcOffScreen->GetSamples() > 0) { + srcOffScreen->Blit(dstOffScreen, true, true); + } + else { + srcOffScreen->BindColorTexture(0); GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_DRAW_FRAME_BUFFER); GPU_shader_bind(shader); @@ -966,18 +874,14 @@ void RAS_OpenGLRasterizer::DrawOffScreen(unsigned short srcindex, unsigned short GPU_shader_unbind(); - m_offScreens.UnbindTexture(srcindex, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); - } - else { - m_offScreens.Blit(srcindex, dstindex, true, true); + srcOffScreen->UnbindColorTexture(); } } -void RAS_OpenGLRasterizer::DrawOffScreen(RAS_ICanvas *canvas, unsigned short index) +void RAS_OpenGLRasterizer::DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen) { - if (m_offScreens.GetSamples(index) > 0) { - m_offScreens.Blit(index, RAS_OFFSCREEN_FINAL, true, false); - index = RAS_OFFSCREEN_FINAL; + if (offScreen->GetSamples() > 0) { + offScreen = offScreen->Blit(GetOffScreen(RAS_OFFSCREEN_FINAL), true, false); } const int *viewport = canvas->GetViewPort(); @@ -987,25 +891,23 @@ void RAS_OpenGLRasterizer::DrawOffScreen(RAS_ICanvas *canvas, unsigned short ind Disable(RAS_CULL_FACE); SetDepthFunc(RAS_ALWAYS); - m_offScreens.RestoreScreen(); - DrawOffScreen(index, 0); + RAS_OffScreen::RestoreScreen(); + DrawOffScreen(offScreen, NULL); SetDepthFunc(RAS_LEQUAL); Enable(RAS_CULL_FACE); } -void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned short lefteyeindex, unsigned short righteyeindex) +void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen) { - if (m_offScreens.GetSamples(lefteyeindex) > 0) { - // Then lefteyeindex == RAS_OFFSCREEN_EYE_LEFT0. - m_offScreens.Blit(RAS_OFFSCREEN_EYE_LEFT0, RAS_OFFSCREEN_EYE_LEFT1, true, false); - lefteyeindex = RAS_OFFSCREEN_EYE_LEFT1; + if (leftOffScreen->GetSamples() > 0) { + // Then leftOffScreen == RAS_OFFSCREEN_EYE_LEFT0. + leftOffScreen = leftOffScreen->Blit(GetOffScreen(RAS_OFFSCREEN_EYE_LEFT1), true, false); } - if (m_offScreens.GetSamples(righteyeindex) > 0) { - // Then righteyeindex == RAS_OFFSCREEN_EYE_RIGHT0. - m_offScreens.Blit(RAS_OFFSCREEN_EYE_RIGHT0, RAS_OFFSCREEN_EYE_RIGHT1, true, false); - righteyeindex = RAS_OFFSCREEN_EYE_RIGHT1; + if (rightOffScreen->GetSamples() > 0) { + // Then rightOffScreen == RAS_OFFSCREEN_EYE_RIGHT0. + rightOffScreen = rightOffScreen->Blit(GetOffScreen(RAS_OFFSCREEN_EYE_RIGHT1), true, false); } const int *viewport = canvas->GetViewPort(); @@ -1015,7 +917,7 @@ void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned sho Disable(RAS_CULL_FACE); SetDepthFunc(RAS_ALWAYS); - m_offScreens.RestoreScreen(); + RAS_OffScreen::RestoreScreen(); if (m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED) { GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_STIPPLE); @@ -1023,8 +925,8 @@ void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned sho OverrideShaderStereoStippleInterface *interface = (OverrideShaderStereoStippleInterface *)GPU_shader_get_interface(shader); - m_offScreens.BindTexture(lefteyeindex, 0, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); - m_offScreens.BindTexture(righteyeindex, 1, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + leftOffScreen->BindColorTexture(0); + rightOffScreen->BindColorTexture(1); GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); @@ -1034,8 +936,8 @@ void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned sho GPU_shader_unbind(); - m_offScreens.UnbindTexture(lefteyeindex, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); - m_offScreens.UnbindTexture(righteyeindex, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + leftOffScreen->UnbindColorTexture(); + rightOffScreen->UnbindColorTexture(); } else if (m_stereomode == RAS_STEREO_ANAGLYPH) { GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_ANAGLYPH); @@ -1043,8 +945,8 @@ void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned sho OverrideShaderStereoAnaglyph *interface = (OverrideShaderStereoAnaglyph *)GPU_shader_get_interface(shader); - m_offScreens.BindTexture(lefteyeindex, 0, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); - m_offScreens.BindTexture(righteyeindex, 1, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + leftOffScreen->BindColorTexture(0); + rightOffScreen->BindColorTexture(1); GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); @@ -1053,44 +955,14 @@ void RAS_OpenGLRasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned sho GPU_shader_unbind(); - m_offScreens.UnbindTexture(lefteyeindex, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); - m_offScreens.UnbindTexture(righteyeindex, RAS_IRasterizer::RAS_OFFSCREEN_COLOR); + leftOffScreen->UnbindColorTexture(); + rightOffScreen->UnbindColorTexture(); } SetDepthFunc(RAS_LEQUAL); Enable(RAS_CULL_FACE); } -void RAS_OpenGLRasterizer::BindOffScreenTexture(unsigned short index, unsigned short slot, OffScreen type) -{ - m_offScreens.BindTexture(index, slot, type); -} - -void RAS_OpenGLRasterizer::UnbindOffScreenTexture(unsigned short index, OffScreen type) -{ - m_offScreens.UnbindTexture(index, type); -} - -void RAS_OpenGLRasterizer::MipmapOffScreenTexture(unsigned short index, OffScreen type) -{ - m_offScreens.MipmapTexture(index, type); -} - -void RAS_OpenGLRasterizer::UnmipmapOffScreenTexture(unsigned short index, OffScreen type) -{ - m_offScreens.UnmipmapTexture(index, type); -} - -short RAS_OpenGLRasterizer::GetCurrentOffScreenIndex() const -{ - return m_offScreens.GetCurrentIndex(); -} - -int RAS_OpenGLRasterizer::GetOffScreenSamples(unsigned short index) -{ - return m_offScreens.GetSamples(index); -} - void RAS_OpenGLRasterizer::SetRenderArea(RAS_ICanvas *canvas) { if (canvas == NULL) { @@ -2335,17 +2207,19 @@ void RAS_OpenGLRasterizer::LoadIdentity() glLoadIdentity(); } -void RAS_OpenGLRasterizer::UpdateGlobalDepthTexture() +void RAS_OpenGLRasterizer::UpdateGlobalDepthTexture(RAS_OffScreen *offScreen) { - unsigned short index = m_offScreens.GetCurrentIndex(); - if (m_offScreens.GetSamples(index)) { - m_offScreens.Blit(index, RAS_IRasterizer::RAS_OFFSCREEN_BLIT_DEPTH, false, true); + /* In case of multisamples the depth off screen must be blit to be used in shader. + * But the original off screen must be kept bound after the blit. */ + if (offScreen->GetSamples()) { + RAS_OffScreen *dstOffScreen = GetOffScreen(RAS_IRasterizer::RAS_OFFSCREEN_BLIT_DEPTH); + offScreen->Blit(dstOffScreen, false, true); // Restore original off screen. - m_offScreens.Bind(index); - index = RAS_IRasterizer::RAS_OFFSCREEN_BLIT_DEPTH; + offScreen->Bind(); + offScreen = dstOffScreen; } - GPU_texture_set_global_depth(m_offScreens.GetDepthTexture(index)); + GPU_texture_set_global_depth(offScreen->GetDepthTexture()); } void RAS_OpenGLRasterizer::ResetGlobalDepthTexture() diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 6a3505621a56..87e756476ed5 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -49,8 +49,6 @@ class RAS_StorageVBO; class RAS_ICanvas; class RAS_OpenGLLight; -struct GPUOffScreen; -struct GPUTexture; struct GPUShader; /** @@ -80,43 +78,21 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer void Render(); }; - /// Internal manager of off screens. class OffScreens { private: - /// All the off screens used. - GPUOffScreen *m_offScreens[RAS_OFFSCREEN_MAX]; - /// The current off screen index. - short m_currentIndex; - - /// The last width. + std::unique_ptr m_offScreens[RAS_OFFSCREEN_MAX]; unsigned int m_width; - /// The last height. unsigned int m_height; - /// The number of wanted/supported samples. int m_samples; - /// The HDR quality. - short m_hdr; - - /// Return or create off screen for the given index. - GPUOffScreen *GetOffScreen(unsigned short index); + HdrType m_hdr; public: OffScreens(); ~OffScreens(); void Update(RAS_ICanvas *canvas); - void Bind(unsigned short index); - void RestoreScreen(); - /// NOTE: This function has the side effect to leave the destination off screen bound. - void Blit(unsigned short srcindex, unsigned short dstindex, bool color, bool depth); - void BindTexture(unsigned short index, unsigned short slot, OffScreen type); - void UnbindTexture(unsigned short index, OffScreen type); - void MipmapTexture(unsigned short index, OffScreen type); - void UnmipmapTexture(unsigned short index, OffScreen type); - short GetCurrentIndex() const; - int GetSamples(unsigned short index); - GPUTexture *GetDepthTexture(unsigned short index); + RAS_OffScreen *GetOffScreen(RAS_IRasterizer::OffScreenType type); }; struct DebugShape @@ -233,13 +209,12 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer /// Class used to render a screen plane. ScreenPlane m_screenPlane; + /// Class used to manage off screens used by the rasterizer. + OffScreens m_offScreens; // We store each debug shape by scene. std::map m_debugShapes; - /// Class used to manage off screens. - OffScreens m_offScreens; - protected: DrawType m_drawingmode; ShadowType m_shadowMode; @@ -285,16 +260,10 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer virtual void EndFrame(); virtual void UpdateOffScreens(RAS_ICanvas *canvas); - virtual void BindOffScreen(unsigned short index); - virtual void DrawOffScreen(unsigned short srcindex, unsigned short dstindex); - virtual void DrawOffScreen(RAS_ICanvas *canvas, unsigned short index); - virtual void DrawStereoOffScreen(RAS_ICanvas *canvas, unsigned short lefteyeindex, unsigned short righteyeindex); - virtual void BindOffScreenTexture(unsigned short index, unsigned short slot, OffScreen type); - virtual void UnbindOffScreenTexture(unsigned short index, OffScreen type); - virtual void MipmapOffScreenTexture(unsigned short index, OffScreen type); - virtual void UnmipmapOffScreenTexture(unsigned short index, OffScreen type); - virtual short GetCurrentOffScreenIndex() const; - virtual int GetOffScreenSamples(unsigned short index); + virtual RAS_OffScreen *GetOffScreen(OffScreenType type); + virtual void DrawOffScreen(RAS_OffScreen *srcOffScreen, RAS_OffScreen *dstOffScreen); + virtual void DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen); + virtual void DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen); virtual void SetRenderArea(RAS_ICanvas *canvas); @@ -452,7 +421,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer void RemoveLight(RAS_ILightObject *lightobject); int ApplyLights(int objectlayer, const MT_Transform& viewmat); - virtual void UpdateGlobalDepthTexture(); + virtual void UpdateGlobalDepthTexture(RAS_OffScreen *offScreen); virtual void ResetGlobalDepthTexture(); void MotionBlur(); diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 861d3380fdb5..703c7a666cf9 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -42,6 +42,7 @@ #include "KX_Globals.h" #include "DNA_scene_types.h" +#include "RAS_OffScreen.h" #include "RAS_CameraData.h" #include "RAS_MeshObject.h" #include "RAS_Polygon.h" @@ -75,8 +76,6 @@ ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera, unsigned int widt m_camera(camera), m_owncamera(false), m_samples(samples), - m_offScreen(NULL), - m_blitOffScreen(NULL), m_finalOffScreen(NULL), m_sync(NULL), m_observer(NULL), @@ -107,13 +106,13 @@ ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera, unsigned int widt m_internalFormat = GL_RGBA8; } - m_offScreen = GPU_offscreen_create(m_width, m_height, m_samples, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL); + m_offScreen.reset(new RAS_OffScreen(m_width, m_height, m_samples, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL, RAS_IRasterizer::RAS_OFFSCREEN_CUSTOM)); if (m_samples > 0) { - m_blitOffScreen = GPU_offscreen_create(m_width, m_height, 0, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL); - m_finalOffScreen = m_blitOffScreen; + m_blitOffScreen.reset(new RAS_OffScreen(m_width, m_height, 0, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL, RAS_IRasterizer::RAS_OFFSCREEN_CUSTOM)); + m_finalOffScreen = m_blitOffScreen.get(); } else { - m_finalOffScreen = m_offScreen; + m_finalOffScreen = m_offScreen.get(); } } @@ -127,18 +126,11 @@ ImageRender::~ImageRender (void) if (m_sync) delete m_sync; #endif - - if (m_offScreen) { - GPU_offscreen_free(m_offScreen); - } - if (m_blitOffScreen) { - GPU_offscreen_free(m_blitOffScreen); - } } int ImageRender::GetColorBindCode() const { - return GPU_offscreen_color_texture(m_finalOffScreen); + return m_finalOffScreen->GetColorBindCode(); } // get update shadow buffer @@ -217,14 +209,14 @@ void ImageRender::calcViewport (unsigned int texId, double ts, unsigned int form } } - GPU_offscreen_bind_simple(m_finalOffScreen); + m_finalOffScreen->Bind(); // wait until all render operations are completed WaitSync(); // get image from viewport (or FBO) ImageViewport::calcViewport(texId, ts, format); - GPU_framebuffer_restore(); + RAS_OffScreen::RestoreScreen(); } bool ImageRender::Render() @@ -314,7 +306,7 @@ bool ImageRender::Render() // The screen area that ImageViewport will copy is also the rendering zone // bind the fbo and set the viewport to full size - GPU_offscreen_bind_simple(m_offScreen); + m_offScreen->Bind(); m_rasterizer->BeginFrame(m_engine->GetClockTime()); @@ -427,7 +419,7 @@ bool ImageRender::Render() m_engine->UpdateAnimations(m_scene); - m_scene->RenderBuckets(camtrans, m_rasterizer); + m_scene->RenderBuckets(camtrans, m_rasterizer, m_offScreen.get()); // restore the canvas area now that the render is completed m_canvas->GetWindowArea() = area; @@ -435,7 +427,7 @@ bool ImageRender::Render() // In case multisample is active, blit the FBO if (m_samples > 0) { - GPU_offscreen_blit(m_offScreen, m_blitOffScreen, true, true); + m_offScreen->Blit(m_blitOffScreen.get(), true, true); } #ifdef WITH_GAMEENGINE_GPU_SYNC @@ -472,7 +464,7 @@ void ImageRender::WaitSync() #endif // this is needed to finalize the image if the target is a texture - GPU_texture_generate_mipmap(GPU_offscreen_texture(m_finalOffScreen)); + m_finalOffScreen->MipmapTexture(); // all rendered operation done and complete, invalidate render for next time m_done = false; @@ -881,8 +873,6 @@ ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObjec m_done(false), m_scene(scene), m_samples(samples), - m_offScreen(NULL), - m_blitOffScreen(NULL), m_finalOffScreen(NULL), m_sync(NULL), m_observer(observer), @@ -903,13 +893,13 @@ ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObjec m_internalFormat = GL_RGBA8; } - m_offScreen = GPU_offscreen_create(m_width, m_height, m_samples, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL); + m_offScreen.reset(new RAS_OffScreen(m_width, m_height, m_samples, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL, RAS_IRasterizer::RAS_OFFSCREEN_CUSTOM)); if (m_samples > 0) { - m_blitOffScreen = GPU_offscreen_create(m_width, m_height, 0, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL); - m_finalOffScreen = m_blitOffScreen; + m_blitOffScreen.reset(new RAS_OffScreen(m_width, m_height, 0, type, GPU_OFFSCREEN_RENDERBUFFER_DEPTH, NULL, RAS_IRasterizer::RAS_OFFSCREEN_CUSTOM)); + m_finalOffScreen = m_blitOffScreen.get(); } else { - m_finalOffScreen = m_offScreen; + m_finalOffScreen = m_offScreen.get(); } // this constructor is used for automatic planar mirror diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index 1e06c4a36a9d..91ec68ed09f3 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -43,7 +43,7 @@ #include "ImageViewport.h" -struct GPUOffScreen; +class RAS_OffScreen; /// class for render 3d scene class ImageRender : public ImageViewport @@ -105,13 +105,13 @@ class ImageRender : public ImageViewport int m_samples; /// The rendered off screen, can be multisampled. - GPUOffScreen *m_offScreen; + std::unique_ptr m_offScreen; /// The non multisampled off screen used when bliting, can be NULL. - GPUOffScreen *m_blitOffScreen; + std::unique_ptr m_blitOffScreen; /** The pointer to the final off screen without multisamples, can * be m_offScreen or m_blitOffScreen in case of mutlisamples. */ - GPUOffScreen *m_finalOffScreen; + RAS_OffScreen *m_finalOffScreen; /// object to synchronize render even if no buffer transfer RAS_ISync *m_sync;