Explorar o código

Resolve multisampled backbuffer for postprocessing. Not yet implemented on OpenGL.

Lasse Öörni %!s(int64=14) %!d(string=hai) anos
pai
achega
5541fc9d87

+ 21 - 0
Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -614,6 +614,27 @@ void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned s
     impl_->device_->Clear(0, 0, d3dFlags, GetD3DColor(color), depth, stencil);
 }
 
+bool Graphics::ResolveToTexture(Texture2D* destination, const IntRect& viewport)
+{
+    if (!destination || destination->GetUsage() != TEXTURE_RENDERTARGET)
+        return false;
+    
+    IntRect vpCopy = viewport;
+    if (vpCopy.right_ <= vpCopy.left_)
+        vpCopy.right_ = vpCopy.left_ + 1;
+    if (vpCopy.bottom_ <= vpCopy.top_)
+        vpCopy.bottom_ = vpCopy.top_ + 1;
+    
+    RECT rect;
+    rect.left = Clamp(vpCopy.left_, 0, width_);
+    rect.top = Clamp(vpCopy.top_, 0, height_);
+    rect.right = Clamp(vpCopy.right_, 0, width_);
+    rect.bottom = Clamp(vpCopy.bottom_, 0, height_);
+    
+    return SUCCEEDED(impl_->device_->StretchRect(impl_->defaultColorSurface_, &rect,
+        (IDirect3DSurface9*)destination->GetRenderSurface()->GetSurface(), &rect, D3DTEXF_NONE));
+}
+
 void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount)
 {
     if (!vertexCount)

+ 7 - 6
Engine/Graphics/Direct3D9/D3D9Graphics.h

@@ -63,25 +63,26 @@ public:
     
     /// %Set window title.
     void SetWindowTitle(const String& windowTitle);
-    /// %Set screen mode.
+    /// %Set screen mode. Return true if successful.
     bool SetMode(int width, int height, bool fullscreen, bool vsync, bool tripleBuffer, int multiSample);
-    /// %Set screen resolution only.
+    /// %Set screen resolution only. Return true if successful.
     bool SetMode(int width, int height);
-    /// Toggle between full screen and windowed mode.
+    /// Toggle between full screen and windowed mode. Return true if successful.
     bool ToggleFullscreen();
     /// Close the window.
     void Close();
-    /// Take a screenshot.
+    /// Take a screenshot. Return true if successful.
     bool TakeScreenShot(Image& destImage);
     /// %Set whether to flush GPU command queue at the end of each frame. Default true.
     void SetFlushGPU(bool enable);
-    
-    /// Begin frame rendering.
+    /// Begin frame rendering. Return true if device available and can render.
     bool BeginFrame();
     /// End frame rendering and swap buffers.
     void EndFrame();
     /// Clear any or all of rendertarget, depth buffer and stencil buffer.
     void Clear(unsigned flags, const Color& color = Color(0.0f, 0.0f, 0.0f, 0.0f), float depth = 1.0f, unsigned stencil = 0);
+    /// Resolve multisampled backbuffer to a texture rendertarget.
+    bool ResolveToTexture(Texture2D* destination, const IntRect& viewport);
     /// Draw non-indexed geometry.
     void Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount);
     /// Draw indexed geometry.

+ 5 - 0
Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -437,6 +437,11 @@ void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned s
     SetDepthWrite(oldDepthWrite);
 }
 
+bool Graphics::ResolveToTexture(Texture2D* destination, const IntRect& viewport)
+{
+    /// \todo Implement
+}
+
 void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount)
 {
     if (!vertexCount)

+ 5 - 3
Engine/Graphics/OpenGL/OGLGraphics.h

@@ -82,9 +82,9 @@ public:
     
     /// Set window title.
     void SetWindowTitle(const String& windowTitle);
-    /// Set screen mode.
+    /// Set screen mode. Return true if successful.
     bool SetMode(int width, int height, bool fullscreen, bool vsync, bool tripleBuffer, int multiSample);
-    /// Set screen resolution only.
+    /// Set screen resolution only. Return true if successful.
     bool SetMode(int width, int height);
     /// Toggle between full screen and windowed mode.
     bool ToggleFullscreen();
@@ -94,12 +94,14 @@ public:
     bool TakeScreenShot(Image& destImage);
     /// Set whether to flush GPU command queue at the end of each frame. Default true.
     void SetFlushGPU(bool enable);
-    /// Begin frame rendering.
+    /// Begin frame rendering. Return true if device available and can render.
     bool BeginFrame();
     /// End frame rendering and swap buffers.
     void EndFrame();
     /// Clear any or all of rendertarget, depth buffer and stencil buffer.
     void Clear(unsigned flags, const Color& color = Color(0.0f, 0.0f, 0.0f, 0.0f), float depth = 1.0f, unsigned stencil = 0);
+    /// Resolve multisampled backbuffer to a texture rendertarget.
+    bool ResolveToTexture(Texture2D* destination, const IntRect& viewport);
     /// Draw non-indexed geometry.
     void Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount);
     /// Draw indexed geometry.

+ 2 - 2
Engine/Graphics/Renderer.cpp

@@ -922,7 +922,7 @@ RenderSurface* Renderer::GetDepthStencil(int width, int height)
 {
     // Return the default depth-stencil surface if applicable
     // (when using OpenGL Graphics will allocate right size surfaces on demand to emulate Direct3D9)
-    if (width <= graphics_->GetWidth() && height <= graphics_->GetHeight())
+    if (width <= graphics_->GetWidth() && height <= graphics_->GetHeight() && graphics_->GetMultiSample() <= 1)
         return 0;
     else
         return GetScreenBuffer(width, height, Graphics::GetDepthStencilFormat())->GetRenderSurface();
@@ -1223,7 +1223,7 @@ void Renderer::RemoveUnusedBuffers()
             occlusionBuffers_.Erase(i);
         }
     }
-    
+    
     for (HashMap<long long, Vector<SharedPtr<Texture2D> > >::Iterator i = screenBuffers_.Begin(); i != screenBuffers_.End();)
     {
         HashMap<long long, Vector<SharedPtr<Texture2D> > >::Iterator current = i++;

+ 16 - 13
Engine/Graphics/View.cpp

@@ -319,11 +319,19 @@ void View::Render()
     #endif
     
     graphics_->SetViewTexture(0);
-    
     graphics_->SetScissorTest(false);
     graphics_->SetStencilTest(false);
     graphics_->ResetStreamFrequencies();
     
+    // Run post-processes or framebuffer blitting now
+    if (screenBuffers_.Size())
+    {
+        if (postProcesses_->Size())
+            RunPostProcesses();
+        else
+            BlitFramebuffer();
+    }
+    
     // If this is a main view, draw the associated debug geometry now
     if (!renderTarget_)
     {
@@ -339,15 +347,6 @@ void View::Render()
         }
     }
     
-    // Run post-processes or framebuffer blitting now
-    if (screenBuffers_.Size())
-    {
-        if (postProcesses_->Size())
-            RunPostProcesses();
-        else
-            BlitFramebuffer();
-    }
-    
     // "Forget" the camera, octree and zone after rendering
     camera_ = 0;
     octree_ = 0;
@@ -973,7 +972,9 @@ void View::RenderBatchesForward()
     // Reset the light optimization stencil reference value
     lightStencilValue_ = 1;
     
-    RenderSurface* renderTarget = screenBuffers_.Size() ? screenBuffers_[0]->GetRenderSurface() : renderTarget_;
+    // If using hardware multisampling with post-processing, render to the backbuffer first and then resolve
+    bool resolve = screenBuffers_.Size() && !renderTarget_ && graphics_->GetMultiSample() > 1;
+    RenderSurface* renderTarget = (screenBuffers_.Size() && !resolve) ? screenBuffers_[0]->GetRenderSurface() : renderTarget_;
     RenderSurface* depthStencil = GetDepthStencil(renderTarget);
     
     // If not reusing shadowmaps, render all of them first
@@ -1050,6 +1051,10 @@ void View::RenderBatchesForward()
         
         RenderBatchQueue(postAlphaQueue_);
     }
+    
+    // Resolve multisampled backbuffer now if necessary
+    if (resolve)
+        graphics_->ResolveToTexture(screenBuffers_[0], viewRect_);
 }
 
 void View::RenderBatchesLightPrepass()
@@ -2502,5 +2507,3 @@ RenderSurface* View::GetDepthStencil(RenderSurface* renderTarget)
         depthStencil = renderer_->GetDepthStencil(renderTarget->GetWidth(), renderTarget->GetHeight());
     return depthStencil;
 }
-
-

+ 1 - 0
Engine/Resource/ResourceCache.cpp

@@ -40,6 +40,7 @@ static const String checkDirs[] = {
     "Music",
     "Objects",
     "Particle",
+    "PostProcess",
     "Scenes",
     "Scripts",
     "Sounds",